第一章通过一个简单的例子向我们展现了Win32窗口设计的一般步骤,大体上分如下几步:
1、声明自定义的窗口处理函数
2、以WinMain函数为入口进入主函数
3、设计一个窗口类
4、注册窗口类
5、创建窗口
6、显示并刷新窗口
7、处理消息循环
8、实现自定义的窗口处理函数
一、窗口处理函数
又称窗口过程函数 定义
LRESULT CALLBACK MyWinProc(
HWND hwnd, //处理函数所属的窗口句柄
UINT uMSG, //接收到的消息
WPARAM wParam, //消息的附加参数,WM_CHAR消息的ASCII码保存于此
LPARAM lParam //消息附加参数
);
二、WinMain函数
int WINAPI WinMain( //入口函数
HINSTANCE hInstance, //当前实例句柄
HINSTANCE hPreInstance, //前一个实例句柄,Win32下不起作用,置为NULL
LPSTR lpCmdLine, //命令行参数
int nCmdShow //显示状态 最大化?最小化?等等
)
三、设计窗口类
WNDCLASS结构体定义
typedef struct tagWNDCLASS {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;
使用方法
//设计窗口类
WNDCLASS wndClass;
wndClass.cbClsExtra = 0; //给类额外附加的空间
wndClass.cbWndExtra = 0; //给窗口额外附加的空间
wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); //设置背景
wndClass.hCursor = LoadCursor(NULL,IDC_APPSTARTING); //设置光标
wndClass.hIcon = LoadIcon(NULL,IDI_APPLICATION); //设置图标
wndClass.hInstance = hInstance; //窗口所属的程序实例
wndClass.lpfnWndProc = MyWinProc; //绑定处理函数
wndClass.lpszClassName = "MFCTest"; //设置类名
wndClass.lpszMenuName = NULL; //指定菜单资源的名字
wndClass.style = CS_HREDRAW | CS_VREDRAW; //设置类的样式
类样式举例: CS_HREDRAW CS_VREDRAW 宽度和高度发生变化时重绘
CS_NOCLOSE 窗口没有关闭按钮 CS_DBLCLKS 用户在窗口中双击鼠标时向窗口过程发送鼠标双击消息
设定窗口图标时用到了LoadIcon函数
HICON WINAPI LoadIcon(
_In_opt_ HINSTANCE hInstance, //若使用系统光标则设为NULL
_In_ LPCTSTR lpIconName //光标类型
);
常用图标类型有:
IDI_APPLICATION IDI_ERROR IDI_QUESTION IDI_WARNINGdeng等 具体参见MSDN设定窗口光标时用到了LoadCursor函数
HCURSOR WINAPI LoadCursor(
_In_opt_ HINSTANCE hInstance,
_In_ LPCTSTR lpCursorName
);
使用系统光标时第一个参数设为NULL
常用的光标类型有
IDC_ARROW IDC_HELP IDC_APPSTARTING等 具体参见MSDN
设定窗口背景时即可以指定为一个画刷的句柄,也可以设置为一个标准的系统颜色值
指定画刷句柄时用到GetStockObject函数,该函数用来得到系统的标准画刷
HGDIOBJ GetStockObject(
_In_ int fnObject
);
参数为要获取的对象的类型,可设为 BLACK_BRUSH DC_BRUSH LTGRAY_BRUSH等 具体参见MSDN
该函数不仅可以获取画刷的句柄,也可获取画笔、字体、调色板的句柄,由于函数可返回多种资源的句柄,因此使用时需把返回值进行类型转换
四、注册窗口类
//注册窗口类
RegisterClass(&wndClass);
CreateWindow定义
HWND WINAPI CreateWindow(
_In_opt_ LPCTSTR lpClassName, //类名,创建的是哪个窗口类的实例对象
_In_opt_ LPCTSTR lpWindowName, //窗口名,显示在标题栏上
_In_ DWORD dwStyle, //窗口的显示样式
_In_ int x, //窗口左上角x坐标
_In_ int y, //窗口左上角y坐标
_In_ int nWidth, //窗口宽度
_In_ int nHeight, //窗口高度
_In_opt_ HWND hWndParent, //被创建窗口的父窗口句柄
_In_opt_ HMENU hMenu, //窗口菜单的句柄
_In_opt_ HINSTANCE hInstance, //窗口所属的应用程序实例句柄
_In_opt_ LPVOID lpParam //WM_CREATE消息附加参数
);
//创建窗口
HWND hWnd;
hWnd = CreateWindow("<span style="font-family: Arial, Helvetica, sans-serif;">MFCTest</span>","TEST MFC",WS_OVERLAPPEDWINDOW,
0,0,500,500,NULL,NULL,hInstance,NULL);
WS_OVERLAPPEDWINDOW 一种复合窗口
六、显示并刷新窗口//显示窗口
ShowWindow(hWnd,SW_SHOWNORMAL);
//刷新窗口
UpdateWindow(hWnd);
BOOL WINAPI ShowWindow(
_In_ HWND hWnd,
_In_ int nCmdShow //显示方式 <span style="color: rgb(42, 42, 42); font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 20.0059986114502px;">SW_MAXIMIZE <span style="color: rgb(42, 42, 42); font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 20.0059986114502px;">SW_MINIMIZE <span style="color: rgb(42, 42, 42); font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 20.0059986114502px;">SW_SHOWNORMAL等</span></span></span>
);
七、接收消息循环
//处理消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
八、定义窗口过程函数
LRESULT CALLBACK MyWinProc(
HWND hWnd, //处理函数所属的窗口句柄
UINT uMSG, //接收到的消息
WPARAM wParam, //消息的附加参数,WM_CHAR消息的ASCII码保存于此
LPARAM lParam //消息附加参数
)
{
switch(uMSG)
{
case WM_CHAR:
char szChar[20];
sprintf(szChar,"code is %d",wParam);
MessageBox(hWnd,szChar,"提示",MB_OK);
break;
case WM_LBUTTONDOWN:
MessageBox(hWnd,"Mouse clicked","MESSAGE",MB_OK);
HDC hdc;
hdc = GetDC(hWnd);
TextOut(hdc,0,50,"鼠标左键按下",strlen("鼠标左键按下"));
ReleaseDC(hWnd,hdc);
break;
case WM_PAINT:
HDC hDc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd,&ps);
TextOut(hDc,0,50,"重画",strlen("重画"));
EndPaint(hWnd,&ps);
break;
case WM_CLOSE:
if(MessageBox(hWnd,"确定退出?","提示",MB_YESNO)==IDYES)
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,uMSG,wParam,lParam);
break;
}
return 0;
}