转载: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. 43(function pointer 1)

    #include<iostream> using namespace std; typedef int A; typedef void (*PF)(); typedef int (*P_A ...

  2. JZ2440裸板烧写(打补丁)

    制作uImage,需要上网下载内核+patch补丁 1.将内核用ftp发送到 打补丁patch -p1 < ../补丁文件名 打补丁文件(目录) 2.配置 :复制cp  configuratio ...

  3. 数据库bcp导入导出批处理工具

    应公司策划要求,需要一个数据库按表导入导出的工具配合svn来进行差异匹配,方便策划每天对数据库修改的记录工具,我使用bcp命令实现如下批处理工具,中间踩了不少坑,现保存在这边希望可以帮到需要此工具的同 ...

  4. Domino代理运行问题

    当Server出现“operation is disallowed in this session”此命令时为代理权限问题,修改后即可正常运行代理.

  5. Tomcat修改端口和编码配置

    1.打开Tomcat中server.xml文件,找到原本的8080,修改成没被占用的端口: 2.在这个标签里增加 URIEncoding="utf-8",修改请求的编码.

  6. 机器学习理论基础学习19---受限玻尔兹曼机(Restricted Boltzmann Machine)

    一.背景介绍 玻尔兹曼机 = 马尔科夫随机场 + 隐结点 二.RBM的Representation BM存在问题:inference 精确:untractable: 近似:计算量太大 因此为了使计算简 ...

  7. webbench,简单、实用!

    官网:http://home.tiscali.cz/~cz210552/webbench.html   1.下载并安装 # wget http://home.tiscali.cz/~cz210552/ ...

  8. c#获取指定时区的日期

    1.首先将服务器的时间转化为utc时间,然后转换成指定时区的日期 public DateTime GetSpecificZoneNowDate(string zoneName = "Chin ...

  9. VS2010/MFC编程入门之五十二(Ribbon界面开发:创建Ribbon样式的应用程序框架)

    上一节中鸡啄米讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始鸡啄米将为大家带来Ribbon界面开发的有关内容.本文先来说说如何创建Ribbon样式的应用程序框架. Rib ...

  10. zw版【转发·台湾nvp系列Delphi例程】HALCON SetComprise2

    zw版[转发·台湾nvp系列Delphi例程]HALCON SetComprise2 procedure TForm1.Button1Click(Sender: TObject);var op : H ...