关于WM_MOUSEHOVER和WM_MOUSELEAVE消息的用法以及按钮的变色问题!

本文用代码的方式详细说明了Windows编程中WM_MOUSEHOVER和WM_MOUSELEAVE消息的用法,以及按钮的变色问题,实现的功能也很多,主要是示例了这两个消息的用法和具体实现按钮的变色。

代码的注释还算详细,就不多做说明了!看代码!

另外做一下功能的说明:

1: 在客户区点鼠标右键,弹出菜单可以关闭窗口!

2: 客户区中的那个巨大的按钮,鼠标移入和移出时可以变色和改变文字,单击鼠标左键可以更改客户区窗口的背景颜色!

3:在最上面的按钮上按住鼠标左键可以移动窗口!(按钮)

建一个空的win32工程,复制下面的代码就可以运行了,vs2012调试通过!!!

编译使用cpp文件,c++方式编译。



//#undef UNICODE  // 加上这行代码,可以编译非UNICODE版本

//如果达不到按钮变色的效果,加上下面这行代码
//#define _WIN32_WINNT  0x0400 

//如有问题,请批评指正。
//本程序在vs2012调试通过
#include<Windows.h>



#define ID_MINIMIZE   0
#define ID_MAXIMIZE   1
#define ID_CLOSE      2
#define ID_CAPTION    3
#define ID_CLICK      4


int indicator_color = 0; 

COLORREF m_color[6] = {RGB(255,0,0),RGB(0,255,0),RGB(0,0,255),
                       RGB(0,0,0),RGB(100,100,100),RGB(0,125,0)};
HBRUSH   m_hBrush[6];  //画刷句柄
HWND     btn_hwnd[5];  //按钮句柄
HINSTANCE m_hInstance;  //应用程序实例句柄


BOOL click_entry   = FALSE;  //FALSE 表示鼠标没有移入button上
BOOL min_entry     = FALSE;
BOOL max_entry     = FALSE;
BOOL close_entry   = FALSE;

// 主窗口过程
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);  
//ID号为ID_CAPTION的button窗口过程
LRESULT CALLBACK btn_CaptionProc(HWND,UINT,WPARAM,LPARAM);  
//ID号为ID_MINIMIZE的button窗口过程
LRESULT CALLBACK btn_MinProc(HWND,UINT,WPARAM,LPARAM); 
//ID号为ID_MAXIMIZE的button窗口过程
LRESULT CALLBACK btn_MaxProc(HWND,UINT,WPARAM,LPARAM); 
//ID号为ID_CLOSE的button窗口过程
LRESULT CALLBACK btn_CloseProc(HWND,UINT,WPARAM,LPARAM); 
//ID号为ID_CLICK的button窗口过程
LRESULT CALLBACK btn_ClickProc(HWND,UINT,WPARAM,LPARAM); 



//以下变量为更改button的窗口过程之用
WNDPROC old_btn_CaptionProc;
WNDPROC old_btn_MinProc;
WNDPROC old_btn_MaxProc;
WNDPROC old_btn_CloseProc;
WNDPROC old_btn_ClickProc;



//一个内部使用的函数,主要用于在ID为ID_CAPTION的按钮上输出文字
void MySetWindowText(const TCHAR *str)
{
	HDC hdc = GetDC(btn_hwnd[ID_CAPTION]);		
	SetBkColor(hdc,m_color[5]);
	SetTextColor(hdc,RGB(255,255,255));  //白色
	RECT rect;
	GetClientRect(btn_hwnd[ID_CAPTION],&rect);
	InvalidateRect(btn_hwnd[ID_CAPTION],NULL,TRUE);
	UpdateWindow(btn_hwnd[ID_CAPTION]);
	TextOut(hdc,0,rect.bottom / 3 * 2,str,lstrlen(str));
	ReleaseDC(btn_hwnd[ID_CAPTION],hdc);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
	//初始化画刷
	for(int i = 0; i < 6; ++i)
		m_hBrush[i] = CreateSolidBrush(m_color[i]);

	m_hInstance = hInstance;

	WNDCLASS wndclass;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hbrBackground = m_hBrush[3]; // 黑色
	wndclass.hCursor = LoadCursor(NULL,IDC_CROSS);
	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
	wndclass.hInstance = hInstance;
	wndclass.lpfnWndProc = WndProc;
	wndclass.lpszClassName = TEXT("sunkang");
	wndclass.lpszMenuName = NULL;
	wndclass.style = CS_HREDRAW | CS_HREDRAW;
	RegisterClass(&wndclass);

	HWND hwnd = CreateWindow(TEXT("sunkang"),TEXT(""),WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,
		hInstance,NULL);

	ShowWindow(hwnd,nShowCmd);
	UpdateWindow(hwnd);

	MSG msg;

	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	//释放资源
	for(int i = 0; i < 6; ++i)
		DeleteObject(m_hBrush[i]);
}


LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	//static HINSTANCE hInstance;
	static int cxClient,cyClient;
	static int click_btn_width,click_btn_height;
	switch(message)
	{
	case WM_CREATE:
		{
			//m_hInstance = (LPCREATESTRUCT(lParam))->hInstance;
			btn_hwnd[ID_CAPTION] = CreateWindow(TEXT("button"),TEXT(""),WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
				0,0,0,0,hwnd,HMENU(ID_CAPTION),m_hInstance,NULL);
			btn_hwnd[ID_CLICK] = CreateWindow(TEXT("button"),TEXT(""),WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
				0,0,0,0,hwnd,HMENU(ID_CLICK),m_hInstance,NULL);

			old_btn_CaptionProc = (WNDPROC)SetWindowLong(btn_hwnd[ID_CAPTION],
				                   GWL_WNDPROC,(LONG)btn_CaptionProc);
			old_btn_ClickProc = (WNDPROC)SetWindowLong(btn_hwnd[ID_CLICK],
				                   GWL_WNDPROC,LONG(btn_ClickProc));
			//以下三个按钮的父窗口为btn_hwnd[ID_CAPTION]
			btn_hwnd[ID_MINIMIZE] = CreateWindow(TEXT("button"),TEXT(""),WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
				0,0,0,0,btn_hwnd[ID_CAPTION],HMENU(ID_MINIMIZE),m_hInstance,NULL);
			btn_hwnd[ID_MAXIMIZE] = CreateWindow(TEXT("button"),TEXT(""),WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
				0,0,0,0,btn_hwnd[ID_CAPTION],HMENU(ID_MAXIMIZE),m_hInstance,NULL);
			btn_hwnd[ID_CLOSE] = CreateWindow(TEXT("button"),TEXT(""),WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
				0,0,0,0,btn_hwnd[ID_CAPTION],HMENU(ID_CLOSE),m_hInstance,NULL);
			//分别更改button的窗口过程

			
			old_btn_MinProc = (WNDPROC)SetWindowLong(btn_hwnd[ID_MINIMIZE],
				               GWL_WNDPROC,(LONG)(btn_MinProc));
			old_btn_MaxProc = (WNDPROC)SetWindowLong(btn_hwnd[ID_MAXIMIZE],
				               GWL_WNDPROC,(LONG)(btn_MaxProc));
			old_btn_CloseProc = (WNDPROC)SetWindowLong(btn_hwnd[ID_CLOSE],
				               GWL_WNDPROC,(LONG)(btn_CloseProc));
			
			break;
		}
	case WM_SIZE:
		{
			cxClient = LOWORD(lParam);
			cyClient = HIWORD(lParam);
			// 模拟标题栏的button
			MoveWindow(btn_hwnd[ID_CAPTION],0,0,cxClient,cyClient / 5,TRUE);
			click_btn_width = cxClient / 2;
			click_btn_height = cyClient / 5 * 2;
			//客户区中的button
			MoveWindow(btn_hwnd[ID_CLICK],cxClient / 4,cyClient / 5 * 2,click_btn_width,click_btn_height,TRUE);

			break;
		}
	case WM_CTLCOLORBTN:
		{
			if(HWND(lParam) == btn_hwnd[ID_CAPTION])
				return (LRESULT)m_hBrush[5];
			else
			{
				HDC hdc = HDC(wParam);
				LOGFONT lf;
				lf.lfCharSet = ANSI_CHARSET;
				lstrcpy(lf.lfFaceName,TEXT("宋体"));
				//lf.lfWidth = click_btn_width / 5;
				lf.lfHeight = click_btn_height;
				lf.lfItalic = FALSE;
				lf.lfClipPrecision = 0;
				lf.lfEscapement = 0;
				lf.lfOrientation = 0;
				lf.lfOutPrecision = 0;
				lf.lfPitchAndFamily = 0;
				lf.lfQuality = 0;
				lf.lfStrikeOut = FALSE;
				lf.lfUnderline = FALSE;
				lf.lfWeight = 400;
				if(click_entry == FALSE)
				{
					TCHAR name[] = TEXT("HELLO");
					lf.lfWidth = click_btn_width / lstrlen(name);
					HFONT hFont = CreateFontIndirect(&lf);
					HFONT old_font = (HFONT)SelectObject(hdc,hFont);
					SetBkColor(hdc,m_color[0]);
					SetTextColor(hdc,m_color[2]);
					TextOut(hdc,0,0,name,lstrlen(name));
					SelectObject(hdc,old_font);
					return (LRESULT)m_hBrush[0];
				}
				else
				{
					TCHAR name[] = TEXT("WORLD");
					lf.lfWidth = click_btn_width / lstrlen(name);
					HFONT hFont = CreateFontIndirect(&lf);
					HFONT old_font = (HFONT)SelectObject(hdc,hFont);
					SetBkColor(hdc,m_color[5]);
					SetTextColor(hdc,m_color[1]);
					TextOut(hdc,0,0,name,lstrlen(name));
					SelectObject(hdc,old_font);
					return (LRESULT)m_hBrush[5];
				}
			}
			break;
		}
	case WM_RBUTTONDOWN:
		{
			HMENU hMenu = CreatePopupMenu();
			AppendMenu(hMenu,MF_STRING,ID_CLOSE,TEXT("退出!"));
			POINT pt = {LOWORD(lParam),HIWORD(lParam)};
			ClientToScreen(hwnd,&pt);
			TrackPopupMenu(hMenu,TPM_LEFTALIGN | TPM_TOPALIGN,
				pt.x,pt.y,0,hwnd,NULL);
			DeleteObject(hMenu);
			break;
		}
	case WM_MOUSEMOVE:
		{
			TCHAR buf[] = TEXT("右键有惊喜!!!");
			MySetWindowText(buf);
			break;
		}
	case WM_COMMAND:
		{
			switch(LOWORD(wParam))
			{
	            case ID_CLOSE:
					 {
						 SendMessage(hwnd,WM_CLOSE,0,0);
						 break;
					 }
				case ID_CLICK:
					{
						indicator_color = ++indicator_color % 5;
						SetClassLong(hwnd,GCL_HBRBACKGROUND,(LONG)(m_hBrush[indicator_color]));
						InvalidateRect(hwnd,NULL,TRUE);
						UpdateWindow(hwnd);
						break;
					}
				default:
					break;
			}
			break;
		}
	case WM_NCCALCSIZE:
		{ //完全去掉标题栏和边框
			break;
		}
	case WM_SYSKEYDOWN:
		{  //屏蔽Alt + F4关闭窗口的功能
			if(wParam == VK_F4)
				;
			else
				return DefWindowProc(hwnd,message,wParam,lParam);
			break;
		}
	case WM_CLOSE:
		{
			if(IDOK == MessageBox(hwnd,TEXT("确定退出吗?"),TEXT("关闭窗口!"),MB_OKCANCEL | MB_ICONQUESTION))
				DestroyWindow(hwnd);
			break;
		}
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}
	default:
		return DefWindowProc(hwnd,message,wParam,lParam);
	}
	return 0;
}



LRESULT CALLBACK btn_CaptionProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	//static HINSTANCE hInstace = 
	switch(message)
	{
	case WM_SIZE:
		{
			int cxClient = LOWORD(lParam);
			int cyClient = HIWORD(lParam);
			int btn_width = cxClient / 15;
			int btn_height = cyClient / 4;
			MoveWindow(btn_hwnd[ID_MINIMIZE],cxClient - btn_width * 3, 0,
				         btn_width,btn_height,TRUE);
			MoveWindow(btn_hwnd[ID_MAXIMIZE],cxClient - btn_width * 2, 0,
				         btn_width,btn_height,TRUE);
			MoveWindow(btn_hwnd[ID_CLOSE],cxClient - btn_width, 0,
				         btn_width,btn_height,TRUE);
			break;
		}
	case WM_CTLCOLORBTN:
		{
			HDC hdc = HDC(wParam);
			switch(GetDlgCtrlID(HWND(lParam)))
			{
			case ID_MINIMIZE:
				{
					if(min_entry == FALSE)
					{
						SetBkColor(hdc,m_color[5]);
						SetTextColor(hdc,m_color[0]);
						RECT rect;
						GetClientRect(HWND(lParam),&rect);
						DrawText(hdc,TEXT("最小化"),lstrlen(TEXT("最小化")),&rect,DT_BOTTOM | DT_CENTER);
						return LRESULT(m_hBrush[5]);
					}
					else
					{
						SetBkColor(hdc,m_color[0]);
						SetTextColor(hdc,m_color[1]);
						RECT rect;
						GetClientRect(HWND(lParam),&rect);
						DrawText(hdc,TEXT("最小化"),lstrlen(TEXT("最小化")),&rect,DT_BOTTOM | DT_CENTER);
						return LRESULT(m_hBrush[0]);
					}
					break;
				}
			case ID_MAXIMIZE:
				{
					if(max_entry == FALSE)
					{
						SetBkColor(hdc,m_color[5]);
						SetTextColor(hdc,m_color[1]);
						RECT rect;
						GetClientRect(HWND(lParam),&rect);
						DrawText(hdc,TEXT("最大化"),lstrlen(TEXT("最大化")),&rect,DT_BOTTOM | DT_CENTER);
						return LRESULT(m_hBrush[5]);
					}
					else
					{
						SetBkColor(hdc,m_color[1]);
						SetTextColor(hdc,m_color[0]);
						RECT rect;
						GetClientRect(HWND(lParam),&rect);
						DrawText(hdc,TEXT("最大化"),lstrlen(TEXT("最大化")),&rect,DT_BOTTOM | DT_CENTER);
						return LRESULT(m_hBrush[1]);
					}
					break;
				}
			case ID_CLOSE:
				{
					if(close_entry == FALSE)
					{
						SetBkColor(hdc,m_color[5]);
						SetTextColor(hdc,m_color[3]);
						RECT rect;
						GetClientRect(HWND(lParam),&rect);
						DrawText(hdc,TEXT("关闭"),lstrlen(TEXT("关闭")),&rect,DT_BOTTOM | DT_CENTER);
						return LRESULT(m_hBrush[5]);
					}
					else
					{
						SetBkColor(hdc,m_color[0]);
						SetTextColor(hdc,m_color[2]);
						RECT rect;
						GetClientRect(HWND(lParam),&rect);
						DrawText(hdc,TEXT("关闭"),lstrlen(TEXT("关闭")),&rect,DT_BOTTOM | DT_CENTER);
						return LRESULT(m_hBrush[0]);
					}
					break;
				}
			default:
				break;
			}
			break;
		}
	case WM_COMMAND:
		{
			switch(LOWORD(wParam))
			{
			case ID_MINIMIZE:
				{
					SendMessage(GetParent(hwnd),WM_SYSCOMMAND,SC_MINIMIZE,lParam);
					break;
				}
			case ID_MAXIMIZE:
				{
					SendMessage(GetParent(hwnd),WM_SYSCOMMAND,SC_MAXIMIZE,lParam);
					break;
				}
			case ID_CLOSE:
				{
					SendMessage(GetParent(hwnd),WM_CLOSE,0,0);
					break;
				}
			default:
				break;
			}
			break;
		}
	case WM_LBUTTONDOWN:
		{ //模拟标题栏的鼠标左键双击
			SendMessage(GetParent(hwnd),WM_NCLBUTTONDOWN,HTCAPTION,lParam);
			break;
		}
	case WM_LBUTTONDBLCLK:
		{
			SendMessage(GetParent(hwnd),WM_NCLBUTTONDBLCLK,HTCAPTION,lParam);
			break;
		}
	case WM_MOUSEMOVE:
		{	
			TCHAR buf[] = TEXT("温馨提示:双击鼠标左键可以最大化窗口,\
按住鼠标左键可以拖动窗口!");
			MySetWindowText(buf);
			break;
		}
	default:
		return CallWindowProc(old_btn_CaptionProc,hwnd,message,wParam,lParam);
		// 也可以用下面的方式,一样的。
		// return old_btn_CaptionProc(hwnd,message,wParam,lParam);
	}
	return 0;
}

LRESULT CALLBACK btn_ClickProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	
	switch(message)
	{
	case WM_MOUSEMOVE:
		{


			if(click_entry == FALSE)
			{
				TRACKMOUSEEVENT tme;
				tme.cbSize = sizeof(TRACKMOUSEEVENT);
				tme.dwFlags = TME_HOVER | TME_LEAVE;
				tme.dwHoverTime = 1; //1ms 立即显示
				tme.hwndTrack = hwnd;
				//激活WM_MOUSEHOVER消息
				TrackMouseEvent(&tme);
			}
			break;
		}
	case WM_MOUSEHOVER:
		{
			click_entry = TRUE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);

			TCHAR buf[] = TEXT("点击鼠标左键可以更改窗口颜色!");
			MySetWindowText(buf);
			break;
		}
	case WM_MOUSELEAVE:
		{
			click_entry = FALSE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);
			break;
		}
	default:
		return CallWindowProc(old_btn_ClickProc,hwnd,message,wParam,lParam);
		//return old_btn_ClickProc(hwnd,message,wParam,lParam);
	}
	return 0;
}



LRESULT CALLBACK btn_MinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	
	switch(message)
	{
	case WM_MOUSEMOVE:
		{
			if(min_entry == FALSE)
			{
				TRACKMOUSEEVENT tme;
				tme.cbSize = sizeof(TRACKMOUSEEVENT);
				tme.dwFlags = TME_HOVER | TME_LEAVE;
				tme.dwHoverTime = 1; //1ms 立即显示
				tme.hwndTrack = hwnd;
				//激活WM_MOUSEHOVER消息
				TrackMouseEvent(&tme);
			}
			break;
		}
	case WM_MOUSEHOVER:
		{
			min_entry = TRUE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);

			TCHAR buf[] = TEXT("最小化窗口!!!");
			MySetWindowText(buf);
			break;
		}
	case WM_MOUSELEAVE:
		{
			min_entry = FALSE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);
			break;
		}
	default:
		return CallWindowProc(old_btn_MinProc,hwnd,message,wParam,lParam);
		//return old_btn_ClickProc(hwnd,message,wParam,lParam);
	}
	return 0;
}


LRESULT CALLBACK btn_MaxProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	
	switch(message)
	{
	case WM_MOUSEMOVE:
		{
			if(max_entry == FALSE)
			{
				TRACKMOUSEEVENT tme;
				tme.cbSize = sizeof(TRACKMOUSEEVENT);
				tme.dwFlags = TME_HOVER | TME_LEAVE;
				tme.dwHoverTime = 1; //1ms 立即显示
				tme.hwndTrack = hwnd;
				//激活WM_MOUSEHOVER消息
				TrackMouseEvent(&tme);
			}
			break;
		}
	case WM_MOUSEHOVER:
		{
			max_entry = TRUE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);

			TCHAR buf[] = TEXT("最大化窗口+++");
			MySetWindowText(buf);
			break;
		}
	case WM_MOUSELEAVE:
		{
			max_entry = FALSE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);
			break;
		}
	default:
		return CallWindowProc(old_btn_MaxProc,hwnd,message,wParam,lParam);
		//return old_btn_ClickProc(hwnd,message,wParam,lParam);
	}
	return 0;
}


LRESULT CALLBACK btn_CloseProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	
	switch(message)
	{
	case WM_MOUSEMOVE:
		{
			if(close_entry == FALSE)
			{
				TRACKMOUSEEVENT tme;
				tme.cbSize = sizeof(TRACKMOUSEEVENT);
				tme.dwFlags = TME_HOVER | TME_LEAVE;
				tme.dwHoverTime = 1; //1ms 立即显示
				tme.hwndTrack = hwnd;
				//激活WM_MOUSEHOVER消息
				TrackMouseEvent(&tme);
			}
			break;
		}
	case WM_MOUSEHOVER:
		{
			close_entry = TRUE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);

			TCHAR buf[] = TEXT("关闭窗口XXXXXXX");
			MySetWindowText(buf);
			break;
		}
	case WM_MOUSELEAVE:
		{
			close_entry = FALSE;
			InvalidateRect(hwnd,NULL,TRUE);
			UpdateWindow(hwnd);
			break;
		}
	default:
		return CallWindowProc(old_btn_CloseProc,hwnd,message,wParam,lParam);
		//return old_btn_ClickProc(hwnd,message,wParam,lParam);
	}
	return 0;
}



下面试程序运行的效果图!











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值