青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Chip Studio

常用鏈接

統計

最新評論

WinAPI編程基礎 之 消息分流器

WinAPI編程基礎 之 消息分流器[z]


文章作者:Bideyore[E.S.T]
信息來源:邪惡八進制 中國(www.EvilOctal.com

對于熟悉Win API編程的同志們來說,windowsx.h這個頭文件應該不會太陌生吧,這次要講的內容就來自這個windowsx.h頭文件。

經常能在msdn上查到這樣一些函數,明明是個函數,而且模樣長得和一般的api函數也一樣一樣的,可卻叫做macro,為什么呢?留意一下函數使用的requirement,你會發現,它的聲明正是在windowsx.h這個頭文件里。

Windowsx.h包含了這樣一些內容:
宏API,窗口消息分流器,控件API;

所 有的這些宏定義,可以使你的程序更加安全,簡潔,結構更清晰,大大提高程序的可讀性;其中窗口消息分流器(message cracker)是我們今天要討論的話題,它可以使我們的API程序變得更簡潔。下面就進入我們的主題:(有關windowsx.h的更多內容,可以參考 MS Knowledge Base Article #83456.)

消息分流器是Windows提供的一組宏定義,它的兩個最大的作用,用MS的話來說,就是:

● 安全的數據類型,因為消息分流器完成了大量的類型轉換的工作;
● 使程序向32位windows的轉化更簡單;

當然,使用消息分流器會大大改變程序的面貌,你也可以選擇不使用它。

下面我們就以一個對話框窗口的消息處理過程為例,看看消息分流器到底是怎么運作的。


1.消息分流器的基本使用
先看一個普通的窗口消息處理函數,它可能需要處理一些窗口的初始化,無效客戶區重繪等消息:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
// ...
return 0;

case WM_PAINT:
// ...
return 0;

case WM_DESTROY:
//...
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

而通過使用消息分流器,我們可以把每個case都寫到相應的消息處理函數中,就像下面這樣:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);

case WM_PAINT:
return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);

case WM_DESTROY:
return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

這里用到了三個宏定義:HANDLE_WM_CREATE, HANDLE_WM_PAINT, HANDLE_WM_DESTROY;這三個宏定義就是我們的三個消息分流器(別看叫什么分流器,說穿了也不值幾個錢,呵呵),它們在windowsx.h中的定義如下:

#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn)
((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)
#define HANDLE_WM_PAINT(hwnd, wParam, lParam, fn)
((fn)(hwnd), 0L)
#define HANDLE_WM_DESTROYCLIPBOARD(hwnd, wParam, lParam, fn)
((fn)(hwnd), 0L)

把這三個宏定義替換回去,就變成:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return Cls_OnCreate(hwnd, (LPCREATESTRUCT)(lParam) ? 0L : (LRESULT)-1L;
// 如果處理了消息,則Cls_OnCreate應返回TRUE,導致WndProc返回0,否則Cls_OnCreate返回FALSE,導致WndProc返回-1;
case WM_PAINT:
return Cls_OnPaint(hwnd), 0L;
// 逗號表達式;Cls_OnPaint是void類型,這里返回0;
case WM_DESTROY:
return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

之后我們就可以按照消息分流器的定義編寫相應的消息處理函數了:

BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct){…};
void Cls_OnPaint(HWND hwnd){…};
void Cls_OnDestroyClipboard(HWND hwnd){…};

windowsx.h還提供了一個更加簡化的方法:使用HANDLE_MSG宏,這個宏是這樣定義的:

#define HANDLE_MSG(hwnd, message, fn)
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

這個宏要做的就是根據不同的message(##用來連接前后的字符串),把自己“變成”相應的HANDLE_XXXXMESSAGE形式的宏,再通過相應的宏來執行消息處理代碼;
比如實際代碼中寫入:

HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate)

則經過轉換就變成:

case (WM_CREATE): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Cls_OnCreate))

這樣,我們就可以直接把程序寫為:
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);
HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

之 后直接編寫相應的消息處理過程就可以了。是不是簡潔多了?而且把消息處理封裝到函數里面,就可以使用VS直接跳轉到這個函數,再也不用費勁去找那個 case了。要注意的一點是,雖然windowsx.h里包括了所有消息對應的分流器,但它們的參數是宏定義顯式說明的,在編寫消息處理函數時,必須遵循 宏定義中的參數類型,否則會導致錯誤;這么多消息分流器,我們每次新寫一個消息處理函數時就得看看是否把參數設置正確了,整個過程繁瑣冗長。好在已經有一 個工具叫Message Cracker Wizard,可以幫助我們生成消息分流器和相關的處理過程,具體見:http://www.codeproject.com/win32/msgcrackwizard.asp。


2.在對話框中使用消息分流器
在對話框消息處理中,窗口子類化是我們經常使用的手段,這也可以通過消息分流器實現,但是有點小問題 :>
下面是一個使用了windowsx.h消息分流器的對話框及其處理過程:
……
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int)
{
DialogBoxParam(
hinstExe, MAKEINTRESOURCE(IDD_PASSTHRU), NULL, (DLGPROC)Dlg_Proc, 0);

return(0);
}
……

LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog); // 不能直接使用HANDLE_MSG宏
HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand); // 不能直接使用HANDLE_MSG宏
}

return false;
}

以上程序中直接使用HANDLE_MSG可能導致錯誤;為什么呢?問題出在子類化的消息處理過程的返回值上,msdn中對于對話框消息處理過程的返回值有如下說明:

一般情況下,對話框過程函數應該在處理了消息的情況下返回TRUE,如果沒有處理,則返回FALSE。如果對話框過程返回了FALSE,那么對話框管理器為這條消息準備默認的對話操作。

如 果對話框處理了一個需要特定返回值的消息,則對話框的返回值應該被設置為調用SetWindowLong(The SetWindowLong function changes an attribute of the specified window. The function also sets a 32-bit (long) value at the specified offset into the extra window memory of a window. )后的返回值,并在返回TRUE之前立即返回這個 值。注意你必須立即調用SetWindowLong(這個函數用于調用窗口子類化的過程),這會導致DWL_MSGRESULT值被一個嵌套的對話框消息 改寫。返回值為特定值的消息有:
• WM_CHARTOITEM
• WM_COMPAREITEM
• WM_CTLCOLORBTN
• WM_CTLCOLORDLG
• WM_CTLCOLOREDIT
• WM_CTLCOLORLISTBOX
• WM_CTLCOLORSCROLLBAR
• WM_CTLCOLORSTATIC
• WM_INITDIALOG
• WM_QUERYDRAGICON
• WM_VKEYTOITEM
看到沒有? 我們的消息WM_INITDIALOG也在其中,對這個消息進行處理的過程不能簡單的返回TRUE表示對消息進行了處理,而是另有其意;它將轉化為:

case (WM_INITDIALOG): return HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, Cls_OnInitDialog);

宏HANDLE_WM_INITDIALOG定義如下:

#define HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, fn)
(LRESULT)(DWORD)(UINT)(BOOL)(fn)((hwnd), (HWND)(wParam), lParam)

對WM_INITDIALOG的處理,如果返回TRUE,則表示設置鍵盤焦點到對話框的默認控件,否則返回FALSE;這時好像還看不出什么問題,而對于我們的另外一個消息WM_COMMAND,HANDLE_MSG簡單的把它變成:

case (WM_COMMAND): return HANDLE_WM_COMMAND(hwnd, wParam, lParam, Cls_OnCommand);

宏HANDLE_WM_COMMAND定義如下:

#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn)
((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L)

問 題出來了,我們的Cls_OnCommand由于是個void型的函數,是沒有返回值的,因此windows默認這種消息處理過程必須返回一個0值,而返 回0值不就表示我們的消息過程不處理這個消息么?這個矛盾是HANDLE_MSG無法解決的。怎么辦才能使消息過程在處理完WM_COMMAND消息之后 正確的返回一個TRUE呢? 答案是使用另一個windowsx.h中的宏:SetDlgMsgResult(hwnd, msg, result)

這個宏定義如下:

#define SetDlgMsgResult(hwnd, msg, result) ((
(msg) == WM_CTLCOLORMSGBOX ||
(msg) == WM_CTLCOLOREDIT ||
(msg) == WM_CTLCOLORLISTBOX ||
(msg) == WM_CTLCOLORBTN ||
(msg) == WM_CTLCOLORDLG ||
(msg) == WM_CTLCOLORSCROLLBAR ||
(msg) == WM_CTLCOLORSTATIC ||
(msg) == WM_COMPAREITEM ||
(msg) == WM_VKEYTOITEM ||
(msg) == WM_CHARTOITEM ||
(msg) == WM_QUERYDRAGICON ||
(msg) == WM_INITDIALOG
) ? (BOOL)(result) : (SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE))

(有沒有注意到,里面多了一個WM_CTLCOLORMSGBOX ? 這個消息是16位WinAPI中的消息,一度被轉換為Win32 API的一個消息;現在在最新的32位API中已經被刪除了;保留它可能考慮到兼容性的問題,這里不做進一步討論)
現 在看到了,如果對話框過程處理的消息恰巧為返回特定值中的一個,則如實返回result;不要被前面的BOOL蒙蔽,BOOL在頭文件中的定義實際上是一 個int型,一旦需要返回非TRUE或FALSE的其他值,照樣可以;這樣,我們的Cls_OnInitDialog就能夠正確的返回它的BOOL值了, 而Cls_OnCommand在處理之后,也可以由后面的逗號表達式正確的返回一個TRUE表示消息已處理。

在《Windows核心編程》一書中,大牛Jeffrey自己定義了一個宏,使SetDlgMsgResult宏的使用更加方便:

#define chHANDLE_DLGMSG(hwnd, message, fn)
case (message): return (SetDlgMsgResult(hwnd, uMsg,
HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

可見這個宏只是簡單的對SetDlgMsgRseult宏進行了封裝。

這樣,我們最終的代碼可以寫成:

LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog); // 使用大牛的chHANDLE_DLGMSG宏
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Cls_OnCommand);
}

return false;
}



下面把原來程序整個框架列出來:

LRESULT CALLBACK Dlg_Proc(HWND hwnd, UNIT umsg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_COMMAND: // 每個case都被一個message cracker代替,這里使用大牛同志的
// do something; // chHANDLE_DLGMSG宏;這個宏負責對消息篩選,處理并返回相應的值
return true;

case WM_INITDIALOG:
// do something;
return xxxx;
}

return false; // 如果消息不在我們的DlgProc過程中被處理,則告訴調用這個DlgProc的消息,
} //告訴系統的對話框管理器,這個消息我們不處理,交給你了

對比一下,消息分流器的作用不言自明。

以上只是介紹了消息分流器的部分應用,更多創造性的用法還等你自己在實踐中發掘。

下面列出一些有用的參考資料:

http://support.microsoft.com/default.aspx?scid=kb;en-us;83456 介紹了STRICT宏定義以及windowsx.h
http://www.codeproject.com/win32/msgcrackwizard.asp 提供message cracker wizard的下載,而且附有源代碼
《windows核心編程》windows系統編程,就跟定大牛了 :> 他在自己的sample中大量使用了message cracker


posted on 2008-02-04 02:53 MyChip 閱讀(186) 評論(0)  編輯 收藏 引用 所屬分類: VC

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产人久久人人人人爽| 亚洲第一二三四五区| 一区二区三区四区五区在线| 亚洲高清影视| 欧美成人精品高清在线播放| 亚洲精品国产拍免费91在线| 欧美韩国一区| 欧美日韩一区二区三区免费| 亚洲视频免费看| 亚洲一区在线观看视频| 国产区精品视频| 猛男gaygay欧美视频| 麻豆成人在线播放| 夜夜夜久久久| 亚洲在线视频| 在线精品视频免费观看| 亚洲全部视频| 国产情侣久久| 亚洲福利视频网站| 国产精品久久久久毛片软件| 久久久久久自在自线| 欧美成人免费全部观看天天性色| 亚洲一区二区三区中文字幕在线| 亚洲免费在线精品一区| 亚洲国产精品一区二区第四页av| 亚洲精品一线二线三线无人区| 国产精品亚洲综合一区在线观看 | 欧美日韩在线亚洲一区蜜芽| 西瓜成人精品人成网站| 久久亚洲影音av资源网| 亚洲自拍偷拍视频| 久久综合色综合88| 欧美在线视频一区二区三区| 欧美成人午夜| 久久免费少妇高潮久久精品99| 欧美激情视频一区二区三区在线播放 | 欧美精品www在线观看| 欧美一区二区三区免费视| 麻豆久久久9性大片| 欧美一级午夜免费电影| 欧美精品免费看| 老司机一区二区三区| 国产精品久久久久久久久| 亚洲丰满在线| 一色屋精品视频在线观看网站| 一二三区精品| 99国产精品久久久久久久久久| 欧美在线看片a免费观看| 亚洲欧美区自拍先锋| 欧美韩国日本一区| 欧美国产日韩在线观看| 精品va天堂亚洲国产| 亚洲欧美一区二区在线观看| 亚洲一区二区三区午夜| 欧美区一区二| 亚洲人成在线播放网站岛国| 亚洲二区在线视频| 久久久久久久一区二区| 久久亚洲精品一区二区| 国产丝袜一区二区| 亚洲综合色网站| 欧美一区二区三区免费看| 国产精品激情av在线播放| 夜夜爽99久久国产综合精品女不卡| 亚洲精品日本| 欧美激情精品| 亚洲三级性片| 中日韩午夜理伦电影免费| 欧美日韩高清在线观看| 亚洲国产专区校园欧美| 99riav国产精品| 欧美日韩国产美女| 99精品欧美| 欧美一区成人| 国模精品一区二区三区| 欧美伊人久久久久久午夜久久久久 | 亚洲人午夜精品| 欧美大片在线影院| 亚洲精品久久久久中文字幕欢迎你 | 国产亚洲精品久久久| 香蕉精品999视频一区二区| 久久久久久久999| 在线不卡视频| 欧美精选在线| 亚洲女性裸体视频| 久久综合久久综合久久| 亚洲国产视频a| 欧美日韩国产欧| 亚洲免费在线视频一区 二区| 久久精品视频在线观看| 亚洲成人资源网| 欧美精品二区三区四区免费看视频| 亚洲免费观看高清在线观看| 性欧美大战久久久久久久免费观看 | 久久综合网hezyo| 亚洲欧洲精品一区二区| 欧美一级专区| 最新国产精品拍自在线播放| 欧美三级资源在线| 久久国产毛片| 日韩一级视频免费观看在线| 久久成人国产| 99精品视频网| 黄色工厂这里只有精品| 欧美日韩mv| 久久不射2019中文字幕| 亚洲毛片av在线| 久久婷婷国产综合尤物精品| 亚洲最新视频在线| 伊人久久大香线蕉综合热线| 欧美激情二区三区| 久久福利毛片| 亚洲一级电影| 亚洲精品黄色| 免费在线观看一区二区| 亚洲一级片在线观看| 在线观看日韩专区| 国产精品男女猛烈高潮激情| 欧美成年人在线观看| 香蕉av777xxx色综合一区| 亚洲国产精品尤物yw在线观看 | 亚洲高清二区| 国产欧美va欧美va香蕉在| 欧美美女bbbb| 免费欧美在线视频| 久久久精品久久久久| 亚洲欧美日韩第一区| 99精品国产99久久久久久福利| 老司机精品视频网站| 欧美综合第一页| 亚洲欧美怡红院| 一二美女精品欧洲| 99re66热这里只有精品4| 在线观看成人小视频| 国产日韩欧美亚洲一区| 国产精品多人| 国产精品sss| 欧美理论在线播放| 欧美成人精精品一区二区频| 久久天天躁夜夜躁狠狠躁2022 | 亚洲一区三区在线观看| 一本久道久久综合狠狠爱| 91久久在线视频| 亚洲电影免费在线观看| 欧美福利视频网站| 亚洲大胆av| 欧美激情中文不卡| 欧美福利视频在线| 欧美大片在线看| 亚洲国产一区二区a毛片| 亚洲高清一区二| 亚洲人成毛片在线播放| 亚洲欧洲综合另类| 日韩性生活视频| 亚洲一区二区在线免费观看| 亚洲图片在线| 欧美一区中文字幕| 久热精品在线视频| 欧美国产一区二区| 欧美性猛交99久久久久99按摩| 国产精品成人一区二区| 国产精品一区久久| 影音先锋日韩精品| 亚洲精品日日夜夜| 亚洲天堂成人在线观看| 欧美一区二区日韩一区二区| 久久久久.com| 亚洲国产欧美日韩另类综合| 亚洲精品永久免费精品| 亚洲亚洲精品三区日韩精品在线视频| 亚洲综合电影| 麻豆精品网站| 国产精品家教| 伊人成人在线视频| 一区二区三区久久| 久久精品人人做人人爽电影蜜月| 欧美不卡福利| 一区二区三区国产| 久久国内精品视频| 欧美日韩国产大片| 国产一区二区三区黄| 亚洲精品日韩激情在线电影| 午夜精品免费| 亚洲国产精品ⅴa在线观看| 亚洲性感激情| 另类成人小视频在线| 国产精品视频久久| 亚洲美女精品久久| 欧美在线观看视频| 亚洲黄一区二区三区| 欧美一区二区三区视频免费| 欧美国产另类| 一区二区在线免费观看| 亚洲视频免费在线| 欧美激情精品久久久久久大尺度| 亚洲欧美另类综合偷拍| 欧美日韩精品一区二区三区| 悠悠资源网亚洲青| 久久国产精品久久久| 一区电影在线观看|