int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wndclass; //声明结构体变量
RegisterClass (&wndClass);//注册窗口
CreateWindow (……);//创建窗口
ShowWindow (……);//显示
UpdateWindow (.....);//更新
while(Getmessage(&msg,NULL,0,0))//进入消息循环
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
你随便找一本关于windows编程的书籍来看都会看到类似于上面的代码,可能是完整版,这里只是为了理解程序结构,所以不需要完整的可执行程序。
先说一下WinMain函数的参数意义:
WinMain函数的第一步是要建立、登记应用程序的窗口类。就像小米生产手机一样,首先需要对手机进行设计,什么样子,什么配置等等。窗口类是定义窗口属性的模板,这些属性包括窗口样式、鼠标形状,菜单,窗口函数。只有先设计出小米的外观,才能开始生产小米手机,同样,只有先建立窗口类,才能创建Windows应用程序窗口。
窗口类的定义如下:
typedef struct _WNDCLASS {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;
它是一个结构体,里面包含设计一个窗口的各种信息,就像小米手机的设计信息需要包括屏幕尺寸,机身厚度,宽度,高度,颜色,电池容量,内存……关于WNDCLASS的详细信息请点击这儿
1)style用于控制窗口的特性
CS_BYTEALIGNCLIENT: 在字节边界上(在x方向上)定位窗口的用户区域的位置
CS_BYTEALIGNWINDOW: 在字节边界上(在x方向上)定位窗口的位置
CS_CLASSDC: 该窗口类的所有窗口实例都共享一个窗口类DC
CS_DBLCLKS: 允许向窗口发送双击鼠标键的消息
CS_GLOBALCLASS: 当调用CreateWindow 或 CreateWindowEx
函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给
RegisterClass 的 hInstance参数不同。如果不指定该风格,则这两个 hInstance 必须相同。
CS_HREDRAW: 当水平长度改变或移动窗口时,重画整个窗口
CS_NOCLOSE: 禁止系统菜单的关闭选项
还有几个特性我们有列出来,这些特性有的是可以用“|”来进行组合的。
lpfnWndproc:是一个指向窗口内消息处理的指针,该消息处理函数通常称为窗口函数,用于接收Windows发送给窗口的消息,并执行相应任务。可以理解为生产小米的代工厂(不是很恰当的比喻)。
wndclass.style =0; // 窗口类型为缺省类型CS_ Class Style
wndclass.lpfnWndProc=WndProc; //定义窗口处理函数
wndclass.cbClsExtra=0; //窗口类无扩展
wndclass.cbWndExtra=0; //窗口实例无扩展
wndclass.hInstance=hInstance; //当前实例句柄
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); //窗口的最小化图标为缺省图标
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); // 窗口采用箭头光标
wndclass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景为白色
wndclass.lpszMenuName=NULL; //窗口无菜单
wndclass.lpszClassName=lpszClassName; //窗口类名为“窗口”
顺带说一下这里面的2个常用函数
HICON
LoadIcon(
HINSTANCE hInstance,
LPCTSTR lpIconName
);
参数lpIconName指明程序图标,可以取一些预设值,
2.GetStockObject函数,用于加载对象资源,原型如下:
HGDIOBJ GetStockObject(int fnObject);
参数fnObject指定对象类型,常见类型如下:
窗口设计完成后,必须要注册窗口类,,当对WNDCLASS结构域一一复制后,就可以注册了,一般调用RegisterClass函数实现窗口类的注册。原型如下:
ATOM RegisterClass(CONST WNDCLASS *lpWndClass)
如果注册失败,RegisterClass返回非0值,程序终止,为0则表示注册成功,程序继续进行。
HWND CreateWindow(
LPCTSTR lpClassName,//注册窗口类名
LPCTSTR lpWindowName,//窗口标题名
DWORD dwStyle, //窗口风格
int x,//显示窗口水平位置
int y,//显示窗口垂直位置
int nWidth,//窗口宽度
int nHeight,//窗口高度
HWND hWndParent,//父窗口句柄
HMENU hMenu,//菜单句柄
HANDLE hlnstance,//应用程序句柄
LPVOID lpParam)//指向传递一个窗口的指针型函数
}
BOOL ShowWIndow(
HWND hWnd,
int nCmdShow
);
其中hWnd是窗口句柄,指定显示哪一个窗口,参数nCmdShow决定窗口的显示模式,这三个模式SW_MINIMIZE(最小化)、SW_SHOWMAXMIZED(最大化)、SW_HIDE(影藏),SW_SHOWNORMAL(普通化)。
Windows为每个运行程序维护一个消息队列,当单机鼠标按键时,Windows并不是直接报这个时间发送给应用程序,而是翻译成一个消息,并把这个消息,放置到应用程序所属的消息队列中去,形成消息循环,在有应用程序从队列中去获取消息。
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
*TranslateMessage函数不会修改原有消息,只是产生新消息,而DispatchMessage函数则用于将消息传回给操作系统,由操作系统调用窗口函数对消息进行响应,而窗口函数对消息进行处理
LRESULT CALLBACK WndProc( //WndProc名称可自由定义
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
细心的读者会发现这个函数的阐述和MSG结构的前4个成员完全相同。WinProc函数通常包括一个多分支switch结构语句,每个case语句对应一种消息。
LRESULT WINAPI WndProc( HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(NULL);
break;
case ..
.
.
.
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
读者可能会由点疑问:为什么没看到WinMain函数显示调用Winproc函数呢?
*请注意,WInProc函数头部有一个CALLBACK标记,表明这是一个回调函数。什么是回调函数呢?简单的说就是等着别人来调用的函数,这些函数的原因都是由调用者设计好,使用的时候只要按照原型重新定义一个函数,然后将函数指针传递过去,我们在前面设计窗口类的时候就有WNDPROC这一项,就是告诉系统我这个类的消息处理函数是谁,因此回调函数是严格按照系统的规定进行说明和定义,函数的调用约定,参数都是固定的。就像系统是最高法院,你的winproc是地方最高法院,专门用来处理当地案件,一般发生了一个案件,不会直接由最高法院处理,而是最高法院让事件发生的所在地的地方法院来处理,但是作为地方法院,一切都有按照规定的流程来。
(注:本文参考书籍博客整理而成)
原文:http://blog.csdn.net/q__y__l/article/details/51275640