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的。

  • 相关阅读:
    结对编程2—单元测试
    个人作业2—英语学习APP案例分析
    结对作业--基于GUI的四则运算生成器
    基于控制台的四则运算
    关于软件工程这门课
    个人作业3——个人总结(Alpha阶段)
    结对编程2——单元测试
    个人作业2——英语学习APP案例分析
    结对作业--基于GUI的四则运算生成器
    个人作业一
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3260380.html
Copyright © 2011-2022 走看看