自绘按钮有多种方法,比如创建一个BS_OWNERDRAW风格的按钮,然后就可以自绘了,但是这个好像不能用SetWindowRgn画各种形状。我介绍的这个方法很简单,但是代码量会稍多一点。就是把一个按钮当做一个单独的窗口来处理,但是这就必须要每个按钮都要注册一个类,所以代码会多一点。
总体的思路是:注册主窗口类并创建主窗口–>注册子窗口类并创建子窗口(就是按钮)–>实现各自的窗口过程–>处理对应的消息.
代码详解及注释:
#include <windows.h>
#include <tchar.h>
#include "resource.h"
HINSTANCE hInst = NULL; //全局实例句柄
LRESULT CALLBACK WindProc(HWND, UINT, WPARAM, LPARAM);//主窗口过程
LRESULT CALLBACK BtnProc1(HWND, UINT, WPARAM, LPARAM); //按钮1窗口过程
LRESULT CALLBACK BtnProc2(HWND, UINT, WPARAM, LPARAM);//按钮2窗口过程
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
hInst = hInstance;
TCHAR szAppName[] = TEXT("MyApp"); //主窗口类名
TCHAR szBtnName1[] = TEXT("MyBtn1"); //按钮窗口类名
TCHAR szBtnName2[] = TEXT("MyBtn2");
//主窗口类
WNDCLASS wndclass = { 0 };
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(COLOR_BACKGROUND);
wndclass.hCursor = NULL;
wndclass.hIcon = NULL;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WindProc;
wndclass.lpszClassName = szAppName;
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("RegisterClass wndclass failed"), TEXT("ERROR"), 0);
return 0;
}
//主窗口
HWND hwnd = CreateWindow(szAppName, TEXT("MyWindow"), WS_OVERLAPPEDWINDOW,
100, 100, 300, 200, NULL, NULL, hInstance, 0);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
//自定义按钮类
WNDCLASS wndbtn1 = { 0 };
wndbtn1.cbClsExtra = 0;
wndbtn1.cbWndExtra = 0; //这个是位图背景,需要自己添加位图资源
wndbtn1.hbrBackground = CreatePatternBrush(LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP)));
wndbtn1.hCursor = NULL;
wndbtn1.hIcon = NULL;
wndbtn1.hInstance = hInstance;
wndbtn1.lpfnWndProc = BtnProc1;
wndbtn1.lpszClassName = szBtnName1;
wndbtn1.lpszMenuName = NULL;
wndbtn1.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wndbtn1))
{
MessageBox(NULL, TEXT("RegisterClass wndbtn failed"), TEXT("ERROR"), 0);
return 0;
}
//自绘按钮
HWND hButton1 = CreateWindow(szBtnName1, TEXT("MyButton1"),
WS_CHILD | WS_VISIBLE,0, 0, 0, 0, hwnd, NULL, hInstance, 0);
ShowWindow(hButton1, SW_SHOW);
UpdateWindow(hButton1);
WNDCLASS wndbtn2 = { 0 };
wndbtn2.cbClsExtra = 0;
wndbtn2.cbWndExtra = 0;
wndbtn2.hbrBackground = CreateSolidBrush(RGB(255,0,0));
wndbtn2.hCursor = NULL;
wndbtn2.hIcon = NULL;
wndbtn2.hInstance = hInstance;
wndbtn2.lpfnWndProc = BtnProc2;
wndbtn2.lpszClassName = szBtnName2;
wndbtn2.lpszMenuName = NULL;
wndbtn2.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wndbtn2))
{
MessageBox(NULL, TEXT("RegisterClass wndbtn failed"), TEXT("ERROR"), 0);
return 0;
}
HWND hButton2 = CreateWindow(szBtnName2, TEXT("MyButton2"),
WS_CHILD | WS_VISIBLE,0, 0, 0, 0, hwnd, NULL, hInstance, 0);
ShowWindow(hButton2, SW_SHOW);
UpdateWindow(hButton2);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps = { 0 };
HDC DC = NULL;
switch (message)
{
case WM_CREATE:
break;
case WM_PAINT:
DC = BeginPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
LRESULT CALLBACK BtnProc1(HWND hBtn1, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps = { 0 };
HDC DC = NULL;
switch (message)
{
case WM_CREATE:
{
MoveWindow(hBtn1, 10, 10, 100, 100, TRUE);
//画椭圆区域,还可以画圆角,多边形等等,可以自行百度
HRGN hRgn = CreateEllipticRgn(10, 10, 100, 100);
SetWindowRgn(hBtn1, hRgn, TRUE);
}
break;
case WM_LBUTTONDOWN: //测试是否成功响应消息
MessageBox(NULL, TEXT("MyButton1"), TEXT("提示"), 0);
break;
case WM_PAINT:
{
DC = BeginPaint(hBtn1, &ps);
SetBkColor(DC, RGB(0, 255, 255)); //按钮背景颜色
SetTextColor(DC, RGB(255, 0, 0)); //按钮上的文字颜色
TextOut(DC, 20, 45, TEXT("MyButton1"), 9);//按钮上的文字
EndPaint(hBtn1, &ps);
}
break;
default:
break;
}
return DefWindowProc(hBtn1, message, wParam, lParam);
}
LRESULT CALLBACK BtnProc2(HWND hBtn2, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps = { 0 };
HDC DC = NULL;
switch (message)
{
case WM_CREATE:
{
MoveWindow(hBtn2, 160, 10, 250, 100, TRUE);
//画椭圆区域,还可以画圆角,多边形等等,可以自行百度
HRGN hRgn = CreateRoundRectRgn(10, 10, 100, 100,20,20);
SetWindowRgn(hBtn2, hRgn, TRUE);
}
break;
case WM_LBUTTONDOWN:
MessageBox(NULL, TEXT("MyButton2"), TEXT("提示"), 0);
break;
case WM_PAINT:
{
DC = BeginPaint(hBtn2, &ps);
SetBkColor(DC, RGB(0, 255, 255)); //按钮背景颜色
SetTextColor(DC, RGB(255, 0, 0)); //按钮上的文字颜色
TextOut(DC, 20, 45, TEXT("MyButton2"), 9); //按钮上的文字
EndPaint(hBtn2, &ps);
}
break;
default:
break;
}
return DefWindowProc(hBtn2, message, wParam, lParam);
}