Win32编程:是调用Win32SDK中的API函数进行编程,注册窗口类,建立窗口,现实窗口,设置消息循环……等等的方式建立Windows程序,以前的Windows程序都这样开发的,写程序要写大量代码。
MFC库:后来微软为了方便编程人员开发,将Win32SDK中的函数进行C/C++封装,于是就是MFC库(架构),开发程序比以往的Win32SDK方式更加简便快捷。
相同:调用的API都是Win32SDK的API
不同:MFC的程序执行起来慢,而且用MFC写程序不自由
Win32SDK开发速度慢,而且要编写的代码多得惊人
一般在Win32下编程,简单的步骤是:
(1)设计窗口类
(2) 注册窗口类
(3)Create窗口
(4)显示窗口
(5)更新窗口
(6)消息循环(关键)
我们用Visual Studio创建一个win32项目上会自动生成一个注册窗口类。如下:
1 ATOM MyRegisterClass(HINSTANCE hInstance) 2 { 3 WNDCLASSEX wcex; 4 5 wcex.cbSize = sizeof(WNDCLASSEX); // UINT cbSize 6 7 wcex.style = CS_HREDRAW | CS_VREDRAW; // UINT style 8 wcex.lpfnWndProc = WndProc; // WNDPROC lpfnWndProc 9 wcex.cbClsExtra = 0; // int cbClsExtra 10 wcex.cbWndExtra = 0; // int cbWndExtra 11 wcex.hInstance = hInstance; // HINSTANCE hInstance 12 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT5)); // HICON hIcon 13 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // HCURSOR hCursor 14 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // HBRUSH hbrBackground 15 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32PROJECT5); // LPCTSTR lpszMenuName 16 wcex.lpszClassName = szWindowClass; // LPCTSTR lpszClassName 17 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); // HICON hIconSm 18 19 return RegisterClassEx(&wcex); 20 }
WNDCLASSEX结构体中:
cbSize:存储表示该结构大小的字节数,通常以sizeof(WNDCLASSEX)的形式对该域进行设置
style :存储表示窗口类风格的整数,它决定了该窗口的外观和内在特征。
lpfnWndProc:指向窗口处理函数(回调函数)。
cbClsExtra :为窗口类的额外信息做记录,初始化为0。
cbWndExtra :记录窗口实例的额外信息,系统初始为0
hIcon :存储该类窗口的图标的句柄
hCursor:存贮表示窗口类光标的句柄,该域必须是一个光标资源的句柄。
hbrBackground:窗口类的背景刷,为背景刷句柄,也可以为系统颜色值,如果颜色值已给出,则必须转化为以下的HBRUSH的值
lpszMenuName:存储以空结尾的指定类菜单资源名的字符串指针,类菜单资源名已经在资源文件中进行了定义。
lpszClassName:存储以空结尾的字符串的指针,或存储一个原子元素(ATOM)。
hIConSm:存储该类窗口小图标的句柄。
MFC下编程,省去了窗口设计步骤,直接通过GetClassInfo()来获取标准窗口的信息。
MFC中,#32770 代表标准窗口类。
BOOL CBBBApp::SetRegisterClass() { WNDCLASS wndcls; ZeroMemory(&wndcls, sizeof(WNDCLASS)); // start with NULL HINSTANCE hInst; hInst = AfxGetInstanceHandle(); ASSERT(hInst != 0);
GetClassInfo(hInst, _T("#32770"), &wndcls); wndcls.lpszClassName = _T("YourClassName"); if (FALSE == AfxRegisterClass(&wndcls)) { AfxThrowResourceException(); return FALSE; } return TRUE; }
1)AfxGetInstanceHandle
作用:获取当前实例句柄
原型:HINSTANCE AFXAPI AfxGetInstanceHandle( );
返回值:返回应用程序当前实例的句柄。如果是从与MFC的USRDLL版本连接的DLL内调用的,则返回代表DLL的HINSTANCE值
2)GetClassInfo
作用:获得窗体类信息
原型:
BOOL GetClassInfo(
HINSTANCE hInstance,
LPCTSTR lpClassName,
LPWNDCLASS lpWndClass
);
参数:hInstance,创建类的应用程序实例
lpClassName,类名
lpWndClass,指向WNDCLASS结构体的指针
返回值:返回非零成功,返回零不成功
3)AfxRegisterClass
作用:注册类
原型:BOOL AFXAPI AfxRegisterClass( WNDCLASS* lpWndClass );
参数:指向WNDCLASS结构体的指针
返回值:若类成功注册则返回零,否则非零。
4)AfxThrowResourceException
这个函数抛出一个资源异常。通常在不能载入Windows资源的时候调用这个函数。
1)注册窗口类以后同一类窗口都用一套WindowProc。有统一的行为
在我们构造一个窗口类结构后,我们需要将这个类结构指针加入到system atom table 即SAT中,这样系统就可以通过查找这张表来找到用户自定义的窗口类
2)注册好窗口类之后就可以用FindWindow函数来找到这个窗口类并获得其句柄,然后即可以向该窗口发送消息。
HWND hComm = ::FindWindow(_T("YourClassName"), NULL); if (NULL == hComm) return FALSE;
if (hComm && ::IsWindow(hComm)) { DWORD dwResult = 0; LRESULT lResult = ::SendMessageTimeout(hComm, WM_NULL, 0, 0, SMTO_ABORTIFHUNG, 500, &dwResult); }
1)FindWindow
作用:该函数获得一个顶层窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。
原型:
2)SendMessageTimeout
作用:该函数将指定的消息发送到一个或多个窗口。
原型:
LRESULT SendMessageTimeout( HWND hwnd, // 其窗口程序将接收消息的窗口的句柄。 // 如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口。 UINT Msg, // 指定被发送的消息 WPARAM wParam,// 指定附加的消息指定信息。 LPARAM IParam, // 指定附加的消息指定信息。 UINT fuFlags, // 指定如何发送消息。 // SMTO_ABORTIFHUNG:如果接收进程处于“hung”状态,不等待超时周期结束就返回。 // SMTO_BLOCK:阻止调用线程处理其他任何请求,直到函数返回。 // SMTO_NORMAL:调用线程等待函数返回时,不被阻止处理其他请求。 // SMTO_NOTIMEOUTIFNOTHUNG:Windows 95及更高版本:如果接收线程没被挂起,当超时周期结束时不返回。 UIUT uTimeout, // 为超时周期指定以毫秒为单位的持续时间。如果GetLastError返回零,表明函数超时 LPDWORD lpdwResultult // 指定消息处理的结果,依赖于所发送的消息 );返回值:若函数调用成功则返回非零值,若失败或超时返回零。