原生Win32应用程序开发
1.WinMain函数(程序的进入点)
int WINAPI WinMain(
HINSTANCE hInstance, //表示当前应用程序实例句柄。实际上是系统将可执行文件映像加载到进程地址
//空间时使用的基地址,通常为0x00400000。
HINSTANCE hPreInstance,//表示应用程序前一个实例句柄。对于Win32应用程序来说,为NULL。
LPSTR lpCmdLine, //表示进程的命令行。
int nCmdShow //表示窗口如何被显示。
);
nCmdShow参数值列表:
参数值 | 描述 |
SW_HIDE | 隐藏窗口 |
SW_MINIMIZE | 最小化窗口,将最顶层窗口激活 |
SW_RESTORE | 还原窗口 |
SW_SHOW | 显示窗口 |
SW_SHOWMAXIMIZED | 最大化显示窗口 |
SW_SHOWMINIMIZED | 最小化显示窗口 |
SW_SHOWMINNOACTIVE | 最小化显示窗口,当前活动的窗口仍然处于活动状态 |
SW_SHOWNA | 显示窗口,当前活动的窗口仍然处于活动状态 |
SW_SHOWNOACTIVATE | 在窗口激活之前显示的大小和位置显示窗口,当前活动搞得窗口仍然处于活动状态 |
SW_SHOWNORMAL | 激活并显示一个窗口,如果窗口处于最小化或最大化状态,恢复窗口原始的大小 |
2.窗口的诞生
窗口是用户与系统交互的手段。窗口实际上是一个内存区域,该区域存储了一个数据结构信息,操作系统通过该数据结构管理窗口。该数据结构定义如下:
typedef struct _WNDCLASS{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
}WNDCLASS;
- style:窗口类的风格。可以使列出的风格的任意组
风格 | 描述 |
CS_BYTEALIGNCLIENT | 窗口的客户区域以“字符边界”对齐,当系统调整窗口的水平位置时,客户区域的左边坐标是8的整倍数 |
CS_BYTEALIGNWINDOW | 窗口以“字符边界”对齐,当系统调整窗口的水平位置时,客户区域的左边坐标是8的整倍数 |
CS_CLASSDC | 分配一个设备环境并被类中的所有窗体共享。它是可以适用于一个应用程序的若干线程创建的一个相同类的窗体。当多个线程试图同时使用相同的设备环境时,系统只允许一个线程成功地进行绘图操作。 |
CS_DBLCLKS | 当用户双击窗口时,将向窗口函数发送鼠标双击消息。 |
CS_HREDRAW | 如果窗口的位置或宽度发生改变,将重绘窗口 |
CS_OWNDC | 为同一个窗口类中的每个窗口创建一个唯一的设备上下文 |
CS_PARENTDC | 设置子窗口中剪下的矩形区域到父窗口中,以使子窗口可以在父窗口上绘图。指定改风格可以提高应用程序的性能。 |
CS_SAVEBITS | 把被窗口遮掩的屏幕图像作为位图保存起来。当该窗口被移动时,Windows操作系统使用被保存的位图来重建屏幕图像。 |
CS_VREDRAW | 如果窗口的位置或高度改变,将重绘窗口 |
CS_GLOBALCLASS | 指定此窗体类是一个应用程序全局类。应用程序全局类是由一个在进程中对所有模块有效的exe或dll注册的窗体类。 |
CS_NOCLOSE | 窗口中的“关闭”按钮不可见 |
- lpfnWndProc:是一个函数指针,表示窗口函数。操作系统通过该成员处理系统中的各种消息。
窗口函数的原型:typedef LRESULT(CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
第一个参数表示窗口句柄,第二个参数表示消息标识,第三、第四参数表示消息的附加信息。即,窗口函数的参数实际上是消息结构MSG的部分成员,也充分说明了窗口函数是为了处理消息而设计的。
- cbClsExtra:表示窗口类的附加信息。Windows系统在内部将它初始化为零。
- cbWndExtra:表示窗口的附加信息。Windows系统在内部将它初始化为零。如果应用程序利用WNDCLASS注册一个对话框类,需要将该成员设置为DLGWINDOWEXTRA。
- hInstance:表示当前的应用程序实例句柄。通过该成员可以加载一些资源。
- hIcon:表示窗口的图标句柄。当窗口正常显示时,图标会在窗口的左上角绘制。该成员为NULL时,系统将提供一个默认的图标。
在为hIcon成员赋值时,可以调用LoadIcon函数获取应用程序中某个图标资源的句柄。该函数第一个参数为应用程序实例句柄;第二个参数为图标资源名称。通常情况下,在程序中图标资源是通过资源ID标识的,为了将资源ID转化为资源名称,可以使用MAKEINTRESOURCE宏。
- hCursor:表示窗口的光标句柄。当鼠标在窗口上移动时,会出现光标。光标是一种GDI资源,可以通过LoadCursor函数获得。
- hbrBackground:表示窗口的背景画刷句柄。当窗口重绘时,系统会用该成员指定的画刷绘制窗口背景。
- lpszMenuName:表示菜单资源名称。菜单资源通常以资源ID的形式表示,为了将其转化为资源名称,可以使用MAKEINTRESOURCE宏。
- lpszClassName:表示窗口的类名。
3.注册窗口类
定义了一个窗口类之后,可以通过调用CreateWindow函数来创建窗体。因为操作系统并不知道窗口类的存在,因此需要向操作系统注册窗口类。可以使用RegisterClass函数向操作系统注册一个窗口类。
ATOM RegisterClass(CONST WNDCLASS *lpWndClass);
lpWndClass表示需要注册的窗口类指针。
返回值:如果函数执行成功,返回值是一个原子,它唯一标识注册的窗口类。
4.创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类名称,窗口类名称必须是已经注册过的,否则窗口将创建失败
LPCTSTR lpWindowName, //窗口的名称。如果窗口中含有标题栏风格,则该参数表示标题栏文本
DWORD dwStyle, //窗口的风格。该风格与窗口类的风格不同,窗口类风格指定的是该类窗口
//所具有的风格,而dwStyle表示每个具体窗口的风格。
int x, //窗口初始化时左上角的x坐标
int y, //窗口初始化时左上角的y坐标
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //被创建窗口的父窗口
HMENU hMenu, //窗口的菜单句柄
HANDLE hInstance, //窗口所在的应用程序的实例句柄
LPVOID lpParam //是一个CREATESTRUCT结构指针,作为WM_CREATE消息的lParam参数被传递。
//在执行CreateWindow函数时,会向窗口函数发送WM_CREATE消息,同时,
//lpParam参数将作为WM_CREATE消息的lParam参数被传递。
);
返回值:如果函数执行成功,返回值是新创建窗口的句柄;如果函数执行失败,返回值为NULL。
5.显示窗口
BOOL ShowWindow(HWND hWnd, int nCmdShow);
hWnd:表示需要显示的窗口句柄
nCmdShow:表示窗口显示的状态,通常为SW_SHOW。
在首次显示窗口时,还需要调用UpdateWindow函数刷新窗口。UpdateWindow函数通过向窗口函数发送WM_PAINT消息,实现窗口客户区域的绘制。
BOOL UpdateWindow(HWND hWnd);
hWnd:表示需要绘制的窗口句柄。
6.Win32应用程序开发
#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,"Hello World",11);
DeleteDC(hdc);
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, msg, wparam, lparam);
}
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
//设计窗口类
WNDCLASS wndcls;
wndcls.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = "CustomWnd";
wndcls.lpfnWndProc = WNDFUN;
wndcls.hInstance = GetModuleHandle(NULL);
wndcls.hIcon = NULL;
wndcls.hCursor = NULL;
wndcls.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
//注册窗口类
RegisterClass(&wndcls);
//创建窗口
HWND hwnd;
hwnd = CreateWindow("CustomWnd", "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;
}