【轉】vc中使用SendMessage正確發送自定義消息的方法--不錯


原文網址:http://zhoumf1214.blog.163.com/blog/static/5241940200910265532959/

最近在用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獲得主窗口。

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

 

MFC退出程序

原文網址:http://blog.csdn.net/one___thousand/article/details/40212369

PostQuitMessage(0);

PostMessage(WM_QUIT,0,0);

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

::PostMessage(AfxGetMainWnd()->m_hWnd,WM_CLOSE,0,0);

ExitProcess(0);//注意使用時先釋放分配的內存,以免造成內存泄露

exit(0) ;//正常終止程序; exit(非0)非正常終止程序

SendMessage(WM_CLOSE); //向主窗口發送WM_CLOSE消息

AfxGetMainWnd->SendMessage(WM_CLOSE); //在其它類關閉應用程序

 

MFC獲取句柄的方法 

句柄獲取方法(獲取該窗口的句柄后,即可向該窗口類類發送消息、處理程序):
例如:::PostMessage("句柄", WM_USER_DRAWVIEWPIC_EDS, 0, 0);

0。獲取所在類窗口的句柄:
this->m_hwnd

1。主窗口的句柄:
無論在主窗口類內,還是子窗口類內,獲取主窗口句柄的方法:
AfxGetMainWnd()->m_hWnd,
如:::SendMessage(AfxGetMainWnd()->m_hWnd , WM_MY_DOSOME , 0 ,(LPARAM)i);
在窗口類中
this->m_hWnd
或者this->GetSafeHwnd()

2。子窗口句柄:用FindWindow,(只要知道子窗口的名字即可)如:
 ::FindWindow(NULL,WindowsName) 
返回找到的窗口的句柄
尋找當前窗口是否在運行windowname的程序,該名字為窗口名字,如:
CWnd* pWnd=FindWindow(NULL,_T("清芝--支票機"));//

GetSafeHwnd
函數功能:獲取某個窗口對象(CWnd的派生對象)指針的句柄(HWND)時,最安全的方法是使用

GetSafeHwnd()函數。
通過下面的例子來看其理由:
  CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器
  HWND hwnd = pwnd->m_hwnd; //得到它的HWND
  這樣的代碼當開始得到的pwnd為空的時候就會出現一個“General protection error”,並關閉應用

程序,因為一般不能對一個NULL指針訪問其成員,如果用下面的代碼:
  CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器
  HWND hwnd = pwnd->GetSafeHwnd(); //得到它的HWND
  就不會出現問題,因為盡管當pwnd是NULL時,GetSafeHwnd仍然可以用,只是返回NULL

源文檔 <http://blog.csdn.net/luheng2006/article/details/5897643> 

3。獲取窗口中 控件的句柄,用 GetDlgItem
語法為:GetDlgItem(IDC_COMBO3)->m_hWnd :參數為 該控件的ID,返回值為:CWnd* 類型,但它是CWnd類

內的函數,因此要先獲取控件所在窗口的指針,如:
CString str(_T("dd"));
::SendMessage(AfxGetMainWnd()->GetDlgItem(IDC_COMBO3)->m_hWnd, WM_SETTEXT , 0 , (LPARAM)

str.GetBuffer(0));

從句柄獲得指針,用 FromHandle
語法:CWnd* pWnd = CWnd::FromHandle(hWnd);
獲取窗口句柄(全集) vc&MFC 
獲得窗口句柄:
this->m_hwnd
HWND GetForegroundWindow(VOID);
GetSafehWnd 取你程序所在窗口類的句柄
GetActiveWindow 取當前活動窗口句柄
AfxGetMainWnd 取主窗口句柄
GetForegroundWindow 取前台窗口句柄
FindWindow
EnumWindow

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM