1. 程式人生 > >vc中怎麼使用SendMessage自定義訊息函式

vc中怎麼使用SendMessage自定義訊息函式

   最近在用VC2008做開發,後來由於要用到訊息的傳送,而且需要自定義訊息,在網上查找了很多例子,根據他們所說的,雖然大致都差不多,但是基本上沒有一個能完全做出來的。要知道VC程式設計有一個小地方出錯,都可能是個讓你頭暈腦脹的事情。經過我後來不但探索,經過改進之後,一點錯誤都沒有,現在貼出來供大家參考。

      1. 先來個基本知識介紹

SendMessage的基本結構如下:

SendMessage(

    HWND hWnd,  //訊息傳遞的目標視窗或執行緒的控制代碼。

    UINT Msg, //訊息類別(這裡可以是一些系統訊息,也可以是自己定義,下文具體介紹,)

    WPARAM wParam, //引數1 (WPARAM 其實是與UINT是同種型別的,

  //在vc編譯器中右鍵有個“轉到WPARAM的定義”的選項可以檢視。

    LPARAM lParam); //引數2

其中一些引數的由來如下:

//typedef unsigned int UINT;

//typedef UINT WPARAM;

//typedef LONG LPARAM;

//typedef LONG LRESULT;

2.  SendMessage用法例項

    例如可以用以下語句:

void CTScrollWinView::OnLButtonDblClk(UINT nFlags, CPoint point)
       {
            // TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值

     ::SendMessage(AfxGetMainWnd()->m_hWnd,WM_CHILDFRAMEDBCLK ,0,0);

     CScrollView::OnLButtonDblClk(nFlags, point);
       }

這是我用VC2008下建立的一個多文件選項卡式工程裡面的一段程式碼,是為了實現在子視窗雙擊後傳送一個不帶引數的訊息(其ID為WM_USER+1)給主視窗, 如上為部分程式碼, 其中WM_CHILDFRAMEDBCLK是自定義的訊息ID, AfxGetMainWnd()->m_hWnd是獲得主視窗(這裡不能使用GetParent()->m_hWnd或者GetParentFrame()->m_hWnd, 因為這是獲得父視窗,但父視窗不一定是主視窗,一定要注意,不然訊息就會發錯導致接收不到,我這裡卡了半天,後來在QQ群裡一位大俠告訴我的,在此再感謝一下那位大俠);

3. 在接收訊息的窗體以及執行緒所在的標頭檔案裡定義:

#define WM_CHILDFRAMEDBCLK  WM_USER+1   // do something

4. 然後接下來定義一個訊息需要對映的函式,如下:

afx_msg LRESULT OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam);

注意格式必須是:兩個引數必不可少,返回型別一定為LRESULT,網上很多文章都忽略了這兩點,這也是網上文章普遍錯誤的地方。

5. 新增訊息函式對映

    ON_MESSAGE(WM_CHILDFRAMEDBCLK,OnChlidFrameDBClick)

    注意這裡必須是ON_MESSAGE, 不能使用ON_COMMAND, 前者主要針對使用者自定義訊息,後者針對

WM_COMMAND命令,比如選單、工具欄等.

6. 實現訊息函式:

我們在接收窗體裡定義一個這樣的事情(過程),

LRESULT CMainFrame::OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam)
      {
            CancelFullScreenWin();  // 這裡呼叫了一個使子視窗全屏的自寫函式,我就不貼出來了,以後專題將的時候會提到

      return 0;
      }

7. 下面是部分程式碼,要想搞清楚自定義訊息傳送只看這部分程式碼就足夠了

在MainFrm.h標頭檔案裡定義了訊息如下:

      #define WM_CHILDFRAMEDBCLK WM_USER+1

然後在MainFrm.cpp中宣告需要對映的訊息函式如下:

      afx_msg LRESULT OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam);

再在MainFrm.cpp中新增對映如下:

      BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
                   ON_WM_CREATE()
                   ON_COMMAND(ID_FullScreen, OnViewFullscreen)
                   ON_MESSAGE(WM_CHILDFRAMEDBCLK,OnChlidFrameDBClick)   // 對映新增到這裡
             END_MESSAGE_MAP()

然後在MainFrm.cpp中實現OnChlidFrameDBClick()方法,如下:

LRESULT CMainFrame::OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam)
       {
            CancelFullScreenWin();//自己定義的函式,你們可以在這裡完成自己需要的業務

     return true;
       }

最後就可以傳送訊息給主視窗了,如下:

void CTScrollWinView::OnLButtonDblClk(UINT nFlags, CPoint point)
      {
            // TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值

     ::SendMessage(AfxGetMainWnd()->m_hWnd,WM_USER+1,0,0);

     CScrollView::OnLButtonDblClk(nFlags, point);
      }

總結一下:①注意定義訊息的ID不能重複,要用WM_USER+n;

                  ②注意定義的訊息函式的返回值一定是LRESULT, 並且有兩個引數分別必須為WPARAM和LPARAM ;

                  ③注意對映用ON_MESSAGE, 而不是ON_COMMAND;

                  ④注意傳給主視窗的訊息在CXXXXView類中要用AfxGetMainWnd()->m_hWnd獲得主視窗。

至此就講完了,希望對大家找不對資源的有所幫助