duilib CNotifyPump

CNotifyPump 主要进行的是消息的映射还有相关VirtualWnd的操作

class UILIB_API CNotifyPump
{
public:
    bool AddVirtualWnd(CDuiString strName,CNotifyPump* pObject);
    bool RemoveVirtualWnd(CDuiString strName);
    void NotifyPump(TNotifyUI& msg);
    bool LoopDispatch(TNotifyUI& msg);
    DUI_DECLARE_MESSAGE_MAP()
private:
    CStdStringPtrMap m_VirtualWndMap;
};

这里用的比较好的是WinImplBase,在OnNotify中调用NotifyPump,当主窗口中有虚拟窗口,并且AddVirtualWnd之后,则会在调用主窗口的OnNotify之后,要去调用父类的__super::OnNotify。具体可以看官方demo中的RichListDemo

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

CRichListWnd::CRichListWnd(void)
{
    m_Page1.SetPaintMagager(&m_PaintManager);
    m_Page2.SetPaintMagager(&m_PaintManager);

    AddVirtualWnd(_T("page1"),&m_Page1);
    AddVirtualWnd(_T("page2"),&m_Page2);
}

CRichListWnd::~CRichListWnd(void)
{
    RemoveVirtualWnd(_T("page1"));
    RemoveVirtualWnd(_T("page2"));
}

那对应的消息映射跟MFC中的消息映射差不多。

声明中:DUI_DECLARE_MESSAGE_MAP()

最主要的是里面的virtual const DUI_MSGMAP* GetMessageMap() const; 是virtual函数

所以在CNotifyPump调用GetMessageMap的时候会去调用子类的GetMessageMap

结论:所以当使用消息映射的时候就必须继承CNotifyPump类。

特别是使用虚拟窗口的时候,因为没有具体的control父类,所以必须也只能使用CNotifyPump来进行消息映射。

那系统是如何知道当前的控件是属于虚拟窗口的呢?

1、在解析xml的时候当遇到virtualwnd的属性名字,则会调用对应的

void CControlUI::SetVirtualWnd(LPCTSTR pstrValue)
{
    m_sVirtualWnd = pstrValue;
    m_pManager->UsedVirtualWnd(true);
}

然后当某个控件发生消息响应的时候在void CPaintManagerUI::SendNotify(TNotifyUI& Msg, bool bAsync /*= false*/)函数中会有该操作:

    if( m_bUsedVirtualWnd )
    {
        Msg.sVirtualWnd = Msg.pSender->GetVirtualWnd();
    }

具体该GetVirtualWnd则可以看CControlUI的GetVirtualWnd函数,当本身的虚拟窗口的名称是空的时候则会父节点查找是否是父窗口。

这样的一系列操作之后,当调用CNotifyPump::NotifyPump的时候则就可以判断该控件是属于哪个虚拟窗口,进而通过Loopdispatch中查找该虚拟窗口对应的消息事件,并响应对应的事件操作。

注意:当前的主窗口要添加对应的虚拟窗口,否则在NotifyPump中即使本身是虚拟窗口也无法被找到。

AddVirtualWnd(_T("page1"),&m_Page1);

然后在析构的时候则需要RemoveVirtualWnd(_T("page1"));

================================================

这里额外说一下tooltip,刚开始一直不知道duilib使用什么机制进行显示的

当鼠标在某个控件上停留(WM_MOUSEHOVER)并且该控件有对应的tooltip内容,则程序会显示相应的内容。

具体是bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)的WM_MOUSEHOVER

            // Create tooltip information
            CDuiString sToolTip = pHover->GetToolTip();
            if( sToolTip.IsEmpty() ) return true;
            ::ZeroMemory(&m_ToolTip, sizeof(TOOLINFO));
            m_ToolTip.cbSize = sizeof(TOOLINFO);
            m_ToolTip.uFlags = TTF_IDISHWND;
            m_ToolTip.hwnd = m_hWndPaint;
            m_ToolTip.uId = (UINT_PTR) m_hWndPaint;
            m_ToolTip.hinst = m_hInstance;
            m_ToolTip.lpszText = const_cast<LPTSTR>( (LPCTSTR) sToolTip );
            m_ToolTip.rect = pHover->GetPos();
            if( m_hwndTooltip == NULL ) {
                m_hwndTooltip = ::CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hWndPaint, NULL, m_hInstance, NULL);
                ::SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip);
            }
            ::SendMessage( m_hwndTooltip,TTM_SETMAXTIPWIDTH,0, pHover->GetToolTipWidth());
            ::SendMessage(m_hwndTooltip, TTM_SETTOOLINFO, 0, (LPARAM) &m_ToolTip);
            ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &m_ToolTip);

但是这里发现一个小问题,就是控件为CEditUI并且里面的内容被选中的时候,使用tooltip鼠标只有在控件的边缘才能显示出来,在编辑框的内部时候却无法显示,具体这个则是因为CEditUI内部使用了系统默认的CEdit控件。

时间: 2024-10-17 06:53:26

duilib CNotifyPump的相关文章

Duilib中的消息泵和虚拟窗口

Duilib中的消息泵和虚拟窗口 一.消息泵的结构 CNotifyPump类是构建Duilib消息泵的根父类,要使用消息泵机制的窗口类应该从该类继承.在继承关系的基础上,通过DUI_DECLARE_MESSAGE_MAP.DUI_BEGIN_MESSAGE_MAP.DUI_END_MESSAGE_MAP.DUI_ON_MSGTYPE.DUI_ON_MSGTYPE_CTRNAME.DUI_ON_CLICK_CTRNAME.DUI_ON_SELECTCHANGED_CTRNAME.DUI_ON_KI

DUILIB虚拟窗口机制

转载请说明原出处,谢谢@@ Duilib虚拟界面由CNotifyPump类控制. CNotifyPump类提供了AddVirtualWnd方法, 按虚拟窗口名称为Key值,绑定CNotifyPump类型的虚拟窗口添加到虚拟窗口m_VirtualWndMap容器中. 看下方红色代码: boolCNotifyPump::AddVirtualWnd(CDuiString strName,CNotifyPump* pObject) { if( m_VirtualWndMap.Find(strName)

duilib DirectUI库里面的一个简单的例子RichListDemo

http://blog.csdn.net/zengraoli/article/details/9993153 2013-08-16 00:08 3289人阅读 评论(2) 收藏 举报 目录(?)[+] 1.首先来看这里的CRichListWnd 已经不再是从CWindowWnd继承了 classCRichListWnd:publicWindowImplBase 从WindowImplBase中,可以看到有三个抽象函数: virtualCDuiStringGetSkinFolder()=0; vi

Duilib中为RichEdit\Edit控件添加自定义右键菜单

前言 Duilib中的RichEdit控件在使用中发现,基本上对复制.粘贴.剪切等快捷方式都是支持的,不过唯一缺点是没有右键菜单,感觉不够好,于是就想着加上右键菜单. 右键菜单基本思路是,在RichEdit的消息处理函数中对鼠标的右键消息处理,发送一个自定义的Notify消息出来,主窗口中受到这个消息后弹出自己的右键菜单. 实现方法 第一步:把鼠标右键消息转发出来 MessageHandler中修改原有代码 bool bWasHandled = true; if( (uMsg >= WM_MOU

duilib 界面库 实现timer定时器

看了大神介绍的duilib感觉已被同龄人狠狠地甩在背后.所以痛下决心,之后要多花时间写代码. 大神教程传送门: http://www.cnblogs.com/Alberl/p/3341956.html 现在的问题是想基于duilib实现一个timer定时器.工程基础大概是在 http://www.cnblogs.com/Alberl/p/3343763.html 因为自己的东西是基于大神的东西写的,所以要把大神的教程看得差不多才知道我在说什么.O(∩_∩)O~~ 前台大概长这个样子: 稍微修改了

Duilib学习(一)

#pragma once #include <UIlib.h> using namespace DuiLib; #ifdef _DEBUG # ifdef _UNICODE # pragma comment(lib, "DuiLib_ud.lib") # else # pragma comment(lib, "DuiLib_d.lib") # endif #else # ifdef _UNICODE # pragma comment(lib, "

Duilib源码分析(五)UI布局—Layout

接下来,继续分析duilib之UI布局Layout,目前提供的布局有:VerticalLayout.HorizontalLayout.TileLayout.TabLayout.ChildLayout分别为垂直布局.水平布局.平铺布局.TAB布局.子窗体布局: 一般项目中用得比较多的是垂直布局.水平布局,我们将分别分析各布局: VerticalLayout:垂直布局,继承于CContainerUI容器UI类:而CContainerUI也继承于CControlUI,故VerticalLayout实际

duilib库分析: 消息流程分析

转 看下CWindowWnd类与CPaintManagerUI类是咋进行消息分发的吧. 1. 先看下CPaintManagerUI类的MessageLoop函数: void CPaintManagerUI::MessageLoop() { MSG msg = { 0 }; while( ::GetMessage(&msg, NULL, 0, 0) ) {    // 获取消息 if( !CPaintManagerUI::TranslateMessage(&msg) ) { // 消息过滤

分享个Duilib中基于wke的浏览器控件

概述 wke是基于谷歌chrome浏览器源代码的裁剪版本,大小仅仅只有10M左右,无需依赖其他的扩展库(跟CEF的一大堆大约40M的DLL来比简直爽呆了),就可以在本地使用谷歌内核快速加载网页.网上也有基于wke在Duilib 上扩展的控件代码,其实wke头文件挺清楚的了,接口一目了然,特别是JS与C++交互的函数更是容易看懂,也没什么难的,你也可以做到的. 代码 毕竟是裁剪库,有的功能还是没有接口来处理的(比如网页加载前.页面跳转.菜单消息--),头文件代码: #ifndef __UIWKEW