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
原创粉丝点击