• Duilib 实现右下角弹出像QQ新闻窗口,3秒后自动关闭(一)


    转载:https://blog.twofei.com/667/

    自绘或子类化控件时,有时需要处理鼠标进入(MouseEnter)/鼠标离开(MouseLeave)/鼠标停留(MouseHover)消息,虽然有定义这两个消息常量(WM_MOUSEHOVER 与 WM_MOUSELEAVE),但默认情况下 Windows 的窗口消息是不会产生这三个消息的。但提供了一个 API 函数_TrackMouseEvent 可以使用,这个函数可以使 Windows 产生 鼠标停留(WM_MOUSEHOVER)与 鼠标离开(WM_MOUSELEAVE)消息,至于鼠标进入消息(Windows 没有定义 WM_MOUSEENTER 宏),直接手动在第一次鼠标移动的时候模拟产生就行了。不过不爽的是 鼠标离开消息 Windows 没有传递离开时的坐标过来,所以这个也得手动模拟:每次鼠标移动的时候记录下坐标,在收到鼠标离开消息时,采用此值即可。下面的代码没有作此处理,如有需要可手动加上。

    效果:

    .h文件

    #ifndef _POPUPWND_H_
    #define _POPUPWND_H_
    
    #include "WndShadow.h"
    
    #define WIN_VISITWIDTH    280
    #define WIN_VISITHEIGHT    186
    
    #define ID_VISITPOP_WINDOW 20
    #define ID_TIMER_DISPLAY_DELAY 30
    #define ID_TIMER_CLOSE_WINDOW 40
    
    class CPopUpWnd :public WindowImplBase
    {
    public:
        CPopUpWnd();
    
        ~CPopUpWnd();
    
    public:
        virtual LPCTSTR GetWindowClassName() const;
    
        virtual void OnFinalMessage(HWND hWnd);
    
        virtual CDuiString GetSkinFile();
    
        virtual CDuiString GetSkinFolder();
    
        virtual UILIB_RESOURCETYPE GetResourceType() const;
    
        virtual CControlUI* CreateControl(LPCTSTR pstrClassName);
    
        virtual LRESULT ResponseDefaultKeyEvent(WPARAM wParam);
    
        virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 
    
        virtual void Notify(TNotifyUI& msg);
    
        virtual void OnClick(TNotifyUI& msg);
    
        virtual void InitWindow();
    
        void OnPrepare();
    
    public:
    
        void InitControl();
    
        void StartTrack();
    
        void MoveSelfWindow();
    
        LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam,BOOL& bHandled);
    
        LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
        LRESULT OnMouseHover(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
        LRESULT OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
        LRESULT OnMouseEnter(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
    
    
    public:
        CWndShadow m_WndShadow;
    
        CLabelUI* m_pMousePos;
    
        UINT m_uTime;//移动窗口时器
    
    protected:
        bool m_bMouseTracking;   // 是否正在跟踪鼠标
        bool m_bMouseWithin;     // 鼠标是否在窗口内
    };
    
    #endif//_POPUPWND_H

    .cpp文件

    #include "....stdafx.h"
    #include "PopUpWnd.h"
    #pragma comment(lib, "comctl32.lib")
    
    CPopUpWnd::CPopUpWnd()
        :m_uTime(0)
        ,m_bMouseTracking(false)
        ,m_bMouseWithin(false)
        ,m_pMousePos(NULL)
    {
    
    }
    
    CPopUpWnd::~CPopUpWnd()
    {
        if (m_uTime)
        {
            KillTimer(this->GetHWND(),ID_VISITPOP_WINDOW);
            m_uTime = 0;
        }
    }
    
    LPCTSTR CPopUpWnd::GetWindowClassName() const
    {
        return _T("PopUpWnd");
    }
    
    void CPopUpWnd::OnFinalMessage(HWND hWnd)
    {
        CWindowWnd::OnFinalMessage(hWnd);
    }
    
    CDuiString CPopUpWnd::GetSkinFile()
    {
        return _T("xml//PopUpDlg.xml");
    }
    
    CDuiString CPopUpWnd::GetSkinFolder()
    {
        return _T("");
    }
    
    UILIB_RESOURCETYPE CPopUpWnd::GetResourceType() const
    {
        return UILIB_FILE;
    }
    
    LRESULT CPopUpWnd::ResponseDefaultKeyEvent(WPARAM wParam)
    {
        if (wParam == VK_RETURN)
        {
            return FALSE;
        }
        else if (wParam == VK_ESCAPE)
        {
            Close();
            return TRUE;
        }
        return FALSE;
    }
    
    CControlUI* CPopUpWnd::CreateControl(LPCTSTR pstrClassName)
    {
        
    
        return NULL;
    }
    
    void CPopUpWnd::InitWindow()
    {
        //窗体增加阴影
        CWndShadow::Initialize(m_PaintManager.GetInstance());
        m_WndShadow.Create(m_hWnd , true);
        m_WndShadow.SetSize(2);
        m_WndShadow.SetPosition(1, 1);
    
        //修改窗口风格
        //SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME );
    
        //加入WS_EX_LAYERED扩展属性
        LONG styleValue = ::GetWindowLong(m_hWnd, GWL_EXSTYLE); 
    
        styleValue &= ~(WS_EX_APPWINDOW);//当窗口可见时将一个顶层窗口放置在任务栏上
        styleValue |= WS_EX_TOOLWINDOW; //工具条窗口样式
    
        SetWindowLong(m_hWnd,GWL_EXSTYLE,styleValue);
    
        InitControl();
    
        //右下角慢慢弹出
        //m_uTime = SetTimer(m_hWnd,ID_VISITPOP_WINDOW,20,NULL);
    
       //在此调用MoveSelfWindow()方法  窗口不会显示在右下角,因为InitWindow在WM_CREATE 消息响应函数里调用,窗口还没创建出来
    }
    
    void CPopUpWnd::InitControl()
    {
        m_pMousePos = static_cast<CLabelUI*>(m_PaintManager.FindControl(TEXT("mouse")));
    }
    
    void CPopUpWnd::OnPrepare()
    {
        //直接显示在右下角
        MoveSelfWindow();
    
        //3秒后窗口自动关闭
        SetTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY,3000,NULL);
    }
    
    void CPopUpWnd::Notify(TNotifyUI& msg)
    {
        if( msg.sType == _T("windowinit") ) OnPrepare();
    
        if ( msg.sType == _T("click") )
        {
            
        }
        WindowImplBase::Notify(msg);
    }
    
    void CPopUpWnd::OnClick(TNotifyUI& msg)
    {
        __super::OnClick(msg);
    }
    
    void CPopUpWnd::MoveSelfWindow()
    {
        RECT rect;
        SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
        int y=rect.bottom-rect.top;
        int x=rect.right-rect.left;
        x=x-WIN_VISITWIDTH;
        y=y-WIN_VISITHEIGHT;
    
        MoveWindow(m_hWnd,x,y,WIN_VISITWIDTH,WIN_VISITHEIGHT,TRUE);
    }
    
    LRESULT CPopUpWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam,BOOL& bHandled)
    {
        static int nHeight=0;
        int cy=GetSystemMetrics(SM_CYSCREEN);
        int cx=GetSystemMetrics(SM_CXSCREEN);
        RECT rect;
        SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
        int y=rect.bottom-rect.top;
        int x=rect.right-rect.left;
        x=x-WIN_VISITWIDTH;
    
        switch(wParam)
        {//多个定时器
        case ID_VISITPOP_WINDOW:
            if(nHeight<=WIN_VISITHEIGHT)
            {
                ++nHeight;        
                MoveWindow(m_hWnd,x,y-WIN_VISITHEIGHT,WIN_VISITWIDTH,WIN_VISITHEIGHT,TRUE);
            }
            else
            {
                //nHeight = 0;
                KillTimer(m_hWnd,ID_VISITPOP_WINDOW);
    
                SetTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY,3000,NULL);
            }
            break;
        case ID_TIMER_DISPLAY_DELAY:
            KillTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY);
            Close(IDCLOSE);
            break;
        }
        return 0;
    }
    
    
    //LRESULT CPopUpWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    //{
    //    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
    //    //::ScreenToClient(m_hWnd,&pt);//转换成屏幕坐标
    //    //POINT pt1 ;/*= { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };*/
    //    //GetCursorPos(&pt1);
    //    RECT rect;
    //    ::GetWindowRect (m_hWnd,&rect);
    //    //::ClientToScreen(m_hWnd,&pt);//转换成屏幕坐标
    //    if (PtInRect(&rect,pt))//判断point是否在rect内部
    //    {
    //        KillTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY);
    //    }
    //
    //    return 0;
    //}
    
    
    void CPopUpWnd::StartTrack()
    {
        TRACKMOUSEEVENT tme = {0};
        tme.cbSize = sizeof(tme);
        tme.hwndTrack = m_hWnd;
        tme.dwFlags = TME_HOVER | TME_LEAVE;
        tme.dwHoverTime = HOVER_DEFAULT;
        _TrackMouseEvent(&tme);
    }
    
    LRESULT CPopUpWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        // 如果鼠标不在客户区内,就产生一个鼠标进入事件
        if(!m_bMouseWithin) {
            OnMouseEnter(uMsg /* WM_MOUSEMOVE */, wParam, lParam, bHandled);
        }
    
        // 开始跟踪鼠标停留/离开事件
        if(!m_bMouseTracking) {
            StartTrack();
            m_bMouseTracking = true;
            return 0;
        }
        
    
        TCHAR text[MAX_PATH];
        wsprintf(text,_T("鼠标移动: %d,%d"),GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
    
        m_pMousePos->SetText(text);
    
    
        return 0;
    }
    
    
    
    LRESULT CPopUpWnd::OnMouseHover(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
         m_bMouseTracking = false;
    
         TCHAR text[MAX_PATH];
         wsprintf(text,_T("鼠标停留: %d,%d"),GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
         m_pMousePos->SetText(text);
    
    
         return 0;
    }
    
    LRESULT CPopUpWnd::OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        m_bMouseTracking = false;
        m_bMouseWithin = false;
    
        SetTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY,3000,NULL);
    
    
         TCHAR text[MAX_PATH];
         wsprintf(text,_T("鼠标离开: %d,%d"),GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
         m_pMousePos->SetText(text);
    
        return 0;
    }
    
    LRESULT CPopUpWnd::OnMouseEnter(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        m_bMouseWithin = true;
    
        
        KillTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY);
    
        TCHAR text[MAX_PATH];
        wsprintf(text,_T("鼠标进入:%d,%d"),GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
        m_pMousePos->SetText(text);
        return 0;
    }
    
    
    LRESULT CPopUpWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        LRESULT lRes = 0;
        BOOL bHandled = TRUE;
    
        switch( uMsg ) 
        {
        case WM_NCLBUTTONDBLCLK:
            //不做处理
            {
                return 0;
            }
            break;
        case WM_TIMER:
            lRes = OnTimer(uMsg,wParam,lParam,bHandled);
            break;
        case WM_MOUSELEAVE:
            lRes = OnMouseLeave(uMsg,wParam,lParam,bHandled);
            break;
        default:
            bHandled = FALSE;
        }
        return WindowImplBase::HandleMessage(uMsg,wParam,lParam);
    }

  • 相关阅读:
    解决centos7的root账户下无法通过code命令启动vscode
    centos7安装epel
    centos7用过yum安装vscode
    yum install gcc报错Error: Package: glibc-2.17-260.el7_6.6.i686 (updates) Requires: glibc-common = 2.17
    centos7通过yum从vim7升级到vim8
    解决VM虚拟机安装centos7无法联网
    centos7设置开机默认使用root账户登陆
    centos7使用sudo命令提示sudo command not found
    不同编译器下C++基本数据类型的字节长度
    C++函数模板
  • 原文地址:https://www.cnblogs.com/chechen/p/7347236.html
Copyright © 2020-2023  润新知