WindowsAPI自绘按钮

自绘按钮有多种方法,比如创建一个BS_OWNERDRAW风格的按钮,然后就可以自绘了,但是这个好像不能用SetWindowRgn画各种形状。我介绍的这个方法很简单,但是代码量会稍多一点。就是把一个按钮当做一个单独的窗口来处理,但是这就必须要每个按钮都要注册一个类,所以代码会多一点。

总体的思路是:注册主窗口类并创建主窗口–>注册子窗口类并创建子窗口(就是按钮)–>实现各自的窗口过程–>处理对应的消息.

效果如图:

WindowsAPI自绘按钮_第1张图片
WindowsAPI自绘按钮_第2张图片

代码详解及注释:

#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);

}

你可能感兴趣的:(api,sdk,自绘按钮)