1. Duilib消息派发机制 源码不完全分析 [源码分析]

这里使用的Duilib库为Duilib_Ultimate
查考: https://blog.youkuaiyun.com/bureau123/article/details/122127080?spm=1001.2014.3001.5506
我推荐的视频duilib视频教程 迪大学院 duilib: http://www.didacollege.com/site-List/show-12-26.html
我的 QQ: 2402398917

WinMain函数的内容如下

int WINAPI _tWinMain(
 HINSTANCE hInstance,      // handle to current instance
 HINSTANCE hPrevInstance,  // handle to previous instance
 LPTSTR lpCmdLine,          // command line
 int nCmdShow)              // show state
{
 ::CoInitialize(NULL);

 CPaintManagerUI::SetInstance(hInstance);

 MainWnd* pMainWnd = new MainWnd();

 pMainWnd->Create(NULL, _T("我是标题"),
  UI_WNDSTYLE_FRAME, NULL, /* 窗口风格 */
  0, 0, 300, 300); // 看这里

 pMainWnd->CenterWindow();

 // pMainWnd->ShowModal();
 CPaintManagerUI::MessageLoop();

 CPaintManagerUI::Term();

 ::CoUninitialize();

 return 0;
}

我们用ctrl看看Create的实现

 pMainWnd->Create(NULL, _T("我是标题"),
  UI_WNDSTYLE_FRAME, NULL, /* 窗口风格 */
  0, 0, 300, 300);

Create的实现如下, 这里我们主要看RegisterWindowClass

HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)
{
    if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
    if( GetSuperClassName() == NULL && !RegisterWindowClass() /*看这里*/ ) return NULL;
 if(m_bUnicode) {
#ifndef UNICODE
  LPWSTR lpClassName = a2w((char*)GetWindowClassName());
  LPWSTR lpName = a2w((char*)pstrName);
#else

RegisterWindowClass的实现如下, 这里我们主要看__WndProc

bool CWindowWnd::RegisterWindowClass()
{
    WNDCLASS wc = { 0 };
    wc.style = GetClassStyle();
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hIcon = NULL;
    wc.lpfnWndProc = CWindowWnd::__WndProc; // 看这里
    wc.hInstance = CPaintManagerUI::GetInstance();
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL;
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = GetWindowClassName();
    ATOM ret = ::RegisterClass(&wc);
    ASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS);
    return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
}

__WndProc的实现如下, 这里我们主要看HandleMessage

LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CWindowWnd* pThis = NULL;
    if( uMsg == WM_NCCREATE ) {
        LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
        pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
        pThis->m_hWnd = hWnd;
        ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
    } 
    else {
        pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
        if( uMsg == WM_NCDESTROY && pThis != NULL ) {
            LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
            ::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
            if( pThis->m_bSubclassed ) pThis->Unsubclass();
            pThis->m_hWnd = NULL;
            pThis->OnFinalMessage(hWnd);
            return lRes;
        }
    }
    if( pThis != NULL ) {
        return pThis->HandleMessage(uMsg, wParam, lParam); // 看这里
    } 
    else {
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}

下面是CWindowWndHandleMessage实现

LRESULT CWindowWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return ::CallWindowProc(m_OldWndProc, m_hWnd, uMsg, wParam, lParam);
}

由m_oldWndProc名称可知, 其为一个成员变量, 双击ctrl+q查看其使用, 可以发现其其实就是DefWindowProc
在这里插入图片描述
HandleMessage是一个虚函数, WindowImplBase 也有基本实现
WindowImplBase 的基本实现如下, 这里的实现可以让我们通过HandleCustomMessageOnCreate来接管处理原生win32api消息
在这里插入图片描述
这里的重点是渲染器m_PaintMessagerMessageHandler

if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
   return lRes;

其实现的代码量很大,我们可以通过IDE的搜索功能发现其会调用Notify, 也就是INotifyUI 接口
在这里插入图片描述
WindowImplBase实现了INotifyUI 接口, 下面是其的具体实现

 void WindowImplBase::Notify(TNotifyUI& msg)
 {
  return CNotifyPump::NotifyPump(msg);
 }

这个消息泵的实现代码量很大,其作用是为消息做分发, 从而让我们WindowImplBase的派生类可以使用下面的消息宏

 // MainWnd.h
 DUI_DECLARE_MESSAGE_MAP()
 void OnSetFocus(TNotifyUI& msg);
// MainWnd.cpp
DUI_BEGIN_MESSAGE_MAP(MainWnd, WindowImplBase)
DUI_ON_MSGTYPE(DUI_MSGTYPE_SETFOCUS, OnSetFocus)
DUI_END_MESSAGE_MAP()

void MainWnd::OnSetFocus(TNotifyUI& msg)
{
    if (msg.pSender->GetName() == _T("main-btn")) {
        ::MessageBox(GetHWND(), _T("设置焦点成功"), _T("我是标题"), MB_OK);
    }
}

WindowImplBase也有这个消息映射宏, 浏览代码时可以通过ctrl+k+o.cpp.h中切换, 其作用是用于对名为closebtn的按钮做默认处理的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值