MFC用PostMessage傳遞消息


1.自定義消息ID。

#define WM_MY_MESSAGE (WM_USER+100)         WM_USER為windows系統為非系統消息保留的ID,這里至少要用100,因為其它控件的消息會占用一部分。

2. 定義消息處理函數。

消息處理函數為消息目標類的成員函數。首先應該在.h 文件中聲明。這里以主窗口類為例,主窗口類名 CMainDialog,則首先在CMainDialog.h聲明消息處理函數。

protected: 

afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); 

3.在CMainDialog.cpp中實現消息處理函數

LPESULT CMainDialog::OnMyMessage(WPARAM wParam, LPARAM lParam) 

// TODO: 處理用戶自定義消息 
... 
return 0; 
}

4.在CMainDialog.cpp中映射消息ID和消息處理函數

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
ON_WM_CREATE() 
ON_WM_TIMER() 
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage) 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP()

在創建線程的時候將主窗口句柄作為參數傳入線程,就可以用 PostMessage傳遞消息了。

 

SendMessage函數功能描述:將指定的消息發送到一個或多個窗口。此函數為指定的窗口調用窗口過程,直到窗口過程處理完消息后才返回。

Postmessage函數則是將消息放入消息隊列里,並立即返回。

常見問題

1)使用SendMessage來實現剪切、復制和粘貼

 

1 SendMessage(hwnd, WM_COPY, 0, 0);
2 SendMessage(hwnd, WM_CUT, 0, 0);
3 SendMessage(hwnd, WM_PASTE, 0, 0);

 

2)SendMessage與PostMessage的區別

PostMessage將消息放入消息隊列后馬上返回,而SendMessage直到窗口過程處理完消息后才返回。

3)SendMessage發送WM_COPYDATA消息在進程間傳送數據

WM_COPYDATA消息主要目的是允許在進程間傳遞少量只讀數據。SDK文檔推薦用戶使用SendMessage()函數,接收方在數據復制完成前不返回,這樣發送方就不可能刪除和修改數據。

例如:

 

1 std:string strData = "VC知識庫 VCKBASE.COM";
2 COPYDATASTRUCT cds;
3 cds.dwData = 0;
4 cds.cbData = strData.Length();
5 cds.lpData = strData.c_str();
6 ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cds);

 

3、PostThreadMessage有時會失敗,報1444錯誤(Invalid thread identifier. ),其實這不一定是線程不存在的原因,也有可能是線程不存在消息隊列(message queue)造成的。事實上,並不是每個thread都有message queue,那如何讓thread具有呢? 答案是,至少調用message相關的function一次,比如GetMessage,PeekMessage。

4、如果是postthreadmessage動態分配的memory給另外一個thread,要注意內存的正確釋放。並且PostThreadMessage不能夠post WM_COPYDATE之類的同步消息,否則會報錯!

5、最好不要使用PostThreadMessage post message給一個窗口,使用PostMessage替代。

 

1    #include <windows.h>
2    #include <cstdio>
3    #include <process.h>
4    #define MY_MSG WM_USER+100
5    const int MAX_INFO_SIZE = 20;
6    HANDLE hStartEvent; // thread start event
7    // thread function
8    unsigned __stdcall fun(void *param)
9    {
10        printf("thread fun start
11    
12    
13    \n");
14        MSG msg;
15        PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
16        if(!SetEvent(hStartEvent)) //set thread start event 
17        {
18            printf("set start event failed,errno:%d\n",::GetLastError());
19            return 1;
20        }
21        
22        while(true)
23        {
24            if(GetMessage(&msg,0,0,0)) //get msg from message queue
25            {
26                switch(msg.message)
27                {
28                case MY_MSG:
29                    char * pInfo = (char *)msg.wParam;
30                    printf("recv %s\n",pInfo);
31                    delete[] pInfo;
32                    break;
33                }
34            }
35        };
36        return 0;
37    }
38    int main()
39    {
40        HANDLE hThread;
41        unsigned nThreadID;
42        hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event
43        if(hStartEvent == 0)
44        {
45            printf("create start event failed,errno:%d\n",::GetLastError());
46            return 1;
47        }
48        //start thread
49        hThread = (HANDLE)_beginthreadex( NULL, 0, &fun, NULL, 0, &nThreadID );
50        if(hThread == 0)
51        {
52            printf("start thread failed,errno:%d\n",::GetLastError());
53            CloseHandle(hStartEvent);
54            return 1;
55        }
56        //wait thread start event to avoid PostThreadMessage return errno:1444
57        ::WaitForSingleObject(hStartEvent,INFINITE);
58        CloseHandle(hStartEvent);
59        int count = 0;
60        while(true)
61        {
62            char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
63            sprintf(pInfo,"msg_%d",++count);
64            if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0))//post thread msg
65            {
66                printf("post message failed,errno:%d\n",::GetLastError());
67                delete[] pInfo;
68            }
69            ::Sleep(1000);
70        }
71        CloseHandle(hThread);
72        return 0;
73    }

 


免責聲明!

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



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