转载: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. 数据挖掘领域十大经典算法之—C4.5算法(超详细附代码)

    https://blog.csdn.net/fuqiuai/article/details/79456971 相关文章: 数据挖掘领域十大经典算法之—K-Means算法(超详细附代码)        ...

  2. Linux 程序后台运行

    例子: shadowsocks 程序后台运行: sslocal -c /etc/shadowsocks-libev/config.json > /dev/>& & 参考: ...

  3. LightOj 1265 - Island of Survival(概率)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1265 题目大意:有一个生存游戏,里面t只老虎,d只鹿,还有一个人,每天都要有两个生物碰 ...

  4. mysql 权限管理 针对表的字段 级别 授权 columns_priv表

    针对Mike账号 db1库下面的t1表的 id,name字段授予select权限,age字段授予update权限 授权格式 select(要授权的字段,要授权的字段) 用户括号 括起来  .updat ...

  5. Java编程实现获取本机IP和计算机名的功能

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/wangshuxuncom/article/details/35990847 import java. ...

  6. MSMQ研究

    开发过程记录如下: 1.   本机配置MSMQ ------控制面板-------启动或者关闭Windows功能----默认安装MSMQ即可 注意:本地安装后再VS中才能引用System.Messag ...

  7. 循环结构 while,do while

    while:先判断条件表达式是否成立,成立则执行循环体,不成立则不执行. 格式:while(条件表达式){ 执行语句(控制循环次数): } 例如: int x=1; while(x<3/*条件表 ...

  8. container / pull-left

    <div class="container"> <h2>实例</h2> <div class="pull-left"& ...

  9. Django-made基础

    知识预览 ORM 创建表(建立模型) 添加表记录 查询表记录 修改表记录 删除表记录 回到顶部 ORM 映射关系: 表名 <-------> 类名 字段 <-------> 属 ...

  10. liunx anacoda 安装pyltp

    anacoda 默认的gcc是4.7需要更新 https://anaconda.org/nlesc/gcc 更新之后再安装即可. 报错: /usr/lib64/libstdc++.so.6: vers ...