既然在Windows操作系统下编程,窗口操作应该是程序设计的主要任务,一切与用户的接口都由窗口体现。窗口类往往用来组织数据、封装数据、表示数据,所以窗口操作也是Windows编程的核心内容。

前面对CWnd类以及它与Windows窗口的关系作了简要论述。下面将进一步阐明CWnd类是如何关联Windows窗口的,是如何封装WIN32窗口操作的。首先要脱离MFC,使用WIN32 API创建一个单窗口应用程序,然后模拟CWnd自己编写一个窗口封装类,最后对CWnd进行阐述。

6.1  使用WIN32 API创建窗口
下面使用WIN32 API创建一个只包含一个主窗口的小程序,主函数WinMain()创建主窗口后进入消息循环,收到WM_QUIT消息后退出。

当然,主函数首先要注册一个窗口类,这是创建窗口的需要。一个窗口类可以用来创建多个窗口。窗口类包含了窗口的风格、图标、光标、菜单、窗口过程等信息。窗口过程就是用来处理窗口消息的特定类型的全局函数,如示例6.1中的WndProc()。

示例清单6.1

#include "stdafx.h"

#define szWindowClass "MyClassName"

#define  szTitle "MyWindow"

 

ATOM MyRegisterClass(HINSTANCE hInstance);

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

 

int APIENTRY WinMain(HINSTANCE hInstance,

                     HINSTANCE hPrevInstance,

                     LPSTR lpCmdLine,

                     Int nCmdShow)

{

        MSG msg;

         HWND hWnd;

   //注册窗口类

         MyRegisterClass(hInstance);

         //使用已注册的窗口类,创建主窗口

         hWnd = ::CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW|WS_ BORDER,

      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 

   if (!hWnd)

   {

      return FALSE;

   }

   //显示主窗口

   ShowWindow(hWnd, nCmdShow);

   UpdateWindow(hWnd);

 

         //先创建主窗口,然后进入消息循环

         while (GetMessage(&msg, NULL, 0, 0))

         {

                            TranslateMessage(&msg);

                            DispatchMessage(&msg);

         }

         //收到WM_QUIT消息,退出

         return msg.wParam;

}

 

ATOM MyRegisterClass(HINSTANCE hInstance)

{

         WNDCLASSEX wcex;

 

         wcex.cbSize = sizeof(WNDCLASSEX);

         //窗口类风格

         wcex.style          = CS_HREDRAW | CS_VREDRAW;

         //处理窗口消息的窗口过程,函数指针指向WndProc()

         wcex.lpfnWndProc= (WNDPROC)WndProc;

         wcex.cbClsExtra= 0;

         wcex.cbWndExtra= 0;

         //实例句柄

         wcex.hInstance         = hInstance;

         //图标光标

         wcex.hIcon= NULL;

         wcex.hCursor= LoadCursor(NULL, IDC_ARROW);

         //背景刷

         wcex.hbrBackground= (HBRUSH)(COLOR_BACKGROUND+1);

         //主菜单

         wcex.lpszMenuName=NULL;

         //类名称

         wcex.lpszClassName= szWindowClass;

         wcex.hIconSm= NULL;

         //注册窗口类

         return RegisterClassEx(&wcex);

}

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

         //处理窗口消息的窗口过程函数

        

         PAINTSTRUCT ps;

         HDC hdc;

 

         switch (message)

         {

         case WM_CREATE:

         case WM_SHOWWINDOW:

         case WM_KEYDOWN:

         case WM_COMMAND:

         //......

                  return ::DefWindowProc(hWnd, message, wParam, lParam);

         case WM_LBUTTONDOWN:

                   int ScreenWidth;

                   int ScreenLength;

                   RECT rcWindow;

                  

                   ::GetWindowRect(hWnd,&rcWindow);

                   ScreenWidth=GetSystemMetrics(SM_CXSCREEN);

                    ScreenLength=GetSystemMetrics(SM_CYSCREEN);

                   //单击鼠标,设置窗口位置

                   ::SetWindowPos(hWnd,HWND_TOP,ScreenWidth/4,

                            ScreenWidth/4,ScreenLength/2,ScreenLength/2,SWP_SHOWWINDOW);

                   Sleep(300);

 

                   ::SetWindowPos(hWnd,HWND_TOP,ScreenWidth/3,

                            ScreenWidth/3,ScreenLength/3,ScreenLength/3,SWP_SHOWWINDOW);

                   Sleep(100);

                   ::SetWindowPos(hWnd,HWND_TOP,ScreenWidth/4,

                            ScreenWidth/4,ScreenLength/2,ScreenLength/2,SWP_SHOWWINDOW);

                   Sleep(100);

                   ::SetWindowPos(hWnd,HWND_TOP,rcWindow.left,rcWindow.top,

                            rcWindow.right-rcWindow.left,rcWindow.bottom-rcWindow.top,

                            SWP_SHOWWINDOW);

                   return ::DefWindowProc(hWnd, message, wParam, lParam);

 

         case WM_RBUTTONDOWN:

         //右击鼠标,隐藏、显示窗口

                   ShowWindow(hWnd,SW_HIDE);

                   Sleep(300);

                   ShowWindow(hWnd,SW_SHOW);

 

         return ::DefWindowProc(hWnd, message, wParam, lParam);

         case WM_PAINT:

                   //绘制窗口

                            hdc = BeginPaint(hWnd, &ps);

                            RECT rt;

                            GetClientRect(hWnd, &rt);

                            ::SetBkColor(hdc,::GetSysColor(COLOR_BACKGROUND));

                            ::SetTextColor(hdc,RGB(255,255,255));

                            DrawText(hdc, "My window created by win32 API",-1,&rt, DT_CENTER);

 

                            EndPaint(hWnd, &ps);

                            return ::DefWindowProc(hWnd, message, wParam, lParam);

                            break;

 

         case WM_DESTROY:

                   //主窗口关闭时,给UI线程消息循环发送WM_QUIT消息,线程退出代码为0

                            PostQuitMessage(0);

                            break;

         default:

                   //调用默认的消息处理过程处理当前消息

                   return ::DefWindowProc(hWnd, message, wParam, lParam);

   }

   return 0;

}