对于有vb或者c#开发经验的程序员来说,窗体应用程序不过是拖拖控件了事,下面介绍一种比较古老的技术,也就所谓win32开发,使用windows函数库来创建windows应用程序
#define WIN32_LEAN_AND_MEAN #define WindowsName "win1" #include <Windows.h> #include <WindowsX.h> LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) { PAINTSTRUCT ps; HDC hdc; switch(msg) { //创建 case WM_CREATE: return 0; break; //重绘 case WM_PAINT: hdc=BeginPaint(hwnd,&ps); return 0; break; //销毁 case WM_DESTROY: PostQuitMessage(0); break; default: break; } return DefWindowProc(hwnd,msg,wparam,lparam); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpcmdline,int ncmdshow) { //窗体类 WNDCLASSEX winclass; HWND hwnd; MSG msg; winclass.cbSize=sizeof(WNDCLASSEX); winclass.style=CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW; winclass.lpfnWndProc=WindowProc; winclass.cbClsExtra=0; winclass.cbWndExtra=0; winclass.hInstance=hInstance; winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); winclass.hCursor=LoadCursor(NULL,IDC_ARROW); winclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName=NULL; winclass.lpszClassName=WindowsName; winclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION); //注册窗体 if(!RegisterClassEx(&winclass)) { return 0; } //创建 if(!(hwnd=CreateWindowEx(NULL, WindowsName, "我的第一个窗体", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0, 0, 400, 400, NULL, NULL, hInstance, NULL ))) { return 0; } while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } //while(true) //{ // if(PeekMessage(&msg,hwnd,0,0,PM_REMOVE) && PeekMessage(&msg,hwnd,0,0,PM_REMOVE)) // { // MessageBox(NULL,"test","标题",NULL); // if(msg.message==WM_QUIT) // { // break; // } // TranslateMessage(&msg); // DispatchMessage(&msg); // } //} return msg.wParam; }
这段代码可以在vs2010中的c++项目中编译成功,有空会写出相应的文章
短短80多行代码足以创建一个黑色背景的窗体
涵盖了:
1、注册windows类
2、创建窗体
3、事件处理
4、主事件循环
我尝试每句话都解释一下
#define WIN32_LEAN_AND_MEAN
这句话的意思是不想要使用MFC来开发,具体什么是MFC,请另百度搜索
#define WindowsName "win1" #include <Windows.h> #include <WindowsX.h>
第一句为宏定义,把WindowsName定义为"win1"的别名,用来给窗体起名字的
第二和第三句分别导入两个函数库,用来进行windows开发的最基本函数库
LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) { PAINTSTRUCT ps; HDC hdc; switch(msg) { //创建 case WM_CREATE: return 0; break; //重绘 case WM_PAINT: hdc=BeginPaint(hwnd,&ps); return 0; break; //销毁 case WM_DESTROY: PostQuitMessage(0); break; default: break; } return DefWindowProc(hwnd,msg,wparam,lparam); }
这是回调函数。
对窗体产生的事件进行处理
比如有
WM_CREATE创建,WM_PAINT绘制,WM_DESTROY销毁
而触发这三种事件的条件是传入了怎样的消息msg
当msg符合创建条件时,就会进入switch条件分支的WM_CREATE中(这简直“太容易理解了”)
总之msg的赋值你并不需要关注,这是系统替我们赋值的
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpcmdline,int ncmdshow)
这句话是win32程序的标准main函数,也就所谓大门,main方法不必过多赘述,跟其他语言一个意思
只不过是多了一点点其他的东西,比如这个int WINAPI WinMain的写法就是十分奇葩,其实就是int WinMain中间多了一个WINAPI
这个WINAPI规定了函数参数的入栈方式是最右边先入栈,这不需要过多的关注,在以后的研究中会搞明白入栈方式对编程的影响。
//窗体类 WNDCLASSEX winclass; HWND hwnd; MSG msg;
第一句话注册了一个窗体类,由于win32编程是用c语言开发的,说是类,但没有class关键字,经过一步步F12追踪源代码,我发现WNDCLASSEX是一个结构体struct, 用来规定窗体长什么样子
HWND hwnd是一个窗体句柄,也就所谓窗体的一个身份标识,再简单的理解,就是身份证
MSG msg是消息,用来确定是执行绘制窗体还是创建窗体,或者是销毁窗体
winclass.cbSize=sizeof(WNDCLASSEX); winclass.style=CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW; winclass.lpfnWndProc=WindowProc; winclass.cbClsExtra=0; winclass.cbWndExtra=0; winclass.hInstance=hInstance; winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); winclass.hCursor=LoadCursor(NULL,IDC_ARROW); winclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName=NULL; winclass.lpszClassName=WindowsName; winclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
规定了很多,如窗体的样式,光标,鼠标,背景颜色等等,其中有两句很重要
winclass.lpfnWndProc=WindowProc;
winclass.lpszClassName=WindowsName;
第一句话规定了本窗体的回调函数是谁,第二句话规定了本窗体的名字叫什么
//注册窗体 if(!RegisterClassEx(&winclass)) { return 0; }
用RegisterClassEx来注册窗体,只有注册过的窗体才能使用,注册失败就让WinMain主函数返回0
//创建 if(!(hwnd=CreateWindowEx(NULL, WindowsName, "我的第一个窗体", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0, 0, 400, 400, NULL, NULL, hInstance, NULL ))) { return 0; }
创建窗体,规定了大小之类的琐事
while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
消息循环,用来转发消息,确定你是要做什么事,比如WM_CREATE创建,WM_PAINT绘制,WM_DESTROY销毁
而且这还是个while循环,不停的在判断是否有事件发生
----------备注------------
简单先写这些,本文未完成,对关键函数以及变量的解释不够,在后面的研究深入中慢慢加入