zoukankan      html  css  js  c++  java
  • 使用dulilib DirectUI库(一)

    1、在创建的窗口类里面

    需要继承CWindowWndINotifyUI


    对于CWindowWnd里面的方法:


    实现CWindowWnd的方法virtualLPCTSTRGetWindowClassName()const=0;,重载virtualUINTGetClassStyle()const;返回窗口的风格类型,重载virtualvoidOnFinalMessage(HWNDhWnd);

    对于INotifyUI里面的,只有一个唯一的抽象方法:

    virtualvoidNotify(TNotifyUI&msg)=0;

     

    当你实现了这个Notify,才能正常的接收、处理消息

    来看看主要的消息处理部分:

    void Notify(TNotifyUI& msg)
    {
    	if( msg.sType == _T("windowinit") ) OnPrepare();
    	else if( msg.sType == _T("click") ) {
    		if( msg.pSender->GetName() == _T("insertimagebtn") ) {
    			CRichEditUI* pRich = static_cast<CRichEditUI*>(m_pm.FindControl(_T("testrichedit")));
    			if( pRich ) {
    				pRich->RemoveAll();
    			}
    		}
    		else if( msg.pSender->GetName() == _T("changeskinbtn") ) {
    			if( CPaintManagerUI::GetResourcePath() == CPaintManagerUI::GetInstancePath() )
    				CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin\FlashRes"));
    			else
    				CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());
    			CPaintManagerUI::ReloadSkin();
    		}
    	}
    }
    


    分开来看:

    a、

    void Notify(TNotifyUI& msg)
    {
    	if( msg.sType == _T("windowinit") ) OnPrepare();
    }
    

    窗口刚创建的时候,发出来的消息时windowsinit,所以这里进行OnPrepare();

    void OnPrepare() 
    {
    	CSliderUI* pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("alpha_controlor")));
    	if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnAlphaChanged);
    	pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("h_controlor")));
    	if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnHChanged);
    	pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("s_controlor")));
    	if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnSChanged);
    	pSilder = static_cast<CSliderUI*>(m_pm.FindControl(_T("l_controlor")));
    	if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnLChanged);
    }
    

    这种方法很简单,只是找到每一个CSliderUI,而且是通过CPaintManagerUIFindControl方法(参数为xml中描述的每一个CSliderUI的名称)

     

    找到之后进行:

    if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &CFrameWindowWnd::OnAlphaChanged);


    主要是给这个CSliderUI加上消息的映射,MakeDelegate的两个参数分别是哪个UI控件(object)和需要绑定的方法

     

    b、第二种事件类型

    void Notify(TNotifyUI& msg)
    {
    	else if( msg.sType == _T("click") ) {
    		else if( msg.pSender->GetName() == _T("changeskinbtn") ) {
    			if( CPaintManagerUI::GetResourcePath() == CPaintManagerUI::GetInstancePath() )
    				CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin\FlashRes"));
    			else
    				CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());
    			CPaintManagerUI::ReloadSkin();
    		}
    	}
    }
    

    这里有这么多的事件要处理,就拿一个换肤的例子来看看(如上面的例子):

    其实也很简单,这么多的代码,只是找到对应的资源路径(比如最上边的一个if语句,判断当前的资源路径是否和当前的程序实例的路径相等,如果相等就……),比如这里"skin\FlashRes",前面再加上项目的路径,来构成一个绝对路径。

    CPaintManagerUI::ReloadSkin();是用来,替换资源的,比如xml中有一个资源的是这样的:


    我们的资源路径下面有:


    那么执行了这个方面,在使用到winbk.bmp的地方就会被直接替换掉了。


    2、那么我的小伙伴们都要奇怪了,这个程序在什么地方响应windows的消息呢?

    看看这段代码:

    	LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    	{
    		if( uMsg == WM_CREATE ) {
     			m_pm.Init(m_hWnd);
     			CDialogBuilder builder;
     			CControlUI* pRoot = builder.Create(_T("test1.xml"), (UINT)0, NULL, &m_pm);
     			ASSERT(pRoot && "Failed to parse XML");
     			m_pm.AttachDialog(pRoot);
     			m_pm.AddNotifier(this);
     			Init();
    			return 0;
    		}
    		else if( uMsg == WM_DESTROY ) {
    			::PostQuitMessage(0L);
    		}
    		else if( uMsg == WM_ERASEBKGND ) {
    			return 1;
    		}
    		LRESULT lRes = 0;
    		if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
    		return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
    	}

    一看这里的WM_CREATE,就知道他是对windows的消息进行响应的部分。

    这里只看WM_CREATE消息,其他的部分要么是退出的消息,要么就是北京擦除的消息、让windows自动处理默认消息的。


    WM_CREATE消息

    if( uMsg == WM_CREATE ) {
     			m_pm.Init(m_hWnd);
     			CDialogBuilder builder;
     			CControlUI* pRoot = builder.Create(_T("test1.xml"), (UINT)0, NULL, &m_pm);
     			ASSERT(pRoot && "Failed to parse XML");
     			m_pm.AttachDialog(pRoot);
     			m_pm.AddNotifier(this);
     			Init();
    			return 0;
    		}


    可以看到首先需要对CPaintManagerUI进行初始化,窗口的句柄是在CWindowWnd中的

    得到的,CFrameWindowWnd继承了CWindowsWnd,所以这个成员变量的值自然也就存在了。CDialogBuilder是一个对话框的创建者,他负责创建一个对话框,在以这个库做UI的窗体,都是以对话框的形式显示出来的。

    CControlUI* pRoot = builder.Create(_T("test1.xml"), (UINT)0, NULL, &m_pm);


    通过xml文件和CPaintManagerUI来创建一个对话框,创建出来的对话框作为顶层(其他的控件作为子层)保存在pRoot中。最后把这个对话框放入到渲染管理(CPaintManagerUI大管家)中,这样duilib就能自己去渲染出来了。m_pm.AddNotifier(this);对这个大管家设置消息响应的类。这样一个检查的初始化就完成了。



    3main函数

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
    {
    	HRESULT Hr = ::CoInitialize(NULL);
    	CFrameWindowWnd* pFrame = new CFrameWindowWnd();	pFrame->Create(NULL, _T("这是一个最简单的测试用exe,修改test1.xml就可以看到效果"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    	pFrame->CenterWindow();
    	pFrame->ShowWindow(true);
    	CPaintManagerUI::MessageLoop();
    
    	::CoUninitialize();
    	return 0;
    }

    CFrameWindowWnd*是我们重载的类,通过creat可以创建出来一个实例,CenterWindow()可以创建一个窗体,ShowWindow(true)可以把窗体给显示出来。CPaintManagerUI::MessageLoop()进行整个UI的消息循环。

    CoInitializeCoUninitialize是初始化com的。

  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3260380.html
Copyright © 2011-2022 走看看