对于有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循环,不停的在判断是否有事件发生
----------备注------------
简单先写这些,本文未完成,对关键函数以及变量的解释不够,在后面的研究深入中慢慢加入