时隔一周多,再继续C++之路。
Windows应用程序响应操作系统的消息,通过MSG结构体传达消息信息:
Windows消息队列,被应用程序逐条响应
注意2点:
1. 消息——用户操作、程序状态
2. 消息响应
int CALLBACK WinMain( _In_ HINSTANCE hInstance,//实例的句柄,标识这个当前运行的实例 _In_ HINSTANCE hPrevInstance, //实例的句柄,标识previous运行的实例 _In_ LPSTR lpCmdLine, //LongPointer_String 长指针,指向一个String , 运行程序时,传入的命令行参数。ARGC ARGV _In_ int nCmdShow //指定窗口显示时的状态(最大化、适中、隐藏。。。) );
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参数解释:
窗口类定义好了,就应该用这个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
ShowWindow(HWIND, 显示状态); //最大化,最小化,normal
UpdateWindow(hwnd);
MSG msg; //定义消息
//进入消息循环
关于GetMessage函数:程序通过GetMessage从消息队列中获得消息。
1. LPMSG lpMsg,取到消息后,指向应该放入的目标消息结构体的地址,比如此处是msg的地址,拿到它以后就将取到的消息可以存入msg了。
2. 从哪个窗口中调用消息
3. 最小消息值,Filter
4. 消息最大值,Filter
TranslateMessage(&msg); //将按键的wmkeydown & wmkeyup消息转换成wmchar消息,放到消息队列中
DispatchMessage(&msg); //将受到的消息,路由给OS,再调用 窗口过程函数 进行处理。
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里时,能有个默认的消息处理机制。
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++ 中 代码生成选项下,可以修改这个约定。
新建一个工程,选择win32 应用程序,命名为WinMain
再新建一个WinMain.cpp源文件,编写这个源文件:
/* File: WinMain.cpp * Date: 2015-6-26 14:11:15 * Author: Sonictl */ //Includes #include <Windows.h> #include <stdio.h> //Declare the WindowProc function LRESULT CALLBACK WindowProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ); //Declare and define WinMain function int CALLBACK WinMain( _In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow ){ //Declare a WndClass Obj: wndcls WNDCLASS wndcls; //Initial WndObj wndcls.cbClsExtra=0; wndcls.cbWndExtra=0; wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); wndcls.hCursor=LoadCursor(NULL, IDC_CROSS); wndcls.hIcon=LoadIcon(NULL,IDI_WINLOGO); wndcls.hInstance=hInstance; wndcls.lpfnWndProc=WindowProc; wndcls.lpszClassName="MyWndCls2016"; //class name wndcls.lpszMenuName=NULL; //NULL menu wndcls.style=CS_HREDRAW | CS_VREDRAW; //window style //Register Wnd RegisterClass(&wndcls); HWND hwnd; //declare handle to this window hwnd=CreateWindow("MyWndCls2016", "China Intelligent Robotic Center", \ WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL,\ hInstance, NULL); //Show Wnd ShowWindow(hwnd, SW_SHOWNORMAL); //show window //Update Wnd UpdateWindow(hwnd); //update window //MsgLoop MSG msg; while(GetMessage(&msg, NULL, 0, 0)){ TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } //Define Window Proc Function LRESULT CALLBACK WindowProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ){ //hadle messages: switch(uMsg){ case WM_CHAR: char szChar[20]; sprintf(szChar, "Your char is %d", wParam); //LPCTSTR lpctstr = (LPCTSTR)szChar; //type transfer //MessageBox(hwnd,"your input is","weixin",0); //lpctstr is LPCTSRT type MessageBox(hwnd,szChar,"Report Message",0); //lpctstr is LPCTSRT type break; case WM_LBUTTONDOWN: MessageBox(hwnd,"mouse clicked", "Report Message", 0); HDC hdc; hdc=GetDC(hwnd); TextOut(hdc,0,50,"智能机器人技术研究中心",strlen("智能机器人技术研究中心")); ReleaseDC(hwnd,hdc); break; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; hDC=BeginPaint(hwnd, &ps); TextOut(hDC,0,0,"机器人改变世界", strlen("机器人改变世界")); EndPaint(hwnd, &ps); break; case WM_CLOSE: if(IDYES==MessageBox(hwnd,"Are u sure to Exit?","Warning",MB_YESNO)){ DestroyWindow(hwnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; }
L"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
运行成功.