VC 新建一个Win32 Application的详细解释

标签:
从零开始学vcwin32applicationit |
分类: VC |
Win32
Application的第一个例子
VC 6中新建一个Win32 Application,在Source
Files中新建一个C++源文件WinMain.cpp,代码如下所示:
#include "stdafx.h"
HWND hWnd=NULL; // 保存 Windows 分配给程序的窗口句柄,它是全局的
LRESULT APIENTRY
MyWndProc(HWND,UINT,WPARAM,LPARAM);
void MyMsgLoop();
int APIENTRY
WinMain(HINSTANCE hInstance,
{
char
clsName[]="myWnd";
WNDCLASS wc;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = MyWndProc;
wc.cbClsExtra = 0L;
wc.cbWndExtra = 0L;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = clsName;
RegisterClass(&wc);
hWnd =
CreateWindow(clsName,"主窗口",
ShowWindow( hWnd, SW_SHOWDEFAULT ); // 显示窗口
UpdateWindow( hWnd );
MyMsgLoop();
return 0;
}
LRESULT APIENTRY
MyWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam ) {//
消息处理
switch(message) {
case WM_CREATE:
case WM_CLOSE:
case WM_SIZE:
case WM_DESTROY: // 当退出消息的时候,进行处理...
case WM_KEYUP:
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
void MyMsgLoop()
{
MSG msg;
BOOL receiveMessage;
PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
while(msg.message != WM_QUIT) { // 消息循环
}
}
通过这个简单的例子,理解Windows基于消息映射的机制。
先从主函数WinMain开始看。
因为要创建一个Windows窗体,所以首先需要注册一个Windows类,因为调用CreateWindow函数的时候,需要根据注册的Windows类的信息来创建一个窗体的。
Windows定义了一个WNDCLASS结构,用来描述一个Windows窗体类的信息,定义如下所示:
typedef struct
_WNDCLASS {
} WNDCLASS;
关于WNDCLASS结构的各个成员变量的含义,可以查看MSDN了解。在上面的程序中,直接设置WNDCLASS结构变量wc的成员:
wc.style =
CS_OWNDC | CS_VREDRAW | CS_HREDRAW; // 窗体风格
wc.lpfnWndProc = MyWndProc; //
wc.cbClsExtra = 0L;
wc.cbWndExtra = 0L;
wc.hInstance = hInstance; // 窗体进程实例的句柄,通过WinMain主函数传递进来
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); //
背景画刷,也就是窗口显示背景颜色
wc.lpszMenuName = NULL;
wc.lpszClassName = clsName; // 注册的Windows类名称
接下来,调用RegisterClass函数进行注册:
RegisterClass(&wc);
该API函数声明如下:
ATOM
RegisterClass(
CONST WNDCLASS *lpWndClass
);
如果注册成功,返回ATOM类型,也就是WORD类型,也就是无符号短整型,如下所示:
typedef unsigned
short
注册完成之后,具备了创建一个窗体的信息,开始调用API函数CreateWindow来进行窗体的创建工作,上述程序中创建如下所示:
hWnd =
CreateWindow(clsName,"主窗口",
窗体创建成功以后,会返回这个窗体的一个句柄,赋给定义的全局的HWND hWnd。关于CreateWindow函数,声明如下:
HWND
CreateWindow(
LPCTSTR lpClassName, // 注册的类的指针
LPCTSTR lpWindowName, // 窗体名称字符串指针
DWORD
dwStyle,
int
x,
int
y,
int
nWidth,
int
nHeight,
HWND
hWndParent,
HMENU
hMenu,
HANDLE
hInstance,
LPVOID
lpParam
);
获取到了创建成功之后的窗体的句柄,然后根据这个返回的句柄来显示这个成功创建的窗体,程序中调用API函数ShowWindow进行显示:
ShowWindow( hWnd, SW_SHOWDEFAULT ); // 显示窗体
其中,ShowWindow函数的声明如下:
BOOL
ShowWindow(
HWND
hWnd,
);
其中,窗体的状态nCmdShow取值可以是如下所示的值:
SW_FORCEMINIMIZE
SW_HIDE Hides
SW_MAXIMIZE
SW_MINIMIZE
SW_RESTORE
SW_SHOW
SW_SHOWDEFAULT
SW_SHOWMAXIMIZED
SW_SHOWMINIMIZED
SW_SHOWMINNOACTIVE
SW_SHOWNA
SW_SHOWNOACTIVATE
SW_SHOWNORMAL
这样,一个窗体就显示出来了,窗体的客户区内是空的。
UpdateWindow函数用于更新窗口,该函数更新窗口的时候会向指定的窗体的进程发送消息,如果被更新的客户区为空,说明窗体没有接收到消息。
最后,调用了自定义了MyMsgLoop函数,进入消息循环。这时,窗体进入一种等待状态,等待消息的来到,然后在该函数中对不同类型的消息进行处理。
我们看一下MyWndProc函数的实现,它是窗口进程,用来根据窗体接收到的消息并进行处理。窗口进程函数的声明如下所示:
LRESULT CALLBACK
WindowProc(
HWND
hwnd,
UINT
uMsg,
WPARAM wParam, // first message parameter
LPARAM lParam
);
可以自定义自己的窗口进程函数,包含上述四个参数。然后根据消息进行选择处理方式。
上述程序中,给出了几种典型的消息,你可以根据需要在case语句中实现处理的过程,处理完成之后,返回DefWindowProc(hWnd, message, wParam, lParam),这时是一个默认的窗口进程函数,可以处理任何Windows消息。
函数MyMsgLoop主要对消息进行管理的,其中,调用PeekMessage函数会检查线程消息队列,根据指定的消息的结构并从消息队列中取出消息,而且,可以设定消息在被PeekMessage函数处理完成以后,是否保留在线程消息队列中,从PeekMessage函数的声明来看:
BOOL
PeekMessage(
LPMSG
lpMsg,
HWND
hWnd,
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax, // last message
UINT
wRemoveMsg
);
最后一个参数wRemoveMsg表示是否在调用PeekMessage函数处理之后从线程消息队列中移除,它有两个取值:
PM_NOREMOVE
PM_REMOVE
对该程序进行编译,运行,显示出一个窗体,如图所示:
根据在MyWndProc函数中定义的窗口进程,可以通过向窗体传递不同类型的消息,来看case语句中对应的输出,有助于理解Windows的消息机制