QT c++ 中使用PostMessage/SendMessage
PostMessage是Windows API(應用程式介面) 中的一個常用函式,用於將一條訊息放入到訊息佇列中。並且不會等待響應的執行緒處理訊息,而是直接返回。(簡單的理解就是非同步)。
而SendMessage作用一樣,但是會等待結果返回(同步)
我們先來看PostMessage函式的原型:
BOOL WINAPI PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
hWnd:其視窗程式接收訊息的視窗的控制代碼。可取有特定含義的兩個值:
HWND_BROADCAST:訊息被寄送到系統的所有頂層視窗,包括無效或不可見的非自身擁有的視窗、 被覆蓋的視窗和彈出式視窗。訊息不被寄送到子視窗
NULL:此函式的操作和呼叫引數dwThread設定為當前執行緒的識別符號PostThreadMessage函式一樣
Msg:指定被寄送的訊息。
wParam:指定附加的訊息特定的資訊。
LParam:指定附加的訊息特定的資訊。
返回值:如果函式呼叫成功,返回非零,否則函式呼叫返回值為零
接收的時候,使用QT5中的方法是 在接收的類中,重新實現 nativeEvent函式(Qt4的時候使用的是winEvent,從Qt5開始,就使用nativeEvent),這個方法既可以攔截系統訊息,也可以攔截通過postMessage,sendMessage傳送的自定義訊息。
[virtual protected] bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result);
其中:
eventType: windows平臺的值就是“windows_generic_MSG”;
message: 型別為MSG*, 儲存的就是PostMessage中的Msg。
Result:型別為LRESULT,返回的值。
如果返回ture:表示停止這個訊息。如果返回false:這個訊息就繼續傳遞給Qt,Qt會將這個訊息轉變為Qt event並將它傳送給響應的控制元件。
我們用Qt環境下來舉個栗子:
先是使用SendMessage來向頂層視窗傳送訊息
HWND m_wnd = ::FindWindowA(("ClientMainWindow"), NULL);//通過主視窗類名尋找主視窗控制代碼 WId wid = this->winId(); //這個視窗的winid if (NULL != m_wnd) { std::thread th([=](){ //單獨啟動一個執行緒進行資料傳遞 QString command = QString("Command=ChangeCode=%1\r\n").arg(code);//傳遞的內容 std::string param = command.toStdString(); COPYDATASTRUCT data; //使用COPYDATA的方式進行資料傳遞 data.dwData = 0; data.cbData = param.length(); data.lpData = ¶m[0]; ::SendMessage(m_wnd, WM_COPYDATA, (WPARAM)wid, (LPARAM)&data); }); th.detach();//傳遞結束後,進行關閉執行緒 }
同時,在接收的頂層視窗中,重寫nativeEvent函式
bool EmbededWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if (eventType == "windows_generic_MSG") //windows平臺
{
MSG* msg = reinterpret_cast<MSG*>(message); //
if(msg->message == WM_COPYDATA)//訊息型別
{
COPYDATASTRUCT *data = reinterpret_cast<COPYDATASTRUCT*>(msg->lParam);
QTextCodec *gbk = QTextCodec::codecForName("GB18030");
QString recevice = gbk->toUnicode((char *)(data->lpData));//轉碼
if(recevice.contains("Command="))
{
return true;//訊息不再進行傳遞,不再處理
}
m_wnd = reinterpret_cast<HWND>(msg->wParam);//高地址的引數
}
}
return QWidget::nativeEvent(eventType, message, result);//交給Qt處理
}