• duilib整体的操作流程


    刚开始的时候设置

    CPaintManagerUI::SetInstance(hInstance);
    CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());
    ::CoInitialize(NULL);

    这里设置的resourcepath是接下去图片资源的位置。

    并初始化了COM库,并且在退出的时候要执行::CoUninitialize();

    CMainWndDlg* pMainDlg = new CMainWndDlg();
    pMainDlg->Create(NULL, _T("cxiaoln窗体"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    pMainDlg->CenterWindow();
    pMainDlg->ShowModal();

    接下去是Create函数,里面执行的是

    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;
        m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetInstance(), this);
        ASSERT(m_hWnd!=NULL);
        return m_hWnd;
    }
    View Code

    这里首先要判断的是否是SuperClassName,关于这个SuperClassName我们在CEditUI中已经说明了。如果是系统本身自带的控件则使用SuperClassName,如果自己创建的窗口则调用普通的GetWindowClassName

    注册完成窗口之后,接下去就是创建窗口::CreateWindowEx

    再接下去就是ShowModal,进行消息的循环。其实从ShowModal 我们发现它的消息循环跟CPaintManagerUI::MessageLoop();的消息循环是差不多的。消息都要先让CPaintManagerUI::TranslateMessage(&msg)进行处理,如果没有对应的控件进行处理才进入

    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);

    进行消息处理。

    为什么要这样子呢? 其实我们稍微分析一下就知道了,我们在创建窗口的时候创建的其实只是一个面板,然后具体的界面上面的按钮其实只是一些图片。或者颜色的绘制。具体这些界面上面的空间如何或者响应待会再讲。

    先说这里的ShowModal则会开始调用消息。

    按创建窗体一般的思路就传递WM_CREATE的消息,然后再传递WM_SIZE消息。pThis->HandleMessage(uMsg, wParam, lParam);

    所以就会调用

    首先创建窗口:OnCreate

    LRESULT CMainWndDlg::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
    {
        m_PaintManager.Init(m_hWnd);
    
        CDialogBuilder builder;
        CControlUI* pRoot = builder.Create(_T("DemoSkin.xml"), (UINT)0, NULL, &m_PaintManager);   // DemoSkin.xml需要放到exe目录下
        ASSERT(pRoot && "Failed to parse XML");
    
        m_PaintManager.AttachDialog(pRoot);
        m_PaintManager.AddNotifier(this);   // 添加控件等消息响应,这样消息就会传达到duilib的消息循环,我们可以在Notify函数里做消息处理
    
        Init();
    
        return 0;
    }
    View Code

    这里首先进行了m_PaintManager.Init(m_hWnd);先进行了初始化,

    void CPaintManagerUI::Init(HWND hWnd)
    {
        ASSERT(::IsWindow(hWnd));
        // Remember the window context we came from
        m_hWndPaint = hWnd;
        m_hDcPaint = ::GetDC(hWnd);
        // We'll want to filter messages globally too
        m_aPreMessages.Add(this);
    }
    View Code

    这里将m_PaintManager添加进了m_aPreMessages的数组。当在调用PreMessageHandler时,会先调用相关的有继承IMessageFilterUI的UI,但是我们发现这个数组是静态的,如果进行多线程的操作时候很有可能会出现多线程不安全的情况。所以多线程的时候得慎用。

    在Init之后则会使用CDialogBuilder类进行了创建,builder.Create(xml),即解析xml函数,具体如何解析在上一章中已经说明了。

    然后这里的AttachDialog,顾名思义就是将pRoot跟CPaintManager关联起来,其实主要是获取pRoot的各种参数(里面保存了xml文件解析的各种数据)。

    接下去如果有继承INotify类,则这里可以添加AddNotifier(this),从而,当有事件发生并发送了SendNotify的时候,OnNotify函数则会收到相应的消息。具体发送的消息内容则根据每个UI控件。

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

    那每个控件是如何响应的呢?

    其实原理很简单,就是点击鼠标的时候,根据鼠标所在的位置当前的控件是什么FindControl(pt)来进行响应该操作对应的事件。具体可以看bool CPaintManagerUI::MessageHandler

    如果出现重叠控件怎么办?

    其实在最开始解析xml的时候已经给了答案了,它在将控件放进容器控件中时是按顺序存放的,当它在滚动台哦还有其他参数的方式进行查找还是没找到时候,则会进行如下方式的操作

    if( (uFlags & UIFIND_TOP_FIRST) != 0 ) {
                for( int it = m_items.GetSize() - 1; it >= 0; it-- ) {
                    CControlUI* pControl = static_cast<CControlUI*>(m_items[it])->FindControl(Proc, pData, uFlags);
                    if( pControl != NULL ) {
                        if( (uFlags & UIFIND_HITTEST) != 0 && !pControl->IsFloat() && !::PtInRect(&rc, *(static_cast<LPPOINT>(pData))) )
                            continue;
                        else 
                            return pControl;
                    }            
                }
            }
    View Code

    是从后往前进行遍历查找,即使同一个位置有两个控件它也能很容易的找到最后放进去的那个(isfloat)

  • 相关阅读:
    348. Design Tic-Tac-Toe
    347. Top K Frequent Elements
    346. Moving Average from Data Stream
    345. Reverse Vowels of a String
    343. Integer Break
    342. Power of Four
    341. Flatten Nested List Iterator
    340. Longest Substring with At Most K Distinct Characters
    339. Nested List Weight Sum
    Python(九) Python的高级语法与用法
  • 原文地址:https://www.cnblogs.com/cxiaoln/p/4412935.html
Copyright © 2020-2023  润新知