现在已经不太使用mfc这种复杂的窗体开发了,但是既然上课的老师热衷把mfc作为c++教学的内容,那么我就微微记录一下mfc框架的学习步骤吧,怎么说mfc学习对了解windwos系统机制还是很有作用的。
1.mfc第一个程序
mfc程序的创建首先是一个windows Application,其次,程序运行在int WinMain(HINSTANCE HInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
中。
在WinMain函数中,需要定义一个struct体,名为WNDCLASSEX,并对其进行属性的赋值。其中WNDCLASSEX这个结构体的属性有
typedef struct {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;
cbSize
通常情况下,只要将此参数设置为sizeof(WNDCLASSEX)即可,如果程序中用到了GetClassInfoEx函数,那么在使用前请一定要先设置cbSize的值。
style
指定一个样式,它的值可以是窗口样式的任意组合,在这里我们将其设置为CS_HREDRAW |CS_VREDRAW
,当然它还有其他取值如
CS_DBLCLKS
CS_OWNDC
CS_CLASSDC
CS_PARENTDC
CS_NOCLOSE
CS_SAVEBITS
CS_BYTEALIGNCLIENT
CS_BYTEALIGNWINDOW
CS_GLOBALCLASS
lpfnWndProc
此参数为指定一个回调函数,我们先定义一个回调函数如下
//回调函数
LRESULT WINAPI WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,Msg,wParam,lParam);
}
然后将此参数设置为回调函数名,WinProc
cdClsExtra
指定一个数值,记录窗口类额外的信息,默认为0
cdWndExtra
指定一个数值,记录窗口实例的额外信息,默认为0,如果程序使用WNDCLASSEX注册一个从资料文件里创建的对话框,则此阐述必须设置为DLGWINDOWEXTRA,这里我也将其设置为0
hIcon
窗口类的图标,此参数ICON资源句柄,如果设置为NULL,操作系统将提供一个默认的图标,这里我指定一个ICON,LoadIcon(NULL,MAKEINTERSOURCE(IDI QUESTION));
hCursor
窗口类的鼠标样式,同样,该参数为只想CURSOR资源的句柄,如果为NULL,则当任何时候鼠标进入窗口区域时必须明确指定鼠标形状,此处讲起设置为LoadCursor(NULL.MAKEINTERSOURCE(IDC HAND));
hbrBackground
背景刷的句柄,即可以只想物理笔刷又可以为一个颜色值,该值必须为标准系统颜色,如果颜色值已经给出,则必须转化为一下给出的HBRUSH类型;
COLOR_ACTIVEBORDER
COLOR_ACTIVECAPTION
COLOR_APPWORKSPACE
COLOR_BACKGROUND
COLOR_BTNFACE
COLOR_BTNSHADOW
COLOR_BTNTEXT
COLOR_CAPTIONTEXT
COLOR_GRAYTEXT
COLOR_HIGHLIGHT
COLOR_HIGHLIGHTTEXT
COLOR_INACTIVEBORDER
COLOR_INACTIVECAPTION
COLOR_MENU
COLOR_MENUTEXT
COLOR_SCROLLBAR
COLOR_WINDOW
COLOR_WINDOWFRAME
COLOR_WINDOWTEXT
当使用UnregisterClass函数注销一个窗口类的时候,系统会自动删除该类的笔刷,程序运行中不可删除;如果此成员值为NULL,那么在必要的时候,科幻段必须自己执行渲染,确认什么时候渲染背景,你可以通过BeginPaint函数提起WM_ERASEBAGND消息或测试PAINTSTRUCE结构中fErase的值;这里我们,我们将其值设置为(HBRUSH)GetObject(WHITE BRUSH);
lpsxMenuName
指向一个NULL结尾的字符串,同资源中的名字一样,作为窗口菜单的名字。如果使用整型ID标识菜单,可以使用MAKEINTERSOURCE定义一个宏。如果它的值为MULL,那么该类创建的窗口将都咩有默认的菜单,为了剪短,我们讲起设置为NULL,即没有菜单。
lpszClassName
窗口类的名字,我们可以任意取,值类型为一个字符串
hIconSm
在任务栏时的图标,值设置同hIcon,这里我们设置为LoadIcon(NULL,IDI_APPLICATION);
至此我们可以完成一个简单的窗口设置,代码如下:
#include <windows.h>
//回调函数
long _stdcall WINAPI WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
PostQuitMessage(-1);
break;
default:
return DefWindowProc(hWnd,Msg,wParam,lParam);
}
}
//主函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
char *cName = "cName";
WNDCLASSEX wc;
HWND hWnd;
MSG Msg;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //GetStockObject
//wc.hCursor = LoadCursor(NULL,MAKEINTRESOURCE(IDC_HAND)); //MAKEINTRESOURCE
wc.hIcon = LoadIcon(NULL,MAKEINTRESOURCE(IDI_QUESTION)); //IDI_QUESTION
wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); //IDI_APPLICATION
wc.hInstance = hInstance;
wc.lpfnWndProc = WinProc;
wc.lpszClassName =(LPSTR)cName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW; //cs_classdc,cs_parentdc,cs_hredraw,cs_vredraw,cs_owndc,cs_dblclks
RegisterClassEx(&wc);
hWnd = CreateWindowEx("First","FirstWindow","cName Window",WS_OVERLAPPEDWINDOW,
0,0,600,400,NULL,NULL,hInstance,NULL);//创建一个调用硬件的句柄
//hWnd=CreateWindowEx("First","FirstWindow",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if(hWnd == NULL)
{
//MessageBox(NULL,"There's an Error","Error Title",MB_ICONEXCLAMATION|MB_OK);
return -2;
}
ShowWindow(hWnd,nShowCmd);
UpdateWindow(hWnd);
while(GetMessage(&Msg,NULL,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.message;
}