@笔记:窗口回调类程序结构的一种扩展写法
//转载请保留以下这段内容
//此文章为本人学习笔记和心得,仅供您学习参考,不能保证其正确性。
//您在阅读本篇文章是有什么意见或看法,需要和本人探讨或指出错误,请到本篇文章处给我留言
//来源:http://www.vcfans.com/2008/08/window-callback-class-structure-of-a-program-to-expand-wording.html
//By Lonkil (lonkil_at_gmail.com)
//2008-8-31
其实本篇文章代码结构早已不是什么新鲜写法了,只不过我一直没有在意吧了。前段时间在公司的一个模块中看到一位同事,这样写才引起我的注意。和罗牛人探讨了一下,便有了此文。现在想想最早见此种写法,是在侯捷先生写的《深入浅出MFC》中,他是在也是在模拟MFC消息循环时用的。现在对比下传统写法和我说的“新的”写法。
我的以前写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | LRESULT WndProc(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_KEYDOWN: pressKey(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam); break; case WM_Paint: DrawDC(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam); break; case WM_DESTROY: DestroyWin(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam); break; case WM_COMMAND: Command(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam); break; } return DefWindowProc(hwnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0 ; wc.cbWndExtra = 0 ; wc.hInstance = hInstance; wc.hIcon = LoadIcon( hInstance,MAKEINTRESOURCE(IDI_ICON1) ); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH) COLOR_WINDOW ; wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("class_name") ; RegisterClass(&wc); m_hwnd = CreateWindowEx(NULL,TEXT("class_name"),TEXT("window title"),WS_SYSMENU,0,0,width,height,NULL,NULL,hInstance,NULL ); ............. } |
下面我用新的写法实现上面的功能,main函数保持不变:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | typedef void (*MsgCallback)(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam); typedef const struct _MsgStruct { UINT msgID; //消息类型 MsgCallback pMsgCallback; //函数指针 }MsgStruct; static MsgStruct MsgProTable[] = { {WM_KEYDOWN, pressKey}, {WM_Paint, DrawDC}, {WM_DESTROY, DestroyWin}, {WM_COMMAND, Command}, {0, NULL}//此处也可不写,在循环判定采用sizeof(MsgProTable)/sizeof(MsgStruct)的方式,也可。 }; LRESULT WndProc(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam) { MsgStruct *pMsgStruct=MsgProTable; for(; 0 != pMsgStruct->msgID; pMsgStruct++ ) { if( msg == pMsgStruct->msgID ) { pMsgStruct->pMsgCallback(hwnd, msg, wParam, lParam); break; } } return DefWindowProc(hwnd, msg, wParam, lParam); } |
这样结构的写法,结构非常清楚(个人认为),方便以后的扩展,扩展时直接修改MsgProTable这个数组即可,其的部分都不看了。可能在这个例子这种方式的优点还不是太明显,不过在我最近做的模块中,使用这种方法效果不错。好久没写什么东西了,一点开发心得,记之。
2 条评论
代码看了。一开始为前者折服,因为用消息做开关我是没有见过滴,想法有点意思,而你则是采用数组来做的。大哥的代码是从中摘的,所以一些东西直接用而没有提及,比如那个gt变量。不过我至始至终没看到所谓的“窗口回调”,只见到了通过消息相应进行窗口的创建。
发布的问题。这个代码着色系统将将指针的调用符->, 转成编码>b了,汗。