Dui缓慢飘出窗体的实现

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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值