简介:
Duilib 是一款强大的界面开发工具,可以将用户界面和处理逻辑彻底分离,极大地提高用户界面的开发效率。提供所见即所得的开发工具UIDesigner。使用DirectUI后将使得我们的设计人员彻底解 放,不会受到开发的束缚,可以充分地发挥其设计能力来设计软件界面,并参与到用户界面开发过程中。 Duilib 目前支持Windows 32 、Window CE、Mobile等平台,使用C++开发,遵循BSD协议,可以免费用于商业项目 。
ListDemo
源码学习
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin"));
CPaintManagerUI::SetResourceZip(_T("ListRes.zip"));
ListMainForm* pFrame = new ListMainForm();
if( pFrame == NULL ) return 0;
pFrame->Create(NULL, _T("ListDemo"), UI_WNDSTYLE_FRAME, WS_EX_STATICEDGE | WS_EX_APPWINDOW , 0, 0, 600, 320);
pFrame->CenterWindow();
::ShowWindow(*pFrame,
CPaintManagerUI::MessageLoop();
return 0;
}
duilib库使用的基本流程
1):实例句柄与渲染类关联 ==主函数中的第一段代码
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetResourcePath(LPCTSTRpStrPath)
2):初始化COM库,为加载COM库提供支持
::CoInitialize
3):创建窗口类,主函数中的第二段代码主要完成的是类CDuiFrameWnd对象的创建,我们跟到对应的构造函数中发现它并没有做多余的操作,现在先不管它是如何构造的,它下面就是调用了类的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;
}
4):调用CWindowWnd::Create创建窗口,Create函数实现了注册窗口,指定回调函数,创建窗口,处理消息等。
5):窗口居中
CWindowWnd::CenterWindow
6):处理消息循环
CPaintManagerUI::MessageLoop
7):CPaintManagerUI::MessageLoop
::CoUninitialize()
8):窗口类中需要重写MessageHandle函数用于处理我们感兴趣的消息。并且在最后需要调用基类的MessageHandle函数,主要是为了调用DefWindowProc处理我们不感兴趣的消息。
目前认知:
对于消息的处理等情况,自己封装一个类,根据需要继承相应的库中提供的类
例如:我目前所看的Demo中 ListMainForm继承了三个类CWindowWnd, INotifyUI, IListCallbackUI
介绍:
CWindowWnd 主要处理窗口问题:是窗口对象的父类,负责创建窗口 窗口消息过程处理
//获取当前窗口的句柄
HWND GetHWND() const;
//显示 或 隐藏窗口 其实是调用了win32的api ::ShowWindow
void ShowWindow(bool bShow = true, bool bTakeFocus = true);
//多窗口时用到
UINT ShowModal();
//向本窗口发送WM_CLOSE消息
void Close(UINT nRet = IDOK);
//计算坐标以后,调用系统SetWindowPos函数,使窗口居中显示
void CenterWindow(); // 居中,支持扩展屏幕
void SetIcon(UINT nRes);//对进程发送了WM_SETICON这个消息,分2次设置图标和小图标
void ResizeClient(int cx = -1, int cy = -1);//重新设置窗口尺寸大小,宽和高
INotifyUI :功能 处理事件和通知
CPaintManagerUI :负责窗口图形绘制
CDialogbuilder :控件布局类 主要作用是解析XML构建控件树,创建控件对象
CControlUI :控件管理的父类。为控件提供通用属性
ListMainForm继承自CWindowWnd, INotifyUI, IListCallbackUI
重写CWindowWnd的虛函数GetWindowClassName、HandleMessage和INotify的虛函数Notify
功能:GetWindowClassName返回窗口名称
HandleMessage处理消息
Notify事件应答 例如点击事件
CPaintManagerUI m_manager.init(m_hwnd);初始化当前窗口
CDialogBuilder builder;
CControlUI *PRoot = builder.Create(_T("dui-design.xml"),(UINT)0,NULL,&m_manager);//加载窗口设计XML文档,初始化窗口部件
加载完XML,窗体定义完成之后,就需要添加对按钮事件的处理,要在重载的Notify函数中编写
窗口绘制完 按钮处理结束,接着在入口函数中为之初始化与分配中资源:
就是博文开始 WinMain中的过程
以上就是duilib库的使用流程。
然后继续ListDemo的学习
LPCTSTR GetWindowClassName() const //LPCTSTR ==> const char*
{
return _T("ScanMainForm"); //给这个类创建一个名称 必须重写
}; //不同的窗体有不同的名字
UINT GetClassStyle() const
{
return CS_DBLCLKS; //设置窗体风格 一般不重用写
};
void init()
{
m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
//FindControl在CPaintManagerUI中到closebtn按钮交给CButtonUI的对象管理 就是XML中的按钮
......
}