相对于DOS程序的main函数,Windows应用程序也有一个入口点函数--WinMain。当操作系统启动一个程序时,它将调用程序的WinMain函数开始执行代码;当WinMain函数返回时,应用程序就结束了。
窗口的诞生
- 设计窗口类:Windows是基于窗口的操作系统,下图显示了一个普通的Windows窗口:
操作系统通过窗口数据结构来管理窗口,该数据结构包含了一个窗口的所有信息,窗口数据结构定义如下:
typedef struct _WNDCLASS { UINT style; // 窗口类型 WNDPROC lpfnWndProc; <span style="white-space:pre"> </span>//窗口处理函数 int cbClsExtra; //窗口扩展 int cbWndExtra; //窗口实例扩展 HINSTANCE hInstance; <span style="white-space:pre"> </span>//实例句柄 HICON hIcon; <span style="white-space:pre"> </span>//窗口的最小化图标 HCURSOR hCursor; <span style="white-space:pre"> </span>//窗口鼠标光标 HBRUSH hbrBackground; <span style="white-space:pre"> </span>//窗口背景色 LPCTSTR lpszMenuName; <span style="white-space:pre"> </span>//窗口菜单 LPCTSTR lpszClassName;<span style="white-space:pre"> </span>// 窗口类名 } WNDCLASS
参数说明:
style:指定类风格,这些风格可以通过按位或操作组合起来。(CS_HREDRAW、CS_VREDRAW、CS_BYTEALIGNCLIENT......)
lpfnWndProc:指向一个窗口函数。函数原型为:
LRESULT CALLBACK WindowProc( HWND
hwnd
, UINT
uMsg
, WPARAM
wParam
, LPARAM
lParam
); //窗口函数由系统调用,响应不同的消 息,通常为一个 switch语句块。
hbrBackground:背景画刷,是HBRUSH类型。hbrBackground字段必须是用于绘制背景的物理刷子的句柄,或者是一个颜色的值。
- 注册窗口类:定义了一个窗口类之后,并不能直接使用它通过CreateWindow函数来创建窗体,因为操作系统并不知道该窗口类的存在。需要通过RegisterClass函数注册一个窗口类。该函数原型如下:
ATOM RegisterClass(CONST WNDCLASS*lpWndClass); //参数lpWndClass即为步骤一设计的窗口类的指针
- 创建窗口:调用CreateWindow函数创建窗口。CreateWindow函数语法如下:
<span style="white-space:pre"> </span>HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
<span style="white-space:pre"> </span>);
参数说明:
lpClassName:跟设计窗口类步骤的参数lpszClassName相同,指定了窗口的类名。
dwStyle:指定创建窗口的风格。该参数可以是下列窗口风格的组合再加上说明部分的控制风格(WS_DISABLED、WS_ICONIC、WS_MAXIMIZE......)。这里的
dwStyle表示每个具体窗口的风格,而窗口类风格指定的是该类窗口所具有的风格。
- 显示窗口:窗口在成功创建之后,还需要调用ShowWindow函数才能显示出来
//显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd);
- 进入消息循环:不断从消息队列取出消息,存在参数lpMsg参数中。如果获得消息为WM_QUIT,返回值为0.如果函数执行过程中出现错误,返回值为-1,其他情况返回值为非零。
<span style="white-space:pre"> </span>//进入消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#include "windows.h"
//窗口函数
LRESULT CALLBACK WNDFUN(HWND hWnd, UINT msg,
WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_PAINT:
{
HDC hdc = GetDC(hWnd);
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, 20, 20, (LPCTSTR)"Hello,world!" , sizeof("Hello,world!")-1);
DeleteDC(hdc);
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, msg, wparam, lparam);
}
return 0;
}
//程序的入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
//设计窗口类
WNDCLASS wndcls;
wndcls.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = (LPCTSTR)"CustomWnd";
wndcls.lpfnWndProc = WNDFUN;
wndcls.hInstance = GetModuleHandle(NULL);
wndcls.hIcon = NULL;
wndcls.hCursor = LoadCursor(hInstance,IDC_ARROW);
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
//注册窗口类
RegisterClass(&wndcls);
//创建窗口
HWND hWnd;
hWnd = CreateWindow((LPCTSTR)"CustomWnd", (LPCTSTR)"Win32App", WS_CAPTION | WS_OVERLAPPEDWINDOW | WS_SYSMENU,
50, 50, 500, 500, NULL, NULL, wndcls.hInstance, NULL);
//显示窗口
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
//进入消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}