关于trackmouseevent的信息
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的路越走越窄。