duilib
相关
局部静态变量初始化失败的问题
- 描述
- 调试一个实现了
exe
和dll
双形态的程序时发现,duilib
一些局部的static
变量new
出来是空的
- 调试一个实现了
1 2 3 4 5 6 7 |
// .cpp文件 /*CControlFactory* CControlFactory::GetInstance() { static CControlFactory* pInstance = new CControlFactory; return pInstance; }*/ |
-
原因
- 可能是
exe
和dll
对于全局变量、静态变量的初始化时机不一样
- 可能是
-
解决
- 把实现放到头文件里面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// .h文件 class UILIB_API CControlFactory { public: CControlUI* CreateControl(CDuiString strClassName); void RegistControl(CDuiString strClassName, CreateClass pFunc); static CControlFactory* GetInstance() { static CControlFactory* pInstance = new CControlFactory; return pInstance; } void Release(); private: // ... } |
dui
里面FindResource
失败
1 2 3 4 5 |
HRSRC hRes = ::FindResource(CPaintManagerUI::GetResourceDll(), L"IDR_ZIPRES1", L"ZIPRES"); // ↓ HRSRC hRes = ::FindResource(CPaintManagerUI::GetResourceDll(), MAKEINTRESOURCE(IDR_ZIPRES1), L"ZIPRES"); |
dui
的资源初始化
- 初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
void init_res() { #ifdef _DEBUG CPaintManagerUI::SetResourceType(UILIB_FILE); #else CPaintManagerUI::SetResourceType(UILIB_ZIPRESOURCE); #endif CDuiString str_res_path = CPaintManagerUI::GetInstancePath(); switch (CPaintManagerUI::GetResourceType()) { case UILIB_FILE: { str_res_path += L"skin"; CPaintManagerUI::SetResourcePath(str_res_path.GetData()); CResourceManager::GetInstance()->LoadResource(L"install.xml", NULL); break; } case UILIB_ZIPRESOURCE: { str_res_path += L"skin"; CPaintManagerUI::SetResourcePath(str_res_path.GetData()); HRSRC hRes = ::FindResource(CPaintManagerUI::GetResourceDll(), MAKEINTRESOURCE(IDR_ZIPRES1), L"ZIPRES"); if (hRes != NULL) { DWORD dwSize = 0; HGLOBAL hGlobal = ::LoadResource(CPaintManagerUI::GetResourceDll(), hRes); if (hGlobal != NULL) { dwSize = ::SizeofResource(CPaintManagerUI::GetResourceDll(), hRes); if (dwSize > 0) { CPaintManagerUI::SetResourceZip((LPBYTE)::LockResource(hGlobal), dwSize); CResourceManager::GetInstance()->LoadResource(L"install.xml", NULL); } } if (hGlobal != NULL) { ::FreeResource(hGlobal); } } break; } default: break; } } |
-
UILIB_FILE
- 上面选择在
debug
模式下使用文件
- 上面选择在
-
UILIB_ZIPRESOURCE
release
模式下,上面的做法是,把skin
文件夹里面的资源内容达成一个zip
包,然后把这个包作为自定义资源类型ZIPRES
,资源ID
为IDR_ZIPRES1
,打入了exe
rc
自定义资源见下节
dui
关于程序运行时大小图标
- 直接使用
LoadIcon
来设置 - 使用
dui
的CWindowWnd
类的SetIcon
函数发现,小图标设置不成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
CUnInstallWnd mainWnd; if (mainWnd.Create(NULL, _T("Win清理优化卸载程序"), UI_WNDSTYLE_FRAME, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 0, 0, 600, 400) == NULL) { return 0; } if (!CCommandParser::GetInstance()->IsSilent()) { HICON hIcon = ::LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); if (hIcon) { ::SendMessage(mainWnd.GetHWND(), WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); ::SendMessage(mainWnd.GetHWND(), WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); } mainWnd.CenterWindow(); mainWnd.ShowWindow(TRUE); } else { mainWnd.ShowWindow(FALSE); } |
dui
实现一个消息派发UI
窗口
- 头文件
- 不需要特意加消息循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#pragma once #include "dui_define.h" #include "simple_bind.h" void RunAsUIThread( ISimpleBind * pSimpleBind ); void AsyncToUIThread( ISimpleBind * pSimpleBind ); #define WM_SWITCH_TO_UI_THREAD (WM_USER + 1978) #define WM_ASYNC_TO_UI_THREAD (WM_USER + 1979) class CUIThreadWindow : public CWindowWnd { public: CUIThreadWindow(void); virtual ~CUIThreadWindow(void); static BOOL InitUIThreadWindow(void); static CUIThreadWindow * GetUIThreadWindow(void); static void DestroyUIThreadWindow(); virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override; protected: virtual CDuiString GetSkinFile() { return L""; } virtual LPCTSTR GetWindowClassName(void) const { return L"ui_thread_wnd"; } private: LRESULT OnSwitchToUIThreadMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled ); LRESULT OnAsyncToUIThreadMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled ); private: static CUIThreadWindow * m_pUIThreadWindow; }; |
- 源文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
#include "UIThreadWindow.h" CUIThreadWindow * CUIThreadWindow::m_pUIThreadWindow = NULL; CUIThreadWindow::CUIThreadWindow(void){ } CUIThreadWindow::~CUIThreadWindow(void) { } CUIThreadWindow * CUIThreadWindow::GetUIThreadWindow( void ) { return m_pUIThreadWindow; } LRESULT CUIThreadWindow::OnSwitchToUIThreadMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled ) { ISimpleBind * pBind = reinterpret_cast<ISimpleBind *>(wParam); if(pBind == NULL) return FALSE; pBind->SimpleInvolk(); return TRUE; } LRESULT CUIThreadWindow::OnAsyncToUIThreadMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled ) { ISimpleBind * pBind = reinterpret_cast<ISimpleBind *>(wParam); if(pBind == NULL) return FALSE; pBind->SimpleInvolk(); delete pBind; pBind = NULL; return TRUE; } BOOL CUIThreadWindow::InitUIThreadWindow( void ) { if (m_pUIThreadWindow) return TRUE; m_pUIThreadWindow = new CUIThreadWindow; if(m_pUIThreadWindow == NULL) return NULL; HWND hWnd = m_pUIThreadWindow->Create(NULL, NULL, WS_POPUP, NULL); return hWnd != NULL; } void CUIThreadWindow::DestroyUIThreadWindow() { if (m_pUIThreadWindow) { m_pUIThreadWindow->Close(); m_pUIThreadWindow = NULL; } } void RunAsUIThread( ISimpleBind * pSimpleBind ) { CUIThreadWindow * pWnd = CUIThreadWindow::GetUIThreadWindow(); if(pWnd == NULL) return; pWnd->SendMessage(WM_SWITCH_TO_UI_THREAD, (WPARAM)pSimpleBind); } void AsyncToUIThread( ISimpleBind * pSimpleBind ) { CUIThreadWindow * pWnd = CUIThreadWindow::GetUIThreadWindow(); if(pWnd == NULL) return; pWnd->PostMessage(WM_ASYNC_TO_UI_THREAD, (WPARAM)pSimpleBind); } LRESULT CUIThreadWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = __super::HandleMessage(uMsg, wParam, lParam); BOOL bHandled = 0; switch (uMsg) { case WM_SWITCH_TO_UI_THREAD: lRes = OnSwitchToUIThreadMessage(uMsg, wParam, lParam, bHandled); break; case WM_ASYNC_TO_UI_THREAD: lRes = OnAsyncToUIThreadMessage(uMsg, wParam, lParam, bHandled); break; default: break; } return lRes; } |
- 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void RunAsUIThread( ISimpleBind * pSimpleBind ) { CUIThreadWindow * pWnd = CUIThreadWindow::GetUIThreadWindow(); if(pWnd == NULL) return; pWnd->SendMessage(WM_SWITCH_TO_UI_THREAD, (WPARAM)pSimpleBind); } void AsyncToUIThread( ISimpleBind * pSimpleBind ) { CUIThreadWindow * pWnd = CUIThreadWindow::GetUIThreadWindow(); if(pWnd == NULL) return; pWnd->PostMessage(WM_ASYNC_TO_UI_THREAD, (WPARAM)pSimpleBind); } auto bind = simple_bind(&CInstaller::OnInstallStartOnUI, this); RunAsUIThread(&bind); |
- 解析
CUIThreadWindow
这个窗口类不会显示出来,在其他非主线程的线程上,可以把一些UI
相关的任务通过消息的方式在这个CUIThreadWindow
派发窗口上去执行
vs
相关
关于byte
和std::byte
二义性问题
- 描述
- 处理上述双形态功能时遇到了这个问题
- 原因
Windows
的sdk
对byte
有一个定义,而std
里面对byte
也有一个定义- 当引入了
Windows
的一些头文件,且直接或间接引入了<cstddef>
时,可能会导致这个问题
- 解决
- 在代码中搜索
using namespace std
,注释掉,并修改相应部位
- 在代码中搜索
1 2 3 4 5 |
string test(); // ↓ std::string test(); |
rc
自定义资源
- 资源视图里面,选择某个工程的
rc
打开,添加资源,自定义,ZIPRES
- 确定后,同时会生成一个默认的
IDR_ZIPRES1
- 解决方案资源管理器里面,找到要保存资源的筛选器,如资源文件
- 右键,添加,资源,选择
ZIPRES
,导入 - 这样会生成资源
ID
为IDR_ZIPRES2
- 删掉
IDR_ZIPRES1
- 重命名
IDR_ZIPRES2
为IDR_ZIPRES1
- 打开
Resource.h
删掉重复的资源id
,比如此时IDR_ZIPRES1
和IDR_ZIPRES2
的值都为130
,只留IDR_ZIPRES1
- 右键,添加,资源,选择
- 右键,
rc
文件,编译
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Duilib应用:安装程序相关09/30
- ♥ Duilib切换界面区域布局11/04
- ♥ 2023_02_1502/20
- ♥ 查找_二分查找05/09
- ♥ Dump分析:空指针访问二,重复释放堆内存二03/30
- ♥ 贪心算法06/29