在讲这些内容之前,我先亮出这些代码的运行效果,来提高大家的兴趣吧,呵呵。
看,效果不错吧,接下来,我们进入正题,
继续上次的内容,我们发现WndProc函数和About函数被没有被winmain函数或其他函数调用,那么为什么写这些代码呢?
不知大家有没有发现,在这些编写这些函数时,都有一个前缀:CALLBACK。我们来看看他的定义:
凡是由你设计却由windows系统呼叫的函数,统称为callback函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
我们再来讲讲windows消息处理机制:消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。
我们学过switch语句,知道他长和case搭配,是一个判断选择代码。其功能就是控制业务流程流转的。而windows消息处理机制就是运用switch 和case,来选择消息,并进行分条处理。下面来看看代码:
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
可以看到他在处理消息时,选择了WM_PAINT,WM_DESTROY,WM_COMMAND这三条消息进行处理。来,我们看看度娘的解释:当窗口显示区域的一部分显示内容或者全部变为“无效”,以致于必须“更新画面”时,将由这个消息通知程序。
他其实就是一个重绘消息,通知程序重新绘制窗口,说白了,就是叫程序重新“画画”,把各种元素(如按钮,文字,标签等等)重新画出来。
WM_DESTROY:WM_DESTROY 是关闭程序的消息。在应用程序关闭时,会产生这个消息,从而调用PostQuitMessage函数销毁程序。
WM_COMMAND:补个函数我们暂时不讲,不过我们要知道,这是一个点击菜单,点击加速键,点击子窗口按钮,点击工具栏按钮时产生的消息。
我们可以自己选择一个消息来进行处理,而在这些消息之后是我们编写代码的地方,接下来,我来演示一个简单的示例:
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_LBUTTONDOWN:
MessageBox(hWnd, L"左键单击", L"左键单击",4);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
WM_LBUTTONDOWN是一个左键单击时的消息。
当用户左键按下时,应用程序就会产生一个WM_LBUTTONDOWN消息,从而执行我们定义的代码,弹出一个消息框——调用MessageBox函数,我们来看看,他各个参数的定义及用途:
int WINAPI MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
//其实它是根据Unicode定义的
WINUSERAPI int WINAPI MessageBoxA(
HWND hWnd ,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);
WINUSERAPI int WINAPI MessageBoxW(
HWND hWnd ,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType);
#ifdef UNICODE
#define MessageBox MessageBoxW //如果用的是Unicode,就用MessageBoxW
#else
#define MessageBox MessageBoxA
#endif
参数
1
|
TEXT(
//sometext)
|
1
|
TEXT(
//sometext)
|
uType参数
按钮参数
|
含义
|
MB_OK
|
默认值。有一个确认按钮在里面。
|
MB_YESNO
|
有是和否在里面。
|
MB_ABORTRETRYIGNORE
|
有Abort(放弃),Retry(重试)和Ignore(跳过)
|
MB_YESNOCANCEL
|
消息框含有三个按钮:Yes,No和Cancel
|
MB_RETRYCANCEL
|
有Retry(重试)和Cancel(取消)
|
MB_OKCANCEL
|
消息框含有两个按钮:OK和Cancel
|
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
|
#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L
#define MB_ICONHAND 0x00000010L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONASTERISK 0x00000040L
#define MB_USERICON 0x00000080L
#define MB_ICONWARNING MB_ICONEXCLAMATION
#define MB_ICONERROR MB_ICONHAND
#endif
#define MB_ICONINFORMATION MB_ICONASTERISK
#define MB_ICONSTOP MB_ICONHAND
#define MB_DEFBUTTON1 0x00000000L
#define MB_DEFBUTTON2 0x00000100L
#define MB_DEFBUTTON3 0x00000200L
#if(WINVER >= 0x0400)
#define MB_DEFBUTTON4 0x00000300L
#endif /* WINVER >= 0x0400 */
#define MB_APPLMODAL 0x00000000L
#define MB_SYSTEMMODAL 0x00001000L
#define MB_TASKMODAL 0x00002000L
#define MB_HELP 0x00004000L // Help Button
#endif /* WINVER >= 0x0400 */
#define MB_NOFOCUS 0x00008000L
#define MB_SETFOREGROUND 0x00010000L
#define MB_DEFAULT_DESKTOP_ONLY 0x00020000L
#define MB_TOPMOST 0x00040000L
#define MB_RIGHT 0x00080000L
#define MB_RTLREADING 0x00100000L
|
参数 | 含义 |
MB_ICONEXCLAMATION
| 一个惊叹号出现在消息框 |
MB_ICONWARNING
| 一个惊叹号出现在消息框 |
MB_ICONINFORMATION
| 一个圆圈中小写字母i组成的图标出现在消息框 |
MB_ICONASTERISK
| 一个圆圈中小写字母i组成的图标出现在消息框 |
MB_ICONQUESTION
| 一个问题标记图标出现在消息框 |
MB_ICONSTOP
| 一个停止消息图标出现在消息框 |
MB_ICONERROR
| 一个停止消息图标出现在消息框 |
MB_ICONHAND
| 一个停止消息图标出现在消息框 |
参数
|
含义
|
MB_APPLMODAL
| |
MB_SYSTEMMODAL
| |
MB_TASKMODAL
|
如果参数hwnd为NULL的话,那么除了所有属于当前线程高层次的窗口失效外,MB_TASKMODALL和MB_APPLMODAL一样。当调用应用程序或库没有一个可以得到的
窗口句柄时,使用此标志。但仍需要阻止输入到调用线程的其他窗口,而不是搁置其他线程。
|
当我左键窗口时:
运行效果如上图所示。