程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#向無窗口的過程發送新聞

C#向無窗口的過程發送新聞

編輯:C#入門知識

C#向無窗口的過程發送新聞。本站提示廣大學習愛好者:(C#向無窗口的過程發送新聞)文章只能為提供參考,不一定能成為您想要的結果。以下是C#向無窗口的過程發送新聞正文


注:本文實用.net2.0+的winform法式
一個winform法式,我願望它不克不及多開,那末在用戶啟動第二個實例的時刻,作為第二個實例來講,年夜概可以有這麼幾種做法:

1.彈個窗告訴用戶【法式已運轉】之類,用戶點擊彈窗後,加入本身

2.甚麼都不做,默默加入本身

3.讓已運轉的第一個實例把它的窗體顯示出來,完了加入本身

明顯第3種做法更地道,完成該後果的焦點成績實際上是:若何顯示指定過程的窗口?

起首想到的是挪用ShowWindow、SetForegroundWindow等API,合營應用可以將被遮擋、最小化的窗口前排顯示出來,這也是許多觸及到這類案例的網文引見的辦法,此法的局限在於,目的過程的主窗口必需存在,精確說是要有有用的主窗口句柄,表示在拜訪Process.MainWindowHandle能獲得一個非IntPtr.Zero的值,即有用的句柄;或許用spy類對象能看到該過程下有至多一個窗口;或許按alt+tab能將它的窗口切換出來。

那假如過程沒窗口怎樣辦?先說一下甚麼情形下過程會沒窗口,很簡略,讓Form.Visible=false(或許Form.Hide(),等價的)就行,此時窗體就消逝了,既弗成見,也沒有對應的義務欄按鈕,alt+tab也切不出來。當法式中的一切Form都Hide後,拜訪該過程的MainWindowHandle會獲得IntPtr.Zero,這就是無窗口過程。那甚麼樣的法式會這麼干,太多了好吧,各類音樂播放器,殺軟甚麼的,都許可【封閉/最小化到體系托盤】,在你點叉或許最小化後,窗體就會隱蔽,只留一個圖標在托盤區。因為這類過程的MainWindowHandle拿不到有用句柄,所以下面那些API是用不了的,只能另想方法。

回到成績【若何顯示指定過程的窗口】,假如你的法式不許可封閉到托盤區,一直存在窗口的話(最小化也是存在),那你高興的用ShowWindow、SetForegroundWindow等API就好,不消持續。但假如你的法式要像播放器殺軟那樣許可用戶隱蔽窗口的話,那還得持續折騰,此時成績釀成【若何讓無窗口的過程顯示窗口】,我的思緒是如許:既然目的過程沒窗口,我沒方法純潔用內部手腕操作到它的窗體,但由於法式是我本身寫的,可弗成以來個裡應外合,辦了這事。好比向它發一條特定新聞,它在收到該新聞後,心照不宣,把本身的窗口顯示出來~到時刻榮華貧賤享之sorry入戲了。這個思緒重要觸及兩個成績,怎樣發和怎樣收,至於收到後若何前排顯示窗口之類,小case。

怎樣發

SendMessage/PostMessage天然是指不上的,由於這倆貨也是基於窗口的,其實我一度疑惑走新聞這條路能否可行,這觸及到一個道理成績,就是假如新聞必定是只能發送給窗口的話,那注定此路欠亨,只能斟酌其余過程間通訊計劃。好在懂得到PostThreadMessage這個API,處理了我的成績。該API是向指定線程發送新聞(MSDN文檔在此),這也解釋在道理上,新聞並不是只可以發給窗口,還可以發給線程,至於還能不克不及發給其余甚麼器械就不曉得了。先看一下發送語句:

void Main()
{
...
//向目的過程的主線程發送新聞
PostThreadMessage(Process.GetProcessById(pid).Threads[0].Id, 0x80F0, IntPtr.Zero, IntPtr.Zero);
...
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostThreadMessage(int threadId, uint msg, IntPtr wParam, IntPtr lParam); 

API的第1個參數是目的線程的ID。留意兩點:①此ID是體系全局的線程ID,並不是Thread.ManagedThreadId這類“假”ID;②目的線程必需存在新聞輪回。winform的主線程常常就是UI線程,自然存在新聞輪回,所以無需斟酌這個成績。第2個參數是要發送的新聞ID。我們的目標是發一條收發兩邊商定的新聞,所以這個新聞要夠特殊,不克不及跟體系新聞撞衫,所以規模最好介於0x8001~0xBFFF之間,這是體系留給運用法式自用的新聞段(WM_APP)。前面倆參數我沒用,你想讓新聞更特殊一點,或想攜帶其它信息的話也能夠用上。辦法前往true/false分離代表發送勝利/掉敗。

別的,目的過程或許有多個線程,個中哪一個才是能收新聞的主線程我沒有迷信的斷定辦法,年夜膽揣測就是Process.Threads聚集中的第1項,這個猜想至今任務優越,不論它。若您有迷信斷定法,請告訴~感謝。

怎樣收

因為新聞是走線程過去的,所以別想著在主窗口的WndProc中去收,再說新聞過去的時刻,主窗口存不存在都是個成績。要用運用法式級其余新聞挑選器來收,挑選器是個完成System.Windows.Forms.IMessageFilter接口的類(MSDN),該接口只需完成一個辦法:bool PreFilterMessage(ref Message m),辦法邏輯是,假如收到的新聞m是你要處置並吃失落的,就前往true,其他新聞則前往false放行。全部挑選器像如許:

class MsgFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x80F0)
{
DoSomething(); //顯示窗口或其它事
return true;
}
return false;
}
}

現實上我收到新聞後其實不是直接做顯示窗口相干的事,而是激發一個事宜,主窗體注冊該事宜,在事宜處置辦法中再寫顯示窗口相干的代碼。這是設計上的考量,與本文宗旨有關,不多說。

挑選器寫好後,還得把它添加到一個處所它能力任務,甚麼時刻添加就甚麼時刻才開端施展感化,所以最好盡早添加,例如在main的開首。像如許:

void Main()
{
Application.AddMessageFilter(new MsgFilter());
...
}

至此,收發的成績處理。這本質上是一個過程間通訊成績,所以其實任何過程通訊手腕都可以運用在本文的案例,走新聞只是個中一種手腕。

以上所述是小編給年夜家引見的C#向無窗口的過程發送新聞的相干常識,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved