VS2010 C++ MFC框架学习笔记5 - C++面向对象编程基础1
时隔一周多,再继续C++之路。
1. MSG结构体
Windows应用程序响应操作系统的消息,通过MSG结构体传达消息信息:
2. 消息队列
Windows消息队列,被应用程序逐条响应
注意2点:
1. 消息——用户操作、程序状态
2. 消息响应
3. WinMain函数——VC++的入口函数
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,//实例的句柄,标识这个当前运行的实例
_In_ HINSTANCE hPrevInstance, //实例的句柄,标识previous运行的实例
_In_ LPSTR lpCmdLine, //LongPointer_String 长指针,指向一个String , 运行程序时,传入的命令行参数。ARGC ARGV
_In_ int nCmdShow //指定窗口显示时的状态(最大化、适中、隐藏。。。)
);
4. 窗口应用程序的创建步骤
- 设计一个窗口类
- 注册窗口
- 创建窗口
- 显示及更新窗口
typedef struct tagWNDCLASS {
UINT style; //Style这里是窗口类型,见上面的解释
WNDPROC lpfnWndProc; //窗口过程函数的指针,用这个函数来处理相应的消息
int cbClsExtra; //分配的额外的内存空间,通常称为类的附加内存
int cbWndExtra; //窗口的附加内存
HINSTANCE hInstance; // = hInstance
HICON hIcon; //图标句柄wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
HCURSOR hCursor; //光标句柄wndclass.hCursor=LoadCursor(NULL,IDC_CROSS);
HBRUSH hbrBackground; //窗口背景被这个参数控制
//画刷的句柄wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
LPCTSTR lpszMenuName; //长指针常量String,用来设定菜单的名字,NULL
LPCTSTR lpszClassName; //常量字符串,设定类的名字。"weixin",创建窗口时,名字要与其一致,否则创建不出窗口
} WNDCLASS, *PWNDCLASS;
怎么使用:
以上的WNDCLASS中UINT style参数解释:
- UINT style; //Style这里是窗口类型,用16进制的某一位为1来表示不同的类型设置,如果要同时具备俩属性,就用 | (或运算符)来分隔,如:wndclass.style=CS_HREDRAW | CS_VREDRAW; 其中,CS_HREDRAW是宏定义的,其本质是0x0001
5. 窗口的定义和创建
窗口类定义好了,就应该用这个Class来创建一个窗口了。
CreateWindow函数的说明:
hwnd=CreateWindow(“WeiXin”, “欢迎使用我”,“WS_OVERLAPPEDWINDOW”,"…
1.ClassName
2.WindowName, Title
3.WindowStyle
4. 窗口水平坐标
5. 窗口垂直坐标
6. 窗口宽度
7. 窗口高度
8. HWND窗口句柄,指示一个父窗口的句柄,NULL
9. HMENU子菜单句柄
10. 实例号,传入hInstance即可
11. lpRaram, 创建时间,NULL
6. 窗口的显示和更新
ShowWindow(HWIND, 显示状态); //最大化,最小化,normal
UpdateWindow(hwnd);
7.消息循环
MSG msg; //定义消息
//进入消息循环
关于GetMessage函数:程序通过GetMessage从消息队列中获得消息。
1. LPMSG lpMsg,取到消息后,指向应该放入的目标消息结构体的地址,比如此处是msg的地址,拿到它以后就将取到的消息可以存入msg了。
2. 从哪个窗口中调用消息
3. 最小消息值,Filter
4. 消息最大值,Filter
TranslateMessage(&msg); //将按键的wmkeydown & wmkeyup消息转换成wmchar消息,放到消息队列中
DispatchMessage(&msg); //将受到的消息,路由给OS,再调用 *窗口过程函数* 进行处理。
8. 窗口过程函数
MSDN中搜索“WindowProc”,得到它的说明:
窗口过程函数的形式必须这样,函数名可以改,参数名可变。消息结构体的前四个参数直接传给她的四个参数。
在学习过程中,对于函数,要多用MSDN查,对于大写字母的宏定义等搞不清的,用右键Go to definition查。
中间我们对消息进行了分类,有:
WM_PAINT – 窗口粉刷消息
WM_CHAR – 按键消息
WM_LBUTTONDOWN – 鼠标左键按下消息
WM_CLOSE – 窗口关闭被按下消息,此时我们调用了DestroyWindow(); 函数,调用时,它会销毁窗口,返回WM_DESTROY消息
WM_DESTROY – 焚毁完成消息,此时我们调用了PostQuitMessage(); 函数,退出程序。它会投递一个WM_QUIT消息到队列中,这个WM_QUIT被GetMessage函数取到时,GetMessage会返回一个0,此时在WinMain函数的 取消息 循环中会退出while循环,导致整个程序退出。
至此,我们就分析完了消息处理函数里的内容,最后,消息处理函数里有个default: 语句,内含的指令是当消息没有落在上述case里时,能有个默认的消息处理机制。
9. 关于窗口过程函数声明时的CALLBACK
LRESULT CALLBACK WinSunProc( //LRESULT - Long Int Result Code
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
右键 go to definition看, #define CALLBACK __stdcall, 其中,stdcall是和cdecl一样的“调用约定”,一种是标准调用约定(PASCAL),主要定义了参数传递顺序、堆栈清除机制。msdn查stdcall,即可。因为VC++中默认使用 cdecl 调用约定,要用 stdcall 的调用习惯,就要标注 CALLBACK 一下。
在 菜单-工程-设置-C/C++ 中 代码生成选项下,可以修改这个约定。
10. WinMain窗口程序的创建过程及源代码
新建一个工程,选择win32 应用程序,命名为WinMain
再新建一个WinMain.cpp源文件,编写这个源文件:
1. /* File: WinMain.cpp
2. * Date: 2015-6-26 14:11:15
3. * Author: Sonictl
4. */
5.
6. //Includes
7. #include <Windows.h>
8. #include <stdio.h>
9.
10. //Declare the WindowProc function
11. LRESULT CALLBACK WindowProc(
12. _In_ HWND hwnd,
13. _In_ UINT uMsg,
14. _In_ WPARAM wParam,
15. _In_ LPARAM lParam
16. );
17.
18. //Declare and define WinMain function
19. int CALLBACK WinMain(
20. _In_ HINSTANCE hInstance,
21. _In_ HINSTANCE hPrevInstance,
22. _In_ LPSTR lpCmdLine,
23. _In_ int nCmdShow
24. ){
25. //Declare a WndClass Obj: wndcls
26. WNDCLASS wndcls;
27. //Initial WndObj
28. wndcls.cbClsExtra=0;
29. wndcls.cbWndExtra=0;
30. wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
31. wndcls.hCursor=LoadCursor(NULL, IDC_CROSS);
32. wndcls.hIcon=LoadIcon(NULL,IDI_WINLOGO);
33. wndcls.hInstance=hInstance;
34. wndcls.lpfnWndProc=WindowProc;
35. wndcls.lpszClassName="MyWndCls2016"; //class name
36. wndcls.lpszMenuName=NULL; //NULL menu
37. wndcls.style=CS_HREDRAW | CS_VREDRAW; //window style
38.
39. //Register Wnd
40. RegisterClass(&wndcls);
41. HWND hwnd; //declare handle to this window
42. hwnd=CreateWindow("MyWndCls2016", "China Intelligent Robotic Center", \
43. WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL,\
44. hInstance, NULL);
45.
46. //Show Wnd
47. ShowWindow(hwnd, SW_SHOWNORMAL); //show window
48. //Update Wnd
49. UpdateWindow(hwnd); //update window
50. //MsgLoop
51. MSG msg;
52. while(GetMessage(&msg, NULL, 0, 0)){
53. TranslateMessage(&msg);
54. DispatchMessage(&msg);
55. }
56. return 0;
57. }
58. //Define Window Proc Function
59. LRESULT CALLBACK WindowProc(
60. _In_ HWND hwnd,
61. _In_ UINT uMsg,
62. _In_ WPARAM wParam,
63. _In_ LPARAM lParam
64. ){
65. //hadle messages:
66. switch(uMsg){
67. case WM_CHAR:
68. char szChar[20];
69. sprintf(szChar, "Your char is %d", wParam);
70. //LPCTSTR lpctstr = (LPCTSTR)szChar; //type transfer
71. //MessageBox(hwnd,"your input is","weixin",0); //lpctstr is LPCTSRT type
72. MessageBox(hwnd,szChar,"Report Message",0); //lpctstr is LPCTSRT type
73. break;
74. case WM_LBUTTONDOWN:
75. MessageBox(hwnd,"mouse clicked", "Report Message", 0);
76. HDC hdc;
77. hdc=GetDC(hwnd);
78. TextOut(hdc,0,50,"智能机器人技术研究中心",strlen("智能机器人技术研究中心"));
79. ReleaseDC(hwnd,hdc);
80. break;
81. case WM_PAINT:
82. HDC hDC;
83. PAINTSTRUCT ps;
84. hDC=BeginPaint(hwnd, &ps);
85. TextOut(hDC,0,0,"机器人改变世界", strlen("机器人改变世界"));
86. EndPaint(hwnd, &ps);
87. break;
88. case WM_CLOSE:
89. if(IDYES==MessageBox(hwnd,"Are u sure to Exit?","Warning",MB_YESNO)){
90. DestroyWindow(hwnd);
91. }
92. break;
93. case WM_DESTROY:
94. PostQuitMessage(0);
95. break;
96. default:
97. return DefWindowProc(hwnd, uMsg, wParam, lParam);
98. }
99. return 0;
100. }
可能会遇到“a value of type “const char *” cannot be assigned to an entity of type “LPCWSTR””错误,
writingL"MyString"
in place of"MyString"
即可。原因是Your code is written to compile as ANSI but your solution settings include
_UNICODE
/
UNICODE
.
http://stackoverflow.com/questions/18470791/c-build-errors-on-win32-school-application
所以在VS2011中,我们的程序作了一点点修改,把编译环境设置成“多字符集”(Multi-Byte Character Set),就可以避免这样转换来转换去。就是在“Project->Configuration Properties->General->Character Set,选择”Use Unicode Character Set“就是使用Uncode字符集,选择” Use Multi-Byte Character Set“就是多字节字符集。
http://jingyan.baidu.com/article/6525d4b1090139ac7d2e9413.html
运行成功.