消息處理(二):投遞與發送

      消息的投遞(Post)過程相似於普通訊件的投遞過程。普通訊件經過郵遞員到達收信方的信箱裏,收信方取得該信,閱讀信件內容,並可能回信。在這個過程當中,郵遞員的責任只是將信件送到收信者的信箱,一切任務就完成了。異步

      消息的發送(Send)過程理解爲打電話交流的過程。甲找到乙的電話號碼,而後開始撥號。若是運氣好,撥通了乙的電話,那麼兩人就聯繫上了。假設甲方從不主動掛斷電話,那麼只有乙方先掛斷電話,兩人的一次聯繫才宣告結束。函數

PostMessage函數spa

BOOL PostMessage(
     HWND        hWnd,                  //目標窗口句柄
    UINT          Msg,                    //消息
    WPARAM     wParam,              //第一個消息參數
    LPARAM      lParam                //第二個消息參數
);

CWnd::PostMessage提供了對PostMessage的簡單包裝,他首先斷言窗口句柄表示一個窗口,而後以窗口句柄爲第一個參數調用全局的PostMessage:線程

_AFXWIN_INLINE BOOL CWnd::PostMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
   ASSERT(::IsWindow(m_hWnd));
   return ::PostMessage(m_hWnd, message, wParam, lParam);
}

hWnd有兩個特殊的值:HWND_BROADCAST和NULL。前者表示要將該消息投遞到系統當前全部的非子窗口。後者表示由線程而不是某個窗口的窗口過程來處理該消息。
Msg表示投遞的消息標誌,最後兩個參數則表示特定於該消息的參數。千萬要注意,由於投遞消息相似於異步調用,因此在消息參數中傳遞指針是很是危險。指針

SendMessage函數code

LRESULT SendMessage(
  HWND hWnd,          //接收消息的目標窗口
  UINT Msg,            //消息標誌
  WPARAM wParam,       //第一個消息參數
  LPARAM lParam      //第二個消息參數
);

 能夠將hWnd的參數設置爲HWND_BROADCAST,表示系統全部的非子窗體廣播此消息。blog

爲了不調用線程陷入永久的等待狀態,能夠用SendMessageTimeout代替SendMessage:回調函數

LRESULT SendMessageTimeout(
    HWND hWnd,          //窗口句柄
   UINT Msg,              //消息標記
   WPARAM wParam,   //第一個消息參數
   LPARAM lParam,     //第二個消息參數
   UINT fuFlags,         //消息發送選項
   UINT uTimeout,     //超時,以毫秒爲單位
   PDWORD_PTR lpdwResult,  //返回值,依賴於特定的消息
);

關鍵是fuFlag參數,它決定了該如何發送該消息,fuFlag參數的值及含義以下表:table

說  明
SMTO_ABORTIFHUNG 若是目標線程處於掛起狀態,調用線程將不等待超時而當即返回
SMTO_BLOCK 阻止調用線程在目標線程處理完消息以前處理其餘請求
SMTO_NORMAL 在等待目標線程處理消息時,容許調用線程處理其餘請求
SMTO_NOTIMEOUTIFNOTHUNG 對於XP/WIN2000有意義:若是目標線程未掛起,調用線程即便發生超時也會等待目標線程處理完該消息

 

 

 

若是調用成功,SendMessageTimeout會返回非0值;若是調用失敗或發生超時,則返回0。爲了防止調用線程被無限等待,能夠將fuFlag參數設爲SMTO_BLOCK,並設置必定的超時時間。class

說明:若是是廣播消息,假定有兩個目標窗口將處理該消息,那麼目標線程將總共有2*uTimeout毫秒的等待期。

CWnd::SendMessage對SendMessage進行了簡單的包裝,它驗證窗口句柄的有效性,而後調用SendMessage API函數:

_AFXWIN_INLINE LRESULT CWnd::SendMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
    ASSERT(::IsWindow(m_hWnd));
    return ::SendMessage(m_hWnd, message, wParam, lParam);
}

提示:CWnd沒有提供對SendMessageTimeout的包裝。

同屬於SendMessage系列的API還有SendNotifyMessage和SendMessageCallback,其行爲特性介於PostMessage和SendMessage之間。

SendNotifyMessage函數:

BOOL SendNotifyMessage(
  HWND hWnd;         //窗口句柄
  UINT Msg;          //消息標誌
  WPARAM wParam,     //第一個消息參數
  LPARAM lParam      //第二個消息參數
);

      若是hWnd窗口由調用線程建立,那麼其行爲特性跟SendMessage相同,這時將等待消息處理完畢後才返回。若是hWnd由另外一線程建立,其行爲特性則與PostMessage相同,它沒必要等待目標線程處理完該消息而直接返回。

SendMessageCallback函數:

SendMessageCallback的行爲特性相似於PostMessage,也是在發出消息後,不等待目標窗口處理該消息就馬上返回,但它容許消息處理完畢後,讓系統執行指定的函數。

BOOL SendMessageCallback(
   HWND hWnd,                //窗口句柄
   UINT Msg,                 //消息標誌
   WPARAM wParam,            //第一個消息參數
   LPARAM lParam,            //第二個消息參數
   SENDASYNCPROC lpCallBack, //回調函數
   ULONG_PTR dwData          //應用範圍內的數據
);

SENDASYNCPROC是回調函數的類型,它具備以下形式的簽名:

VOID CALLBACK SendAsyncProc(
   HWND hwnd,        //目標窗口的句柄
   UINT uMsg,        //消息標記
   ULONG_PTR dwData, //應用範圍的數據
   LRESULT lResult   //消息處理結束,依賴於特定的消息
);

傳入回調函數的dwData正是在SendMessageCallback中的dwData參數指定的。

相關文章
相關標籤/搜索