Dui缓慢飘出窗体的实现
来源:互联网 发布:微商城与淘宝的区别 编辑:程序博客网 时间:2024/06/06 14:28
Dui缓慢飘出窗体的实现
有时候,某个子窗体在隐藏状态下执行某个任务,执行结束用户是看不到的,一下子弹出一个窗体告诉用户任务已完成显得又太唐突,于是,自己写了一个缓慢飘出的窗体提示用户,任务已完成。(1)这个子窗体是使用Dui生成的窗体,并用Dui的控件来维护。(2)这个子窗体是使用单独的线程来维护,因为缓慢飘出这个动作会占用很多时间,放在主窗体所在的主线程里面运行会导致主窗体卡死。(3)析构时执行子窗体的线程需要完全终止,再释放窗体对象的资源,因为线程的强制杀死是异步的,有可能线程没被终止,而窗体对象的资源被释放掉,会造成线程运行时找不到资源,程序异常。
首先是派生自Dui的WindowImplBase类,因为它为子类实现了绝大多数
方法,包括最重要的绘制以及消息处理。
class CUiBaseWindow : public WindowImplBase{public: explicit CUiBaseWindow(LPCTSTR pszXmlPath) :m_strXmlPath(pszXmlPath) {} virtual LPCTSTR GetWindowClassName() const { return _T("FeiYouWindow"); } virtual CDuiString GetSkinFile() { return m_strXmlPath; } virtual CDuiString GetSkinFolder() { return _T(""); }protected: CDuiString m_strXmlPath;};//主窗体class CUiMainWindow : public CUiBaseWindow{ typedef std::vector<std::wstring> vecWstrHintInfo;private: //主窗体中的提示框控件 也就是Dui缓慢飘出窗体控件 CUiHintControl* m_hintWindowControl; CUiHintWindow* m_hintWindow; //C++11 互斥锁 std::mutex m_mutex; vecWstrHintInfo m_vecWstrHintInfo; //boost线程 boost::thread* m_hintInfoThread;public: CUiMainWindow(LPCTSTR pzsXmlPath); ~CUiMainWindow(); CControlUI* CreateControl(LPCTSTR pstrClass); void InitWindow(); void Notify(TNotifyUI& msg); LRESULT HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled); LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); void AddHintInfo(std::wstring); std::wstring ReadHintInfo(); void ThreadShowHintInfo(); void TimerShowHintInfo();};
飘出窗体是使用Dui的控件维护的,下面是我的主窗体的xml,主窗体中的其他控件被我删除了,只留下了自定义控件–缓慢飘出窗体的控件。
<?xml version="1.0" encoding="UTF-8"?><Window size="1000,680" caption="0,0,0,100" showshadow="true" shadowsize="2" shadowcolor="#FF050505" maxinfo="1000,680" > <VerticalLayout > <HorizontalLayout bkcolor="FF2A8AE0" height="100" > </HorizontalLayout> <VerticalLayout height="549" bkcolor="#FFFAFAFA" > </VerticalLayout > <Control height="1" bkcolor="#FFCECECE" /> <HorizontalLayout bkcolor="#FFE6E6E6" width="1000"> <HintWinow pos ="300,2" width="400" height="25" float="true" /> <!--<飘出窗体控件>--> </HorizontalLayout> </VerticalLayout > </Window>
下面是子窗体控件的实现已经子窗体的xml
**class CUiHintWindow :public CUiBaseWindow{private: CLabelUI* m_label;public: CUiHintWindow(LPCTSTR pzsXmlPath); ~CUiHintWindow(); void InitWindow(); void Notify(TNotifyUI& msg); LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); CLabelUI* GetLabelHintInfo();};class CUiHintControl :public CControlUI{public: CUiHintControl(CUiHintWindow*); ~CUiHintControl(); LPCTSTR GetClass() const; void SetInternVisible(bool bVisible = true); void SetPos(RECT rc); void DoEvent(TEventUI& event); CUiHintWindow* GetHintWindow();protected: HWND m_hwnd; CUiHintWindow* m_pHintWindow;};CUiHintWindow::CUiHintWindow(LPCTSTR pzsXmlPath) :CUiBaseWindow(pzsXmlPath){}CUiHintWindow::~CUiHintWindow(){}void CUiHintWindow::InitWindow(){ m_label = static_cast<CLabelUI*>(m_PaintManager.FindControl(_T("labelHintInfo")));}CLabelUI* CUiHintWindow::GetLabelHintInfo(){ return m_label;}void CUiHintWindow::Notify(TNotifyUI& msg){ if (msg.sType == _T("click")) { CDuiString strCtrlName = msg.pSender->GetName(); if (strCtrlName == _T("btnClose")) { ShowWindow(false); } }}LRESULT CUiHintWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){ if (WM_NCLBUTTONDBLCLK != uMsg) { return WindowImplBase::HandleMessage(uMsg, wParam, lParam); } return 0;}CUiHintControl::CUiHintControl(CUiHintWindow* pHintWindow){ m_pHintWindow = NULL; m_pHintWindow = pHintWindow; }CUiHintControl::~CUiHintControl(){}LPCTSTR CUiHintControl::GetClass() const{ return _T("uiHintControl");}//关键点1,使用dui控件的显示与隐藏,控制窗体的显示与隐藏。void CUiHintControl::SetInternVisible(bool bVisible){ //控件无需显示,因为即使显示也会被窗体给覆盖掉 CControlUI::SetInternVisible(false); ::ShowWindow(m_pHintWindow->GetHWND(), bVisible ? SW_SHOW : SW_HIDE);}//关键点2,使用dui控件的位置,也就是xml中获取的位置控制窗体的位置。void CUiHintControl::SetPos(RECT rc){ CControlUI::SetPos(rc); ::SetWindowPos(m_pHintWindow->GetHWND(), NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);}void CUiHintControl::DoEvent(TEventUI& event){ if (event.Type == UIEVENT_SETCURSOR) { ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); return; } CControlUI::DoEvent(event);}CUiHintWindow* CUiHintControl::GetHintWindow(){ return m_pHintWindow;}
//子窗体的xml<?xml version="1.0" encoding="UTF-8"?><Window size="400,25" maxinfo="400,25" > <Font name="微软雅黑" size="15" bold="true" italic="false" /> <Font name="微软雅黑" size="12" bold="true" italic="false" /> <Font name="微软雅黑" size="12" bold="false" italic="false" /> <Font name="微软雅黑" size="14" bold="false" italic="false" /> <Font name="微软雅黑" size="12" bold="true" italic="false" /> <Font name="微软雅黑" size="10" bold="true" italic="false" /> <HorizontalLayout height="25" bkcolor="#FF2A8AE0"> <Label name="labelHintInfo" align="left" font="1" /> <Control /> <Button name="btnClose" width="25" height="20" normalimage="file='download\close.png' source='0,0,25,20'" hotimage="file='download\close.png' source='25,0,50,20'" selectedimage="file='download\close.png' source='50,0,75,20'" /> </HorizontalLayout></Window>
下面是主窗体的缓慢显示窗体的实现代码
CUiMainWindow::CUiMainWindow(LPCTSTR pzsXmlPath) : CUiBaseWindow(pzsXmlPath){ m_hintWindow = NULL;}CUiMainWindow::~CUiMainWindow(){ if (m_hintInfoThread) { /*先完全中断线程,因为中断线程是异步的,所以join等待线程完全被中断,避免m_hintWindow资源被释放,却被没完全中断的线程访问,造成程序异常。 m_hintInfoThread->interrupt(); m_hintInfoThread->join(); delete m_hintInfoThread; m_hintInfoThread = NULL; } if (m_hintWindow) { delete m_hintWindow; m_hintWindow = NULL; }}CControlUI* CUiMainWindow::CreateControl(LPCTSTR pstrClass){ if (_tcscmp(pstrClass, _T("HintWinow")) == 0) { //创建缓慢飘出窗体 m_hintWindow = new CUiHintWindow(_T("HintWindow.xml")); m_hintWindow->Create(m_hWnd, _T("HintWindow"), UI_WNDSTYLE_CHILD&~WS_VISIBLE, 0); //将缓慢飘出窗体与主窗体中的自定义控件相关联 m_hintWindowControl = new CUiHintControl(m_hintWindow); return m_hintWindowControl; } return NULL;}void CUiMainWindow::InitWindow(){//创建线程 m_hintInfoThread = new boost::thread(boost::bind(&CUiFyMainWindow::ThreadShowHintInfo,this));//&CUiFyMainWindow::ThreadShowHintInfo, this); for (int n = 0; n < 20;n++) { //往缓慢飘出窗体加入任务提示语句 AddHintInfo(L"HintInfoHintInfoHintInfo"); }}void CUiMainWindow::Notify(TNotifyUI& msg){ if (msg.sType == _T("click")) { }}LRESULT CUiMainWindow::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled){ if (uMsg == WM_KEYDOWN) { switch (wParam) { case VK_RETURN: break; case VK_ESCAPE: bHandled = true; break; case VK_SPACE: bHandled = true; break; case SC_CLOSE: bHandled = true; break; default: break; } } else if (uMsg == WM_SYSCOMMAND) { switch (wParam) { case SC_CLOSE: { ShowWindow(false); bHandled = true; } } } return false;}LRESULT CUiMainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){ if (WM_NCLBUTTONDBLCLK != uMsg) { return WindowImplBase::HandleMessage(uMsg, wParam, lParam); } return 0;}//因为缓慢窗体飘出和主窗体占用的是不同的线程,需要给//m_vecWstrHintInfo加上互斥量,避免发生读写访问冲突。void CUiMainWindow::AddHintInfo(std::wstring wstrHintInfo){ m_mutex.lock(); m_vecWstrHintInfo.push_back(wstrHintInfo); m_mutex.unlock();}std::wstring CUiMainWindow::ReadHintInfo(){ m_mutex.lock(); std::wstring wstrHintInfo; if (int n =m_vecWstrHintInfo.size()) { wstrHintInfo = *m_vecWstrHintInfo.begin(); m_vecWstrHintInfo.erase(m_vecWstrHintInfo.begin()); } m_mutex.unlock(); return wstrHintInfo;}void CUiMainWindow::ThreadShowHintInfo(){ while (true) { boost::this_thread::sleep(boost::posix_time::seconds(1)); TimerShowHintInfo(); }}void CUiMainWindow::TimerShowHintInfo(){ std::wstring wstrHintInfo = ReadHintInfo(); if (!wstrHintInfo.empty()) { RECT recPos = m_hintWindowControl->GetPos(); m_hintWindow->GetLabelHintInfo()->SetText(wstrHintInfo.c_str()); m_hintWindow->ShowWindow(true); for (int n = 1; n < 10; n++) { LONG lHeight = (recPos.bottom - recPos.top) / n; ::SetWindowPos(m_hintWindow->GetHWND(), NULL, recPos.left, recPos.top + lHeight, recPos.right - recPos.left, recPos.bottom - recPos.top - lHeight, SWP_NOZORDER | SWP_NOACTIVATE); boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } boost::this_thread::sleep(boost::posix_time::milliseconds(100)); ::SetWindowPos(m_hintWindow->GetHWND(), NULL, recPos.left, recPos.top, recPos.right - recPos.left, recPos.bottom - recPos.top, SWP_NOZORDER | SWP_NOACTIVATE); boost::this_thread::sleep(boost::posix_time::seconds(5)); for (int n = 10; n > 0; n--) { LONG lHeight = (recPos.bottom - recPos.top) / n; ::SetWindowPos(m_hintWindow->GetHWND(), NULL, recPos.left, recPos.top + lHeight, recPos.right - recPos.left, recPos.bottom - recPos.top - lHeight, SWP_NOZORDER | SWP_NOACTIVATE); boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } boost::this_thread::sleep(boost::posix_time::milliseconds(100)); m_hintWindow->ShowWindow(false); } }
0 0
- Dui缓慢飘出窗体的实现
- DUI异形窗口实现
- CEF完整嵌入DUI窗体(四) --将浏览器的回调通知应用层
- CEF完整嵌入DUI窗体(五) --JS调用C++注册的函数
- Unity实现缓慢的LookAt (缓慢旋转对着目标)
- 缓慢增加的能量条的实现
- Scroller 实现控件缓慢平移的效果
- vb.net简单实现透明窗体显示出背景透明的png
- dui框架开发系列:基于控件组合或继承实现 可视化界面编辑工具 的优劣
- CEF完整嵌入DUI窗体(一) --Cef3简介
- CEF完整嵌入DUI窗体(三) --基本浏览器功能
- 用js实现层的缓慢关闭与缓慢的打开
- WinForm的技巧,让窗体关闭的时候缓慢地消失
- 异形窗体的实现
- 不规则窗体的实现
- 透明窗体的实现
- 弹出窗体的实现
- 异形窗体的实现
- mysql的交集与差集
- 验证二叉查找树
- VS下生成与配置静态库与动态库(一)
- 设计模式---策略模式
- 不跟进,便淘汰
- Dui缓慢飘出窗体的实现
- 二分查找的两种实现方法
- python 获取linux环境变量
- 以后在CSDN落个户,开始写自己的科研笔记。
- tortoisesvn 版本控制文件图标解读
- Maven实战 -- 目录
- 进程退出
- [leetcode] 35.Search Insert Position
- Android listview里面包含checkbox