欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Win32 API自绘按钮

程序员文章站 2022-07-05 13:00:11
...

WinMain.c

#include <windows.h>

HINSTANCE hInst;
WNDPROC OldBtnProc;
BOOL bMouseHover;
HBRUSH hBrush1;
HBRUSH hBrush2;
HBRUSH hBrush3;

LRESULT CALLBACK WindowProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	);

LRESULT CALLBACK NewBtnProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	);

int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine,
	int nCmdShow
	)
{
	hInst = hInstance;
	bMouseHover = FALSE;

	WNDCLASS wndcls;
	wndcls.cbClsExtra = 0;
	wndcls.cbWndExtra = 0;
	wndcls.hbrBackground = GetStockObject(GRAY_BRUSH);
	wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
	wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
	wndcls.hInstance = hInstance;
	wndcls.lpfnWndProc = WindowProc;
	wndcls.lpszClassName = TEXT("MainWnd");
	wndcls.lpszMenuName = NULL;
	wndcls.style = CS_VREDRAW | CS_VREDRAW;
	RegisterClass(&wndcls);
	HWND hwnd = CreateWindow(TEXT("MainWnd"),TEXT("MainWnd"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	MSG msg;
	while (GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	)
{
	static HWND hBtn;
	DRAWITEMSTRUCT* pdis;

	switch (uMsg)
	{
	case WM_CREATE:
		hBrush1 = CreateSolidBrush(RGB(0, 255, 0));
		hBrush2 = CreateSolidBrush(RGB(255, 0, 0));
		hBrush3 = CreateSolidBrush(RGB(0, 0, 255));
		hBtn = CreateWindow(TEXT("BUTTON"), TEXT("按钮1"), WS_CHILD |WS_VISIBLE| BS_OWNERDRAW, 50, 50, 200, 100, hwnd,
			123, hInst, NULL);
		OldBtnProc = SetWindowLong(hBtn,GWL_WNDPROC, NewBtnProc);
		SetFocus(hBtn);
		return 0;

	case WM_DRAWITEM:
		pdis = (LPDRAWITEMSTRUCT)lParam;
		if (GetCapture() == hBtn)
		{
			if (pdis->itemState & ODS_SELECTED)//如果鼠标选中按钮
			{
				FillRect(pdis->hDC, &pdis->rcItem, hBrush3);//蓝色
			}
			else
			{
				FillRect(pdis->hDC, &pdis->rcItem, hBrush2);//初始按钮样式:红色
			}
		}
		else
		{
			if (bMouseHover)//鼠标悬停
			{
				FillRect(pdis->hDC, &pdis->rcItem, hBrush1);//初始按钮样式:绿色
			}
			else
			{
				FillRect(pdis->hDC, &pdis->rcItem, hBrush2);//初始按钮样式:红色
			}
		}
		if (pdis->itemState & ODS_FOCUS)//如果按钮获得焦点
		{
			DrawFocusRect(pdis->hDC, &pdis->rcItem);
		}
		return 0;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case 123:
			//MessageBox(hwnd,TEXT("按钮"),0,0);
			break;
		}
		return 0;
		 
	case WM_CLOSE:
		DestroyWindow(hwnd);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd,uMsg,wParam,lParam);
}


LRESULT CALLBACK NewBtnProc(HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
	)
{
	switch (uMsg)
	{
	case WM_MOUSEMOVE://注意,只要当鼠标位于窗口内,即使没有移动,也会产生WM_MOUSEMOVE消息
	{
		if (!bMouseHover)
		{
			bMouseHover = TRUE;//特别注意:这条语句不能放在TrackMouseEvent函数调用之后
			InvalidateRect(hwnd, NULL, TRUE);
			UpdateWindow(hwnd);

			TRACKMOUSEEVENT tme;
			tme.cbSize = sizeof(tme);
			tme.hwndTrack = hwnd;
			tme.dwFlags = TME_LEAVE | TME_HOVER;
			tme.dwHoverTime = HOVER_DEFAULT;
			TrackMouseEvent(&tme);
		}
		break;
	}

	//可以用于显示ToolTip提示框
	case WM_MOUSEHOVER:
		break;

	case WM_MOUSELEAVE:
		bMouseHover = FALSE;
		InvalidateRect(hwnd, NULL, TRUE);
		UpdateWindow(hwnd);
		break;

	}
	return CallWindowProc(OldBtnProc,hwnd,uMsg,wParam,lParam);
}