转载: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()
,m_bMouseTracking(false)
,m_bMouseWithin(false)
,m_pMousePos(NULL)
{ } CPopUpWnd::~CPopUpWnd()
{
if (m_uTime)
{
KillTimer(this->GetHWND(),ID_VISITPOP_WINDOW);
m_uTime = ;
}
} 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();
m_WndShadow.SetPosition(, ); //修改窗口风格
//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,,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,,&rect,);
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=;
int cy=GetSystemMetrics(SM_CYSCREEN);
int cx=GetSystemMetrics(SM_CXSCREEN);
RECT rect;
SystemParametersInfo(SPI_GETWORKAREA,,&rect,);
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,,NULL);
}
break;
case ID_TIMER_DISPLAY_DELAY:
KillTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY);
Close(IDCLOSE);
break;
}
return ;
} //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 = {};
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 ;
} TCHAR text[MAX_PATH];
wsprintf(text,_T("鼠标移动: %d,%d"),GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); m_pMousePos->SetText(text); return ;
} 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 ;
} LRESULT CPopUpWnd::OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
m_bMouseTracking = false;
m_bMouseWithin = false; SetTimer(m_hWnd,ID_TIMER_DISPLAY_DELAY,,NULL); TCHAR text[MAX_PATH];
wsprintf(text,_T("鼠标离开: %d,%d"),GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
m_pMousePos->SetText(text); return ;
} 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 ;
} LRESULT CPopUpWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = ;
BOOL bHandled = TRUE; switch( uMsg )
{
case WM_NCLBUTTONDBLCLK:
//不做处理
{
return ;
}
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);
}

Duilib 实现右下角弹出像QQ新闻窗口,3秒后自动关闭(一)的更多相关文章

  1. Duilib 实现右下角弹出像QQ新闻窗口,3秒后窗口透明度渐变最后关闭,若在渐变过程中鼠标放到窗口上,窗口恢复最初状态(二)

    效果: 1.定义两个个定时器ID #define ID_TIMER_DISPLAY_DELAY 30 #define ID_TIMER_DISPLAY_CLOSE 40 2.添加一个成员函数和成员变量 ...

  2. 三、临时弹出一个QQ对话窗口

    第一种:需要添加好友才可以访问 <a href="http://wpa.qq.com/msgrd?v=3&uin=317985559&site=qq&menu= ...

  3. C#利用API制作类似QQ一样的右下角弹出窗体

    C#利用API制作类似QQ一样的右下角弹出窗体 (2009-03-21 15:02:49) 转载▼ 标签: 杂谈 分类: .NET using System;using System.Collecti ...

  4. 搜狗输入法弹出搜狐新闻的解决办法(sohunews.exe)

    狗输入法弹出搜狐新闻的解决办法(sohunews.exe) 1.找到搜狗输入法的安装目录(一般是C:\program files\sougou input\版本号\)2.右键点击sohunews.ex ...

  5. 右下角弹出"Windows-延缓写入失败"或者"xxx-损坏文件 请运行Chkdsk工具"

    知识点分析: 任务栏右下角弹出“Windows-延缓写入失败”或者“xxx-损坏文件 请运行Chkdsk工具”. 操作步骤: 方法一:Chkdsk工具 在开始---运行中输入cmd,然后输入chkds ...

  6. Jquery--仿制360右下角弹出窗口

    原文:Jquery--仿制360右下角弹出窗口 先发浏览器效果图,给大家看. 要实现这样的效果,按照思路,第一步,写好CSS布局,将图片放到浏览器右下角的位置 CSS代码很灵活,我写的只是简单的一种而 ...

  7. C# Winform在win10里弹出无焦点的窗口

    原文:C# Winform在win10里弹出无焦点的窗口 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/wangmy1988/article/det ...

  8. 点击文字弹出一个DIV层窗口代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  9. [转]C# 安装时弹出设置服务登录窗口

    本文转自:http://blog.csdn.net/prince_jun/article/details/38435887 安装服务时系统不要弹出设置服务登录窗口:在程序中将serviceProces ...

随机推荐

  1. 《SEO在网页制作中的应用》视频笔记

    学习了慕课网<SEO在网页制作中的应用>视频,今天将里面的知识整理一下. 一.SEO介绍 1.  搜索引擎工作原理 搜索引擎现在主流有百度.谷歌.360,他们都有庞大的搜索引擎数据库,每个 ...

  2. PL/SQL EXCEPTION捕获抛出异常

    EXCEPTION抛出异常 处理除数为零异常 declare varA number; begin varA:=10/0; dbms_output.put_line('IT WILL NOT WORK ...

  3. windows kibana的连接使用

    下载后解压使用,打开config目录下的kibana.yml文件,然后添加:elasticsearch.url: "http://localhost:9200"  表示你要添加的e ...

  4. 【find -exec】查找并复制文件

    find . -name *run_server* -type f -exec cp {} /tmp/ \;

  5. 测试Celery 在Windows中搭建和使用的版本

    官网:http://docs.celeryproject.org/en/latest/faq.html#does-celery-support-windows 描述如下:表示Celery 4.0版本以 ...

  6. 014-Spring Boot web【三】拦截器HandlerInterceptor、异常处理页面,全局异常处理ControllerAdvice

    一.拦截器HandlerInterceptor 1.1.HandlerInterceptor接口说明 preHandle,congtroller执行前,如果返回false请求终端 postHandle ...

  7. JS的二维数组

    今天,记录一下JS的二位数组,并附上例题. 一.二维数组的本质:数组中的元素又是数组. 其实,我们都见过这样的二维数组,只不过没在意罢了,例如: var arr = [[1,2,4,6],[2,4,7 ...

  8. [LeetCode] 476. Number Complement_Easy tag: Bit Manipulation

    这个题目思路就是比如101 的结果是010, 可以从111^101 来得到, 那么我们就需要知道刚好比101多一位的1000, 所以利用 while i <= num : i <<= ...

  9. c#图像灰度化、灰度反转、二值化

    图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*25 ...

  10. itertools模块(收藏)

    Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. count().cycle().repeat() 首先,我们看看itertools提供的几个“无限”迭代器: > ...