第一章主要讲解WIN32程序的基本模式,为后续的MFC程序奠定基础。该练习使用WIN32 API来显示一个窗口并响应一些事件。
(1)首先当然还是main函数入手,
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
第一个参数是当前实例的句柄,这个应该是代表了本实例的内存对象。第二个参数是前一个实例句柄,在WIN32程序时代已经不再使用了。第三个参数就是命令行了。第四个暂不理会。
(2)第二步就是标准的WIN窗口创建、显示流程,包括
(A)创建窗口类 WNDCLASS,其实也就是初始化这个结构体。几个重要的成员:
hbrBackground,背景画刷句柄,可以使用API GetStockObject,它可以获得系统自带的画刷、笔
hCursor,光标,可以使用LoadCursor,该API可以获取系统自带资源,也可以是本程序自身资源, 前者要求第一个参数为NULL,eg:LoadCursor(NULL, IDC_CROSS)
hIcon,图标,可以使用LoadIcon,与LoadCursor类似,eg:LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2)),其中IDI_ICON2是我们自己定义的一个图标资源,注意需 要引入头文件"resource.h"方能引用资源ID号。MAKEINTRESOURCE用于将INT型的ID号转为 LPCSTR类型
lpfnWndProc,指向最重要的东东,窗口过程函数
lpszClassName,类名,创建一个窗口类,总要给人家一个名字。引用孙鑫老师的话,“奥迪A6”
style,类的风格特性,是该类窗口都具备的特性,注意与窗口特性区分,一个是CS,一个是WS。
(B)注册窗口类,“奥迪A6需要国家审批通过才能入市”,RegisterClass
(C)创建窗口,这下轮到实例化窗口类了。CreateWindow, 几个参数有:类名,窗口名称,窗口坐标和大 小,窗口风格WS,父窗口句柄,实例句柄。WS这个需要掌握,具体还是baidu。
(D)显示窗口,ShowWindow
(E)更新窗口,UpdateWindow,用于产生WM_PAINT消息,驱动窗口的更新显示
(3)第三步进入该实例的消息处理循环
while(GetMessage(&msg, NULL, 0, 0)) 这里第二个参数为需要取得消息的窗口句柄,NULL时获得调用线程 所有窗口的消息。GetMessage只有再收到WM_QUIT时才返回0
TranslateMessage,负责一些消息的预处理,比如组合形成WM_CHAR消息
DispatchMessage,将消息交换操作系统,后者负责去调用相应的窗口过程函数。
(4)窗口过程函数----主要的工作地
因为是回调函数,所以其内部无法使用this指针,系统将窗口句柄作为参数传递进去,便于处理。
LRESULT CALLBACK WinProc(HWND hWnd, UINT unMsg, WPARAM wParam, LPARAM lParam)
这里我学习了HDC设备描述符的知识,并使用简单的GDI API进行了作图显示。在WM_CLOSE消息中,我们判断 是否需要真的退出,若是则调用DestroyWindow发出WM_DESTROY消息,后者则调用PostQuitMessage使得 GetMessage退出,应用程序生命周期结束。
<span style="white-space:pre"> </span> <pre name="code" class="cpp">LRESULT CALLBACK WindowProc(HWND hWnd, UINT unMsg, WPARAM wParam, LPARAM lParam)
{
switch(unMsg)
{
case WM_CHAR:
{
char szChar[20];
sprintf(szChar, "char code is :%d", wParam);
MessageBox(hWnd, szChar, "char", MB_OK);
break;
}
case WM_LBUTTONDOWN:
{
HDC hDc;
hDc = GetDC(hWnd);
TextOut(hDc, 0, 50, "Programmer", strlen("Programmer"));
ReleaseDC(hWnd, hDc);
SetWindowPos(hWnd, NULL, 20, 300, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
break;
}
case WM_PAINT:
{
HDC hDc;
PAINTSTRUCT ps;
hDc = BeginPaint(hWnd, &ps);
TextOut(hDc, 0, 0, "BBBBMMMMWWWW", strlen("BBBBMMMMWWWW"));
EndPaint(hWnd, &ps);
break;
}
case WM_CLOSE:
{
if (IDYES == MessageBox(hWnd, "Are you sure to quit!", "message", MB_YESNO))
{
DestroyWindow(hWnd);
}
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
{
return DefWindowProc(hWnd, unMsg, wParam, lParam);
}
}
return 0;
}
(5)附加学习了改变应用程序图标的方法,包括引入资源RC文件,创建icon资源,在RC文件中设定应用程序图标。
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "App.ico"
IDI_ICON2 ICON DISCARDABLE "Window.ICO"
最小的ID值对应的ICO资源将成为应用程序图标,IDI_ICON2是我们添加的另一个资源,用于上面
的
LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_ICON2))。可见,RC文件建立起了程序代码与资源之间的桥 梁。