要制作一个热点按钮并实现所描述的需求,你可以按照以下步骤进行操作:

  1. 准备资源文件:

    • 在你的项目中添加两个图片资源,分别命名为 IDB_PNG1 和 IDB_PNG2,这两个资源分别对应普通情况下和热点效果下的按钮图片。
  2. 编写对话框模板:

    • 在资源文件中,打开对话框资源(IDD_DIALOG1)并添加一个按钮控件(IDOK)。
    • 将按钮控件的风格设置为 BS_OWNERDRAW,这样你可以自定义按钮的外观。
    • 将按钮控件的 ID 设置为一个自定义的 ID,比如 IDC_HOTSPOT_BUTTON。
  3. 编写绘制按钮的函数:

    • 在代码中,编写一个绘制按钮的函数,用于绘制按钮的外观,包括普通情况下和热点效果下的外观。
    • 在函数中,使用 GDI+ 库加载并绘制两种不同状态下的按钮图片。
  4. 注册和处理按钮消息:

    • 在 DialogProc 函数中,注册和处理按钮的消息。
    • 在 WM_INITDIALOG 消息中,使用 GetDlgItem 获取按钮句柄,并使用 SetWindowLongPtr 设置按钮的风格为 BS_OWNERDRAW。
    • 在 WM_DRAWITEM 消息中,根据绘制按钮的函数来绘制按钮的外观。
    • 在 WM_COMMAND 消息中,根据按钮的 ID 来处理按钮的点击事件。

以下是一个示例代码,演示了如何制作热点按钮并实现所描述的需求:

#include <windows.h>
#include <windowsx.h>
#include <vector>
#include <gdiplus.h>
#include "resource.h"
#pragma comment(lib, "gdiplus.lib")

using namespace Gdiplus;

HINSTANCE Hinstance;

// 存储按钮绘制效果所需的参数
struct CustomButtonData {
    RECT rect;
    bool isHot;
    HBITMAP normalImage;
    HBITMAP hotImage;

    CustomButtonData(RECT r, HBITMAP normal, HBITMAP hot)
        : rect(r), isHot(false), normalImage(normal), hotImage(hot) {}
};

// 全局变量,存储按钮的绘制效果数据
std::vector<CustomButtonData> buttonsData;

void DrawCustomButton(HDC hdc, const CustomButtonData& data) {
    HBITMAP hBitmap = data.isHot ? data.hotImage : data.normalImage;
    HDC hMemDC = CreateCompatibleDC(hdc);
    HGDIOBJ hOldBitmap = SelectObject(hMemDC, hBitmap);
    BitBlt(hdc, data.rect.left, data.rect.top, data.rect.right - data.rect.left,
        data.rect.bottom - data.rect.top, hMemDC, 0, 0, SRCCOPY);
    SelectObject(hMemDC, hOldBitmap);
    DeleteDC(hMemDC);
}

INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_INITDIALOG: {
        // 获取按钮句柄并存储绘制数据
        HWND hButton = GetDlgItem(hwndDlg, IDC_HOTSPOT_BUTTON);
        RECT rect;
        GetClientRect(hButton, &rect);
        HBITMAP normalImage = LoadBitmap(Hinstance, MAKEINTRESOURCE(IDB_PNG1));
        HBITMAP hotImage = LoadBitmap(Hinstance, MAKEINTRESOURCE(IDB_PNG2));
        CustomButtonData data(rect, normalImage, hotImage);
        buttonsData.push_back(data);
        // 设置按钮风格为 BS_OWNERDRAW
        SetWindowLongPtr(hButton, GWL_STYLE, GetWindowLongPtr(hButton, GWL_STYLE) | BS_OWNERDRAW);
        return TRUE;
    }
    case WM_DRAWITEM: {
        // 绘制按钮
        DRAWITEMSTRUCT* dis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
        for (const auto& data : buttonsData) {
            if (dis->CtlID == IDC_HOTSPOT_BUTTON && dis->hwndItem == GetDlgItem(hwndDlg, IDC_HOTSPOT_BUTTON)) {
                data.isHot = (dis->itemState & ODS_SELECTED) || (dis->itemState & ODS_FOCUS);
                DrawCustomButton(dis->hDC, data);
                break;
            }
        }
        return TRUE;
    }
    case WM_COMMAND: {
        if (LOWORD(wParam) == IDC_HOTSPOT_BUTTON && HIWORD(wParam) == BN_CLICKED) {
            // 点击了热点按钮,执行相应操作
            MessageBox(hwndDlg, "Hotspot Button Clicked!", "Button Clicked", MB_OK);
            return TRUE;
        }
        break;
    }
    case WM_CLOSE: {
        EndDialog(hwndDlg, 0);
        return TRUE;
    }
    }
    return FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    Hinstance = hInstance;

    // 初始化 GDI+
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    // 创建并显示对话框
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);

    // 释放 GDI+
    GdiplusShutdown(gdiplusToken);

    return 0;
}

请注意,上述示例代码中使用了 GDI+ 库来加载和绘制按钮的图片。确保你的项目正确地链接了 gdiplus.lib 库,并且在代码中包含了相关的头文件。

希望这可以帮助到你!如果你还有其他问题,请随时提问。

如何制作一个热点按钮 - 使用 Windows API 和 GDI+ 实现自定义按钮

原文地址: https://www.cveoy.top/t/topic/VlY 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录