关于圆角
没有子窗口
- 如果SOUI的宿主窗口没有包含子窗口,直接使用窗口的半透明属性:translucent=1就可以解决了,整个窗口形状完全由背景图决定,可以实现完美的圆角。
有子窗口
- 窗口半透明时,窗口中的子窗口(非SWindow)就不能正常显示,所以有时候不得不使用translucent=0,这时窗口就成了方形。
- translucent
- 窗口透明此属性子窗口不能使用真窗口 0不透明 1透明
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 |
template <class T> class CWHRoundRectFrameHelper { protected: SIZE m_sizeWnd; void OnSize(UINT nType, CSize size) { T *pT = static_cast<T*>(this); if (nType == SIZE_MINIMIZED) return; if (size == m_sizeWnd) return; CRect rcWindow, rcClient; CRgn rgnWindow, rgnMinus, rgnAdd; pT->CSimpleWnd::GetWindowRect(rcWindow); pT->CSimpleWnd::GetClientRect(rcClient); pT->CSimpleWnd::ClientToScreen(rcClient); rcClient.OffsetRect(- rcWindow.TopLeft()); rgnWindow.CreateRectRgn(rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2); rgnAdd.CreateRectRgn(rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1); rgnWindow.CombineRgn(rgnAdd, RGN_OR); rgnAdd.OffsetRgn(0, rcClient.Height() - 1); rgnWindow.CombineRgn(rgnAdd, RGN_OR); rgnAdd.SetRectRgn(rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2); rgnWindow.CombineRgn(rgnAdd, RGN_OR); rgnAdd.OffsetRgn(0, rcClient.Height() - 3); rgnWindow.CombineRgn(rgnAdd, RGN_OR); pT->CSimpleWnd::SetWindowRgn(rgnWindow); pT->SetMsgHandled(FALSE); m_sizeWnd = size; } public: BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) { BOOL bHandled = TRUE; switch(dwMsgMapID) { case 0: if (uMsg == WM_SIZE) { OnSize((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); lResult = 0; } break; } return FALSE; } }; |
1 2 3 4 5 6 7 8 9 10 11 |
class CFuckDialog : public SHostDialog , public CWHRoundRectFrameHelper<CFuckDialog> { //xxxxx //HOST消息及响应函数映射表 BEGIN_MSG_MAP_EX(CMainDlg) CHAIN_MSG_MAP(CWHRoundRectFrameHelper<CFuckDialog >)//重要 CHAIN_MSG_MAP(SHostDialog) REFLECT_NOTIFICATIONS_EX() END_MSG_MAP() //xxxx }; |
动态多语言切换
ITranslatorMgr
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
namespace SOUI { /** * @struct ITranslator * @brief 语言翻译接口 * * Describe */ struct ITranslator : public IObjRef { /** * Load * @brief 从资源中加载语言翻译数据 * @param LPVOID pData -- 资源指针,具体含义由接口的实现来解释 * @param UINT uType -- 资源类型,具体含义由接口的实现来解释 * @return BOOL true-加载成功, false-加载失败 * * Describe */ virtual BOOL Load(LPVOID pData,UINT uType)=0; /** * name * @brief 获取翻译资源的name * @return SOUI::SStringW 翻译资源的name * * Describe */ virtual SStringW name()=0; /** * guid * @brief 获取翻译资源的ID * @return GUID 翻译资源的ID * * Describe */ virtual GUID guid()=0; /** * tr * @brief 执行翻译的接口 * @param const SStringW & strSrc -- 原字符串 * @param const SStringW & strCtx -- 翻译上下文 * @param SStringW & strRet -- 翻译后的字符串 * @return BOOL true-翻译成功,false-翻译失败 * * Describe */ virtual BOOL tr(const SStringW & strSrc,const SStringW & strCtx,SStringW & strRet)=0; }; /** * @struct ITranslatorMgr * @brief 语言翻译接口管理器 * * Describe */ struct ITranslatorMgr : public IObjRef { /** * SetLanguage * @brief 设置翻译模块当前接受的语言 * @param [in] const SStringW & strLang -- 翻译语言 * * Describe 自动清除语言和目标语言不同的模块 */ virtual void SetLanguage(const SStringW & strLang) = 0; /** * GetLanguage * @brief 获取翻译模块当前接受的语言 * @return SStringW -- 翻译语言 * * Describe */ virtual SStringW GetLanguage() const = 0; /** * CreateTranslator * @brief 创建一个语言翻译对象 * @param [out] ITranslator * * ppTranslator -- 接收语言翻译对象的指针 * @return BOOL true-成功,false-失败 * * Describe */ virtual BOOL CreateTranslator(ITranslator ** ppTranslator)=0; /** * InstallTranslator * @brief 向管理器中安装一个语言翻译对象 * @param ITranslator * ppTranslator -- 语言翻译对象 * @return BOOL true-成功,false-失败 * * Describe */ virtual BOOL InstallTranslator(ITranslator * ppTranslator) =0; /** * UninstallTranslator * @brief 从管理器中卸载一个语言翻译对象 * @param REFGUID id -- 语言翻译对象的ID * @return BOOL true-成功,false-失败 * * Describe */ virtual BOOL UninstallTranslator(REFGUID id) =0; /** * tr * @brief 翻译字符串 * @param const SStringW & strSrc -- 原字符串 * @param const SStringW & strCtx -- 翻译上下文 * @return SOUI::SStringW 翻译后的字符串 * * Describe 调用ITranslator的tr接口执行具体翻译过程 */ virtual SStringW tr(const SStringW & strSrc,const SStringW & strCtx)=0; }; } |
- 用户切换UI语言后,使用SDispatchMessage方法向所有SWindow发送UM_SETLANGUAGE消息
- SWindow收到该消息后对窗口中需要做语言翻译的对象重新翻译语言后更新显示
设置翻译模块
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 |
HRESULT hRes = OleInitialize(NULL); SASSERT(SUCCEEDED(hRes)); int nRet = 0; SComMgr *pComMgr = new SComMgr; //将程序的运行路径修改到项目所在目录所在的目录 TCHAR szCurrentDir[MAX_PATH] = { 0 }; GetModuleFileName(NULL, szCurrentDir, sizeof(szCurrentDir)); LPTSTR lpInsertPos = _tcsrchr(szCurrentDir, _T('\\')); _tcscpy(lpInsertPos + 1, _T("..\\SouiWizard1")); SetCurrentDirectory(szCurrentDir); { BOOL bLoaded=FALSE; CAutoRefPtr<SOUI::IImgDecoderFactory> pImgDecoderFactory; CAutoRefPtr<SOUI::IRenderFactory> pRenderFactory; CAutoRefPtr<ITranslatorMgr> trans; //多语言翻译模块,由translator.dll提供 bLoaded = pComMgr->CreateRender_GDI((IObjRef**)&pRenderFactory); SASSERT_FMT(bLoaded,_T("load interface [render] failed!")); bLoaded=pComMgr->CreateImgDecoder((IObjRef**)&pImgDecoderFactory); SASSERT_FMT(bLoaded,_T("load interface [%s] failed!"),_T("imgdecoder")); bLoaded = pComMgr->CreateTranslator((IObjRef**)&trans); SASSERT_FMT(bLoaded, _T("load interface [%s] failed!"), _T("translator")); pRenderFactory->SetImgDecoderFactory(pImgDecoderFactory); SApplication *theApp = new SApplication(pRenderFactory, hInstance); //从DLL加载系统资源 HMODULE hModSysResource = LoadLibrary(SYS_NAMED_RESOURCE); if (hModSysResource) { CAutoRefPtr<IResProvider> sysResProvider; CreateResProvider(RES_PE, (IObjRef**)&sysResProvider); sysResProvider->Init((WPARAM)hModSysResource, 0); theApp->LoadSystemNamedResource(sysResProvider); FreeLibrary(hModSysResource); }else { SASSERT(0); } CAutoRefPtr<IResProvider> pResProvider; #if (RES_TYPE == 0) CreateResProvider(RES_FILE, (IObjRef**)&pResProvider); if (!pResProvider->Init((LPARAM)_T("uires"), 0)) { SASSERT(0); return 1; } #else CreateResProvider(RES_PE, (IObjRef**)&pResProvider); pResProvider->Init((WPARAM)hInstance, 0); #endif theApp->InitXmlNamedID(namedXmlID,ARRAYSIZE(namedXmlID),TRUE); theApp->AddResProvider(pResProvider); if (trans) {//加载中文语言翻译包 theApp->SetTranslator(trans); pugi::xml_document xmlLang; if (theApp->LoadXmlDocment(xmlLang, _T("cn"), _T("lang"))) { CAutoRefPtr<ITranslator> langCN; trans->CreateTranslator(&langCN); langCN->Load(&xmlLang.child(L"language"), 1);//1=LD_XML trans->InstallTranslator(langCN); } } // BLOCK: Run application { CMainDlg dlgMain; dlgMain.Create(GetActiveWindow()); dlgMain.SendMessage(WM_INITDIALOG); dlgMain.CenterWindow(dlgMain.m_hWnd); dlgMain.ShowWindow(SW_SHOWNORMAL); nRet = theApp->Run(dlgMain.m_hWnd); } delete theApp; } delete pComMgr; OleUninitialize(); return nRet; } |
切换语言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void CMainDlg::OnLanguage(int nID) { ITranslatorMgr *pTransMgr = SApplication::getSingletonPtr()->GetTranslator(); bool bCnLang = nID == R.id.lang_cn; pugi::xml_document xmlLang; if (SApplication::getSingletonPtr()->LoadXmlDocment(xmlLang, bCnLang?_T("cn"):_T("en"), _T("lang"))) { CAutoRefPtr<ITranslator> lang; pTransMgr->CreateTranslator(&lang); lang->Load(&xmlLang.child(L"language"), 1);//1=LD_XML pTransMgr->SetLanguage(lang->name()); pTransMgr->InstallTranslator(lang); SDispatchMessage(UM_SETLANGUAGE,0,0); //soui2.6 新增加的方法。 } } |
异步任务
接口
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 |
#pragma once #include <unknown/obj-ref-i.h> namespace SOUI { struct IRunnable { virtual ~IRunnable() {} virtual IRunnable* clone() const = 0; virtual void run() = 0; virtual void *getObject() = 0; virtual const char *getClassInfo() const = 0; }; struct ITaskLoop : public IObjRef { enum Priority { High = 1, Normal = 0, Low = -1, }; virtual bool getName(char *pszBuf, int nBufLen) = 0; /** * Start a thread to run. * @param priority the thread priority */ virtual void start(const char * pszName,Priority priority) = 0; /** * Stop thread synchronized. */ virtual void stop() = 0; /** * postTask post or send a tasks to this task manager. * @param runnable the to be run task object. * @param waitUntilDone, true for send and false for post. * @param priority, the task priority. * @return the task id, can be used by cancelTask. */ virtual long postTask(const IRunnable *runnable, bool waitUntilDone, int priority=0) = 0; /** * Remove tasks for a specific object from task loop pending task list * @param object the specific object wants pending functors to be removed */ virtual void cancelTasksForObject(void *object) = 0; /** * Cancel tasks for a specific task ID list * @param taskList the task ID list to be canceled * @return the removed task list. */ virtual bool cancelTask(long taskId) = 0; /** * get the total task number in the task loop queue. * @return total task number in task loop queue */ virtual int getTaskCount() const = 0; /** * get the run loop status. * @return the running status */ virtual bool isRunning() = 0; /** * get the running task info. * @param buf, to receive task info buf. * @param bufLen, buffer length * @return false - no task is running; true - succeed. */ virtual bool getRunningTaskInfo(char *buf, int bufLen) = 0; }; } |
- 创建出ITaskLoop接口后,先调用start来启动,再调用postTask来添加一个异步任务
- 添加到同一个TaskLoop对象中的任务顺序在同一个线程中执行
- 任务的优先级默认是0,如果很多任务在排除,新加入的任务希望优先执行,则将nPriority这个参数设置为一个更大的值,任务插入队列的时候,自动根据nPriority排序,nPriority越大,排序越前
demo
- 使用TaskLoop最好结合SOUI的NotifyCenter对象一起使用,在异步任务中需要通知UI层,使用NotifyCenter是最简单有效的
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 |
//演示异步任务。 class CAsyncTaskObj { public: void task1(int a) { SLOG_INFO("task1,a:" << a); } void task2(int a, const std::string & b) { SLOG_INFO("task2,a:" << a<<" b:"<<b.c_str()); } }; int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/) { //必须要调用OleInitialize来初始化运行环境 HRESULT hRes = OleInitialize(NULL); SASSERT(SUCCEEDED(hRes)); //使用imgdecoder-png图片解码模块演示apng动画 SComMgr2 *pComMgr = new SComMgr2(_T("imgdecoder-png")); { //演示异步任务。 CAutoRefPtr<ITaskLoop> pTaskLoop; if (pComMgr->CreateTaskLoop((IObjRef**)&pTaskLoop)) { CAsyncTaskObj obj; pTaskLoop->start("test", ITaskLoop::Low); STaskHelper::post(pTaskLoop, &obj, &CAsyncTaskObj::task1, 100,true); STaskHelper::post(pTaskLoop, &obj, &CAsyncTaskObj::task2, 100,"abc", true); pTaskLoop->stop(); pTaskLoop = NULL; } } //.... return 0; } |
SOUI问题记录
- 窗口圆角
- 本篇
- 屏蔽Edit控件的右键弹窗
1 2 3 4 5 6 7 8 |
BOOL CMainDlg::OnInitDialog(HWND hWnd, LPARAM lParam) { auto edit = FindChildByName2<SOUI::SEdit>(L"path"); if (edit) { edit->GetEventSet()->subscribeEvent(EVT_CTXMENU, Subscriber(&CMainDlg::OnCtxMenu, this)); //edit->GetEventSet()->subscribeEvent(EVT_RE_NOTIFY, Subscriber(&CMainDlg::OnEditNotify, this)); } } |
1 2 3 4 5 6 |
bool CMainDlg::OnCtxMenu(EventArgs* pEvtBase) { EventCtxMenu* pEvt = (EventCtxMenu*)pEvtBase; pEvt->bCancel = true; return true; } |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Windows物理内存虚拟内存03/28
- ♥ Boost 程序库完全开发指南:工具与字符串08/22
- ♥ Zlib记述:一09/17
- ♥ C++编程规范101规则、准则与最佳实践 二01/07
- ♥ 线程和协程10/31
- ♥ Windows 核心编程 _ 进程二06/19