关于trackmouseevent的信息

http://www.itjxue.com  2023-01-14 13:36  来源:未知  点击次数: 

C++ 如何判断鼠标有没有在窗口上? 纯API 不是MFC

示例一:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

TRACKMOUSEEVENT tme; //定义触发鼠标事件结构

tme.cbSize = sizeof (TRACKMOUSEEVENT); //结构大小

tme.dwFlags = TME_HOVER | TME_LEAVE ; //鼠标停留/鼠标离开

tme.dwHoverTime = 300; //延时300毫秒

tme.hwndTrack = hWnd ; //窗体句柄

switch (message) {

case WM_CREATE: //创建窗口消息

edt = CreateWindow(L"edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,115, 23, 120, 24, hWnd, (HMENU)IDB_EDIT, hInst, NULL); //edit编辑文本框

break;

case WM_MOUSEMOVE :

//鼠标移动消息

TrackMouseEvent(tme); //调用TrackMouseEvent函数,系统根据tme触发WM_MOUSEHOVER或WM_MOUSELEAVE消息

break ;

case WM_MOUSEHOVER: //鼠标停留消息(这不会自动触发,需要TrackMouseEvent函数来触发)

SetWindowText (edt, _T("鼠标在窗体上面"));

break ;

case WM_MOUSELEAVE : //鼠标离开消息(这不会自动触发,需要TrackMouseEvent函数来触发)

SetWindowText (edt, _T("鼠标已离开窗体"));

break ;

case WM_COMMAND :

break ;

default:

return DefWindowProc(hWnd,

message, wParam, lParam); ;

}

return 0;

}

示例二:

示例一的WM_MOUSEHOVER、WM_MOUSELEAVE貌似只能对窗体有效果,对窗体的子控件就没反应了;因此示例二演示如何实现对窗体上的控件也有效果

wchar_t* MouseHoL(HWND hWnd); //向前声明一个鼠标停留与离开函数

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){

TRACKMOUSEEVENT tme; //定义触发鼠标事件结构

tme.cbSize = sizeof (TRACKMOUSEEVENT); //结构大小

tme.dwFlags = TME_HOVER | TME_LEAVE ; //鼠标停留/鼠标离开

tme.dwHoverTime = 100; //延时100毫秒

tme.hwndTrack = hWnd ; //窗体句柄

switch (message) {

case WM_CREATE: //创建窗口消息

cbtn = CreateWindow(L"button", L"确定", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_GROUP, 250, 20, 75, 30, hWnd, (HMENU)IDB_BTN,(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); //button按键

edt = CreateWindow(L"edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,115, 23, 120, 24, hWnd, (HMENU)IDB_EDIT, hInst, NULL); //edit编辑文本框

break;

case WM_MOUSEMOVE :

//鼠标移动消息

TrackMouseEvent(tme); //调用TrackMouseEvent函数,系统根据tme触发WM_MOUSEHOVER或WM_MOUSELEAVE消息

break ;

case WM_MOUSEHOVER: //鼠标停留消息(这不会自动触发,需要TrackMouseEvent函数来触发)

SetWindowText (edt, MouseHoL(cbtn)); //调用MouseHoL函数,判断鼠标是否停留在cbtn窗口

break ;

case WM_MOUSELEAVE : //鼠标离开消息(这不会自动触发,需要TrackMouseEvent函数来触发)

SetWindowText (edt, MouseHoL(cbtn)); //调用MouseHoL函数,判断鼠标是否离开cbtn窗口

break ;

case WM_COMMAND :

break ;

default:

return DefWindowProc(hWnd, message, wParam, lParam); ;

}

return 0;

}

//定义鼠标停留或离开函数

wchar_t* MouseHoL(HWND hWnd) {

RECT cRC, winRC; //控件屏幕位置RECT,控件窗口大小RECT

POINT Mxy,Cxy; //鼠标坐标结构,控件坐标结构

GetCursorPos(Mxy); //获取鼠标在屏幕的坐标

GetWindowRect(hWnd, cRC);

//获取控件位于屏幕的位置及大小

GetClientRect(hWnd, winRC); //获取控件的宽高

cRC.right = cRC.left + winRC.right; //控件右下角的x坐标,也就是宽

cRC.bottom = cRC.top + winRC.bottom; //控件右下角的y坐标,也就是高

if (Mxy.x cRC.left Mxy.x cRC.right Mxy.y cRC.top Mxy.y cRC.bottom) { //判断鼠标坐标是否在窗口内

return L"鼠标已进入控件";

}else {

return L"鼠标经离开控件";

}

}

VC 怎样监测其他窗口的消息

WM_MOUSELEAVE 是鼠标离开窗口时发出的消息,但是这个消息与普通的鼠标消息不同,要收到WM_MOUSELEAVE消息必须先调用TrackMouseEvent,并且每调用一次TrackMouseEvent 窗口只能收到一次WM_MOUSELEAVE,也就说如果要获得WM_MOUSELEAVE消息的话,当鼠标重新进入窗口时必须调用一次TrackMouseEvent。 static BOOL bTrackLeave=FALSE; void CMyWnd::OnMouseMove(UINT nFlags, CPoint point) { if (!bTrackLeave) { // 鼠标第一次移入窗口时, 请求一个WM_MOUSELEAVE 消息 TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.hwndTrack = m_hWnd; tme.dwFlags = TME_LEAVE; _TrackMouseEvent(tme); bTrackLeave = TRUE; // 在这里添加处理鼠标进入的代码 : ……………………………… } } 手工添加消息映射和消息处理函数 BEGIN_MESSAGE_MAP(CMyWnd, CWnd) //{{AFX_MSG_MAP(CMyWnd) ……………………… //}}AFX_MSG_MAP ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave) END_MESSAGE_MAP() LPARAM CMyWnd::OnMouseLeave(WPARAM wp, LPARAM lp) { bTrackLeave = FALSE; // 在这里添加处理鼠标离开的代码 :

高分急求:VC中鼠标移到按钮上后,更改按钮图片的实现代码

楼主无法解决该问题,从解决问题的能力上有两点不足:

1)不会使用 MSDN,一定要多参考MSDN。

2)楼主对WINDOWS编程不熟悉,MFC不是用来学习的,MFC是让职业程序员在做开发时,

对于原来大量需要调用的API调用和一些基本功能模块进行了包装,简化程序员的编码,提高工作效率。学习的话,只能从最底层的API调用开始学习。这个是VC程序员的悲哀,VB,C#不需要关注太多WINDOWS编程的底层细节,VC.NET同样也不需要关注太多。只有用MFC的程序员,必须了解所有底层的机制。

这里,我自己写了一个针对楼主帖子的代码示例,是WIN32的,没有使用MFC,其中用编号给出的注释,是要实现位图加文本按钮的必须步骤,否则程序无法获得需要的效果。在最后,我指出楼主MFC中的一个问题,可能是这个原因,当然,任何其它情况都会阻碍程序的实现。楼主没有代码,我不知道楼主是否还有其它问题。

#include windows.h

#include tchar.h

#include windowsx.h

class IconButton {

public:

IconButton(HWND hParent, LPRECT prcPos) {

// 按钮在不同状态下显示的文本

m_pszHover = _T("hover");

m_pszLeave = _T("leave");

m_pszPressed = _T("pressed");

// 按钮在不同状态下显示的图标

m_hIconHover = LoadIcon(NULL, IDI_INFORMATION);

m_hIconLeave = LoadIcon(NULL, IDI_QUESTION);

m_hIconPressed = LoadIcon(NULL, IDI_WARNING);

// 2)按钮的样式不能指定 BS_ICON 或 BS_BITMAP 或两者。

m_hButton = CreateWindowEx(WS_EX_LTRREADING|WS_EX_RIGHTSCROLLBAR|WS_EX_NOPARENTNOTIFY,

_T("Button"), m_pszLeave,

WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP|BS_TEXT,

prcPos-left, prcPos-top,

prcPos-right - prcPos-left, prcPos-bottom - prcPos-top,

hParent,

NULL,

GetModuleHandle(NULL),

NULL);

// 按钮原来的消息处理函数

m_pfnOldProc = (WNDPROC)SetWindowLongPtr(m_hButton, GWLP_WNDPROC, (LONG_PTR)BtnProc);

SetWindowLongPtr(m_hButton, GWLP_USERDATA, (LONG_PTR)this);

m_bHover = FALSE;

SendMessage(m_hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)m_hIconLeave);

}

private:

// 一些API调用时会重复使用的参数,将它们保存为类成员

HWND m_hButton;

HICON m_hIconHover;

HICON m_hIconLeave;

HICON m_hIconPressed;

LPCTSTR m_pszHover;

LPCTSTR m_pszLeave;

LPCTSTR m_pszPressed;

WNDPROC m_pfnOldProc;

BOOL m_bHover;

static LRESULT BtnProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

LRESULT lRet;

IconButton *pib = (IconButton*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

switch (uMsg) {

case WM_MOUSEMOVE:

if (!pib-m_bHover) {

/*

WM_MOUSELEAVE 是当鼠标离开窗口,窗口会收到的消息,

该消息并不是自动由 Windows 操作系统发送到线程消息队列中的,

而是需要程序员在代码中调用 TrackMouseEvent ,

只有这样,操作系统才会把 WM_MOUSELEAVE 消息发送到线程消息队列中。

*/

TRACKMOUSEEVENT tme = { sizeof(tme) };

tme.dwFlags = TME_LEAVE;

tme.hwndTrack = pib-m_hButton;

TrackMouseEvent(tme);

pib-m_bHover = TRUE;

pib-SetButton(pib-m_pszHover, pib-m_hIconHover);

}

lRet = 0;

break;

case WM_MOUSELEAVE:

pib-m_bHover = FALSE;

pib-SetButton(pib-m_pszLeave, pib-m_hIconLeave);

lRet = 0;

break;

case WM_LBUTTONDOWN:

pib-SetButton(pib-m_pszPressed, pib-m_hIconPressed);

lRet = 0;

break;

case WM_LBUTTONUP:

pib-SetButton(pib-m_pszHover, pib-m_hIconHover);

lRet = 0;

break;

default:

lRet = (*pib-m_pfnOldProc)(hWnd, uMsg, wParam, lParam);

break;

}

return lRet;

}

void SetButton(LPCTSTR pszText, HICON hIcon) {

Button_SetText(m_hButton, pszText);

/*

3)设置按钮图标并启用文本,第二个参数是 BM_SETIMAGE,

第三个参数是 IMAGE_ICON ,如果是位图,第三个参数是 IMAGE_BITMAP ,

第四个参数是图标或位图句柄。

*/

SendMessage(m_hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);

}

};

LRESULT CALLBACK NormalProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

LRESULT lRet;

switch (uMsg) {

case WM_CLOSE:

PostQuitMessage(0);

lRet = 0;

break;

default:

lRet = DefWindowProc(hWnd, uMsg, wParam, lParam);

}

return lRet;

}

HWND CreateNormalWindow() {

WNDCLASS wc = { 0 };

wc.hInstance = GetModuleHandle(NULL);

wc.lpfnWndProc = NormalProc;

wc.lpszClassName = _T("ButtonTestWndClass");

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

RegisterClass(wc);

return CreateWindow(_T("ButtonTestWndClass"), _T("Button Test Window"),

WS_OVERLAPPEDWINDOW | WS_VISIBLE,

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0,

NULL,

NULL,

GetModuleHandle(NULL),

NULL);

}

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) {

/*

1)启用可视化样式,在WIN32编程中,

向导不会为我们启用可视化样式给出向导创建的代码。

在MFC中,启用可视化样式是MFC工程创建向导默认给出的。

在此也就没有必要给出我自己写的 zInitVisualStyle 的代码了。

*/

zInitVisualStyle(ICC_WIN95_CLASSES);

HWND hWnd = CreateNormalWindow();

RECT rc = { 0, 0, 200, 40 };

IconButton ib(hWnd, rc);// 有关图标文本按钮的类

UpdateWindow(hWnd);

BOOL bQuit = FALSE;

MSG msg;

while (!bQuit) {

if (PeekMessage(msg, NULL, 0, 0, PM_REMOVE)) {

if (msg.message == WM_QUIT) {

bQuit = TRUE;

continue;

}

TranslateMessage(msg);

DispatchMessage(msg);

}

}

return msg.wParam;

}

楼主的问题第一个就是“按钮的bitmap属性已经改为TRUE”,这个在我的代码中的第二个注释中已经说明。“按钮的bitmap属性已经改为TRUE”意味着设置了按钮的 BS_BITMAP 样式。其次,根据楼主已有的信息,我不知道为何要知道坐标,计算坐标,它们用来干吗的?

真正做职业软件的,涉及到换肤的话,都是用底层WIN32做自己的包装类,就如以上我给出的IconButton,没人会去用MFC作换肤。还是那句话那时如日中天的MFC是做快速开发只用的,兼顾软件项目开发效率和程序运行效率,这两者。但,就我的理解,目前的MFC处境非常尴尬,论程序运行效率,MFC肯定比不上纯粹的WIN32:

1、MFC占更多的内存

2、执行更多的代码

3、生成的文件尺寸更大,还需要依赖MFC库,不利于软件部署。

从快速开发的角度而言,肯定是MFC比WIN32来得效率高,WIN32是要写死人的,而且调试也远比MFC来得困难,但是与此同时,使用C#或VB进行.NET开发,MFC根本比不上.NET的开发效率,若论做界面的话,新崛起的WPF可以做出非常炫的界面(甚至用“让人吃惊”来形容)。

因此,MFC现在是一种高不成(不如C#、VB)低不就(WIN32)的尴尬局面。MFC的路越走越窄。

(责任编辑:IT教学网)

更多