生活的天平本不平衡,只有通过努力改变其偏向。

@笔记:窗口回调类程序结构的一种扩展写法

2008-08-31

//转载请保留以下这段内容
//此文章为本人学习笔记和心得,仅供您学习参考,不能保证其正确性。
//您在阅读本篇文章是有什么意见或看法,需要和本人探讨或指出错误,请到本篇文章处给我留言
//来源: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这个数组即可,其的部分都不看了。可能在这个例子这种方式的优点还不是太明显,不过在我最近做的模块中,使用这种方法效果不错。好久没写什么东西了,一点开发心得,记之。

作者:lonkil | 分类目录:编程开发 | 标签:

2 条评论

  1. Trajon.BWL 说道:

    代码看了。一开始为前者折服,因为用消息做开关我是没有见过滴,想法有点意思,而你则是采用数组来做的。大哥的代码是从中摘的,所以一些东西直接用而没有提及,比如那个gt变量。不过我至始至终没看到所谓的“窗口回调”,只见到了通过消息相应进行窗口的创建。