win32对比atl

原文
窗口过程中:

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    // TODO: 加绘画代码
    EndPaint(hWnd, &ps);
    break;
// TODO: 标签下添加 TextOut(hdc, 0, 0, _T("Hello world!"), 12);

win32你好

主程序:

1.2.1 WinMain

//APIENTRY代表程序从此开始运行(入口)处.
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
      // TODO: 放代码
      MSG msg;
      MyRegisterClass(hInstance);
 
      // 初化应用
      if (!InitInstance (hInstance, nCmdShow))
      {
            return FALSE;
      }
     
      // 主消息循环
      while (GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }
 
      return (int) msg.wParam;
}

三块构成:注册/初化/主消息循环.

1.2.1 注册窗口类

ATOM MyRegisterClass(HINSTANCE hInstance)
{
      WNDCLASSEX wcex;
      wcex.cbSize = sizeof(WNDCLASSEX);
      wcex.style              = CS_HREDRAW | CS_VREDRAW;
      wcex.lpfnWndProc = WndProc;
      wcex.cbClsExtra         = 0;
      wcex.cbWndExtra         = 0;
      wcex.hInstance          = hInstance;
      wcex.hIcon              = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32));
      wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
      wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);
      wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32);
      wcex.lpszClassName      = szWindowClass;
      wcex.hIconSm            = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
 
      return RegisterClassEx(&wcex);
}

1.2.3 初化应用

主要为创建并显示窗口.

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   hInst = hInstance; // 全局变量中存储实例
   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
 
   if (!hWnd)
   {
      return FALSE;
   }
   ShowWindow(hWnd, nCmdShow);
   return TRUE;
}

1.2.4 窗口过程

在这里,主要处理WM_PAINTWM_DESTROY等消息.

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      int wmId, wmEvent;
      PAINTSTRUCT ps;HDC hdc;
      switch (message)
      {
      case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // TODO: 加绘画代码
            TextOut(hdc,0,0,_T("你好!"),12);
            EndPaint(hWnd, &ps);
            break;
      case WM_DESTROY:
            PostQuitMessage(0);
            break;
      default:
            return DefWindowProc(hWnd, message, wParam, lParam);
      }
      return 0;
}

构建并输出,略.

ATL中你好

2.1 修改stdafx.h

1.1中创建的Win32代码中移除或注释stdafx.h中的:

// 窗口头文件
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

并在stdafx.h中添加如下的include语句:

#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include <atlwin.h>
#include "CWellcomeWindow.h"

2.2 添加CWellcomeWindow.h

#pragma once
#include "stdafx.h"
 
class CWellcomeWindow : public CWindowImpl<CWellcomeWindow,CWindow, CFrameWinTraits> {
public :
    DECLARE_WND_CLASS(NULL);
    BEGIN_MSG_MAP(CWellcomeWindow)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    END_MSG_MAP()
 
    LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
      {
            HICON appIcon = LoadIcon(_Module.GetResourceInstance(),
                  MAKEINTRESOURCE(IDI_LEARNINGWTLPART1_ATL));
            this->SetIcon(appIcon);
 
            return 0;
      }
 
 
      LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
      {
            PAINTSTRUCT ps;
            CComBSTR wellcome(_T("你好!"));
 
            HDC hdc; // = this->GetDC();
            hdc = this->BeginPaint(&ps); // this->BeginPaint(&ps);
                  TextOut(hdc, 0, 0, wellcome, wellcome.Length());
            this->EndPaint(&ps);
            //this->ReleaseDC(hdc);
 
            return 0;
      }
 
      LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
      {
            ::PostQuitMessage(0);
            return 0;
      }
};

2.3 修改win32.cpp

保留WinMain方法声明和#include"stdafx.h"语句,删除或注释掉其余代码.添加_Module定义,修改WndMain方法体;完成后的代码如下:

#include "stdafx.h"
#include "LearningWTLPart1_ATL.h"
 
CComModule _Module;
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
      UNREFERENCED_PARAMETER(hPrevInstance);
      UNREFERENCED_PARAMETER(lpCmdLine);
      _Module.Init(NULL, hInstance);
      CComBSTR appTitle;
      appTitle.LoadString(_Module.GetResourceInstance(), IDS_APP_TITLE);
      CWellcomeWindow wnd;
      wnd.Create(NULL, 0, appTitle);
      // 主消息循环
      MSG msg;
      while (GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
 
      }
 
      _Module.Term();
 
      return (int) msg.wParam;
}

3对比

atl轻量封装了基础构造块.atl四块:注册/初化/主循环/窗口过程.

3.1.2 ATL基础构造块和主要流程

CComModule下面函数完成.Init/Termatlcom服务器的部分.

函数作用
Init初化CComModule类数据
Create上面四步都在此函数
主消息循环一样
Term结束,释放数据

4atl编程模型

atlwtl的基础.

4.1 注册类在哪?

上面MyRegisterClass函数要完成的工作:1.初化WNDCLASSEX;2.RegisterClassEx.
而在ATL中,由CWellcomeWindow之由宏定义的成员函数(宏定义的成员函数)DECLARE_WND_CLASS(NULL)完成,其由wnd.Create(NULL,0,appTitle)调用(例如,在win32.cpp中).

4.1.1 DECLARE_WND_CLASS(NULL)宏定义?

// CWndClassInfo 窗口类信息
#define DECLARE_WND_CLASS(WndClassName) \
static ATL::CWndClassInfo& GetWndClassInfo() \
{ \
      static ATL::CWndClassInfo wc = \
      { \
            { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \
             0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
            NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
      }; \
      return wc; \
}

CWndClassInfoATL内使用WNDCLASSEX结构的结构(C++),看看代码就应该有所了解了,关键在于4.1.2CWndClassInfo结构(_ATL_WNDCLASSINFOW)定义的黑体部分(Bold).

4.1.2CWndClassInfo结构(_ATL_WNDCLASSINFOW)定义

struct _ATL_WNDCLASSINFOW
{//类信息.
      WNDCLASSEXW m_wc;
      LPCWSTR m_lpszOrigName;
      WNDPROC pWndProc;
      LPCWSTR m_lpszCursorID;
      BOOL m_bSystemCursor;
      ATOM m_atom;
      WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT];
      ATOM Register(WNDPROC* p)
      {
            return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p);
      }
};

4.1.3 ATL::CWindowImpl::Create定义

HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  DWORD dwStyle = 0, DWORD dwExStyle = 0,
  _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  {
        if (T::GetWndClassInfo().m_lpszOrigName == NULL)
              T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
        ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);

        dwStyle = T::GetWndStyle(dwStyle);
        dwExStyle = T::GetWndExStyle(dwExStyle);

        // 置标题
        if (szWindowName == NULL)
              szWindowName = T::GetWndCaption();

        return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName,
              dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
  }

真正完成CreateWindow.

4.2 WndProc在哪?

ATL中保留了主消息循环(例如,在win32.cpp中).WndProc宏定义成员函数完成,参看2.2添加CWellcomeWindow.h可以看到如下代码:

  BEGIN_MSG_MAP(CWellcomeWindow)
      MESSAGE_HANDLER(WM_CREATE, OnCreate)
      MESSAGE_HANDLER(WM_PAINT, OnPaint)
      MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
  END_MSG_MAP()

4.2.1 映射消息

#define BEGIN_MSG_MAP(theClass) \
public : \
      BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
      { \
            BOOL bHandled = TRUE; \
            (hWnd); \
            (uMsg); \
            (wParam); \
            (lParam); \
            (lResult); \
            (bHandled); \
            switch(dwMsgMapID) \
            { \
            case 0:
                 
#define END_MSG_MAP() \
                  break; \
            default: \
                  ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)/n"), dwMsgMapID); \
                  ATLASSERT(FALSE); \
                  break; \
            } \
            return FALSE; \
      }

你所定义特定消息处理将会置于case 0defaul之间,例如2.2添加CWellcomeWindow.h将会产生如下代码:

BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0)
      {
            BOOL bHandled = TRUE;
            (hWnd);
            (uMsg);
            (wParam);
            (lParam);
            (lResult);
            (bHandled);
            switch(dwMsgMapID)
            {
            case 0:
                  if(uMsg == msg)
                  {
                        bHandled = TRUE;
                        lResult = OnCreate(uMsg, wParam, lParam, bHandled);
                        if(bHandled)
                              return TRUE;
                  }
            ...
                  break;
            default:
                  break;
            }
            return FALSE;
      }
posted @   zjh6  阅读(16)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示