学习duilib
来源:互联网 发布:淘宝图片设计原则 编辑:程序博客网 时间:2024/04/29 01:26
学习duilib
最近在学习windows开发,真是两眼一抹黑,刚开始看windows的代码被全是大写和匈牙利命名法搞得生活不能自理。
主要是看书《Windows程序设计 5e》,最近发现了duilib,简单看了下用来写界面真是极好的,与Android非常相似,于是专研了几天,整理如下内容分享给大家,这样就能快速起飞……
目录
- 一个最基本的程序
- duilib定义的Notify方法中的事件类型
- 对UI的操作
- 开新线程做耗时操作以及回调
- 参考资料
一个最基本的程序
最基本的程序只需要一个入口main函数和一个window即可。先看看window应该如何定义。比如我想写一个功能为注册的窗口,取名为RegisterWindow。
新建一个RegisterWindow.cpp。代码如下:
// 这一坨头文件是为了使用duilib#define WIN32_LEAN_AND_MEAN#define _CRT_SECURE_NO_DEPRECATE#include <windows.h>#include <objbase.h>#include "..\DuiLib\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_u.lib")# else# pragma comment(lib, "DuiLib.lib")# endif#endif// 继承的是WindowImplBase这个类class RegisterWindow : public WindowImplBase{public: RegisterWindow() {}; virtual LPCTSTR GetWindowClassName() const { return _T("RegisterWindow"); } // 这里填写xml的路径,这个路径是相对于生成的exe的位置 virtual CDuiString GetSkinFile() { return _T("res\\layout\\register.xml"); } virtual CDuiString GetSkinFolder() { return _T(""); } virtual void InitWindow() { // 这个方法里可以做一些初始化操作 } virtual void Notify(TNotifyUI& msg) { // 这个方法里是duilib封装的一些事件的回调,它定义了一些msg type,然后根据消息的sender // 来得知这个消息是什么控件发送出来的 if (msg.sType == MSG_TYPE::CLICK) { if (msg.pSender->GetName() == _T("btn_next")) { // do your job } } // 这一行是必须的,可以帮助我们去处理一些预置的消息,比如closebtn这个按钮点击就会关闭窗口 __super::Notify(msg); } virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { // 这里可以获得windows的原始的所有消息 // 这一行是必须的,否则上面的notify方法就失效了 return __super::HandleMessage(uMsg, wParam, lParam); }};
然后xml文件,非常类似于Android中的布局文件。
具体可以参考这个教程:2013 duilib入门简明教程
Window准备好了,接下来就写一个main函数,作为程序的入口就行了。程序的入口我是放到一个单独的文件main.cpp中去写的。
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow){ CPaintManagerUI::SetInstance(hInstance); // 注意这一坨代码,以后开启另一个新的窗口也是用这样一坨类似的代码来搞就行了 RegisterWindow* pFrame = new RegisterWindow(); pFrame->Create(NULL, _T("测试"), UI_WNDSTYLE_FRAME | WS_VSCROLL, WS_EX_WINDOWEDGE); pFrame->CenterWindow(); pFrame->ShowModal(); delete pFrame; return 0;}
duilib定义的Notify方法中的事件类型
Notify方法中拿到的消息,type都是字符串类型的,这一点略微蛋疼(因为要写很多if),
这些msg type的定义在duilib的UIDefine.h
头文件中
#define DUI_MSGTYPE_MENU (_T("menu"))#define DUI_MSGTYPE_LINK (_T("link"))#define DUI_MSGTYPE_TIMER (_T("timer"))#define DUI_MSGTYPE_CLICK (_T("click"))#define DUI_MSGTYPE_RETURN (_T("return"))#define DUI_MSGTYPE_SCROLL (_T("scroll"))#define DUI_MSGTYPE_DROPDOWN (_T("dropdown"))#define DUI_MSGTYPE_SETFOCUS (_T("setfocus"))#define DUI_MSGTYPE_KILLFOCUS (_T("killfocus"))#define DUI_MSGTYPE_ITEMCLICK (_T("itemclick"))#define DUI_MSGTYPE_TABSELECT (_T("tabselect"))#define DUI_MSGTYPE_ITEMSELECT (_T("itemselect"))#define DUI_MSGTYPE_ITEMEXPAND (_T("itemexpand"))#define DUI_MSGTYPE_WINDOWINIT (_T("windowinit"))#define DUI_MSGTYPE_BUTTONDOWN (_T("buttondown"))#define DUI_MSGTYPE_MOUSEENTER (_T("mouseenter"))#define DUI_MSGTYPE_MOUSELEAVE (_T("mouseleave"))#define DUI_MSGTYPE_TEXTCHANGED (_T("textchanged"))#define DUI_MSGTYPE_HEADERCLICK (_T("headerclick"))#define DUI_MSGTYPE_ITEMDBCLICK (_T("itemdbclick"))#define DUI_MSGTYPE_SHOWACTIVEX (_T("showactivex"))#define DUI_MSGTYPE_ITEMCOLLAPSE (_T("itemcollapse"))#define DUI_MSGTYPE_ITEMACTIVATE (_T("itemactivate"))#define DUI_MSGTYPE_VALUECHANGED (_T("valuechanged"))#define DUI_MSGTYPE_SELECTCHANGED (_T("selectchanged"))
对UI的操作
duilib中的UI跟Android中的View很类似,基类是CControlUI。如果不需要对某个UI进行操作,比如一个logo,万年静止的图片,那么在xml里写好就行了。
如果对某个UI需要进行操作,比如在点击按钮的时候要改变一些属性什么的,就需要在代码中获取到这个UI的对象。
可以使用下面这行代码来获取,有点像findViewById
// 这一行代码可以放在window定义的InitWindow方法里面CEditUI* mAddressInput = static_cast<CEditUI*>(m_PaintManager.FindControl(_T("input_email_address")));
里面写的字符串input_email_address
是在xml中定义的name属性。
<Edit name="input_email_address" text="email address" bordersize="2" font="0" height="50" bordercolor="ffd3d5db" borderround="6, 6" padding="10, 0, 10, 0"/>
能获得某个UI对象的指针,就可以调用它的方法来进行操作了,这一点就是面向对象的那种套路了。不过我发现,调用某个方法后,需要调用NeedUpdate方法才会进行重绘。比如:
// 设置文本mAddressInput->SetText(HINT_EMAIL_ADDRESS_INPUT);// 调用这一行才生效mAddressInput->NeedUpdate();
更多更细节的API还不是很熟悉,再慢慢研究吧。
开新线程做耗时操作以及回调
开新线程有windows提供的CreateThread方法和C库提供的_beginthread方法(在process.h头文件里)。我比较习惯用第二个,因为参数少……
class RegisterWindow: public WindowImplBase {public: void __stdcall doWork(void* param) { for (int i = 0; i < 20; i++) { TCHAR* buffer = new TCHAR[100]; wsprintf(buffer, _T("doWork: %i \n"), i); OutputDebugString(buffer); delete[] buffer; Sleep(200); } HWND hwnd = (HWND)param; ::PostMessage(hwnd, 9999, NULL, NULL); }; //beginthread方法不能直接传一个成员方法进去,所以要用static方法裹一下 static void __cdecl doWorkWrap(void* param) { static_cast<RegisterWindow*>(param)->doWork(param); } virtual void Notify(TNotifyUI& msg) { if (msg.sType == _T("click")) { if (msg.pSender->GetName() == _T("btn_valid")) { //这里启动线程搞事情 HWND hwnd = GetHWND(); _beginthread(&RegisterWindow::doWorkWrap, 0, hwnd); } } __super::Notify(msg); } virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { // 在这里拿到9999消息 return __super::HandleMessage(uMsg, wParam, lParam); }}
掌握了上面着一些就可以做一些基本的异步操作了。
参考资料
- 2013 duilib入门简明教程
- duilib进阶教程
- github: duilib
- 学习duilib
- DuiLib学习-DuiLib中的通知事件
- duilib学习(一)第一duilib程序
- duilib学习笔记
- duilib学习笔记
- duilib学习笔记
- duilib 学习过程_20130507
- duilib学习笔记
- duilib学习笔记
- duilib学习笔记
- duilib学习笔记
- duilib学习笔记
- Duilib学习总结
- Duilib学习总结
- duilib学习资源汇总
- duilib学习笔记
- Duilib学习总结
- DuiLib学习(一)
- 杭州市高层次人才住房保障实施意见
- yolo模型的批量测试和位置输出
- slf4j-api、slf4j-log4j12以及log4j之间什么关系?
- HTML5学习---新新手怎样在云主机上部署html5项目
- 自定义IP核在SDK中添加驱动方法
- 学习duilib
- 深入浅出 Java Concurrency (1) : J.U.C的整体认识
- 安装mysqldb
- Spring MVC开发流程
- iOS 开发抽屉效果 MMDrawerController
- Java正则表达式
- 剑指offer——矩阵覆盖
- PLSQL 循环游标 cursor loop fetch into
- Android中的内存泄露(一.内存泄漏的认识以及LeakCannry的基本用法)