我有一个背景色为蓝色的win32窗口.我使用代码在窗口上创建了一个按钮
// code for creating button
hButton1= CreateWindow(_T("BUTTON"),_T("Test button"), BS_ICON | WS_VISIBLE | WS_CHILD ,800,200,228,228,hWnd, (HMENU)1,NULL,NULL);
Run Code Online (Sandbox Code Playgroud)
我使用代码将.png透明图像加载为按钮图像
// code to
// using GDI
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Gdiplus::Bitmap* m_pBitmap;
HICON hicon;
m_pBitmap = Gdiplus::Bitmap::FromFile(L"d:\\gear.png");
m_pBitmap->GetHICON(&hicon);
LRESULT lr = SendMessage(hButton1,BM_SETIMAGE,IMAGE_ICON,(LPARAM)hicon );
ShowWindow(hButton1,SW_SHOW);
Run Code Online (Sandbox Code Playgroud)
现在按钮显示透明的.png图像数据,按钮默认背景颜色.我将按钮背景颜色更改为蓝色.但是当我们加载.png文件时,按钮颜色变为默认颜色.
我需要保持按钮的透明区域与窗口的背景颜色相同,即蓝色.你可以参考我窗口的图像

AFAIK没有简单的方法使按钮的背景透明,只让它绘制图标.
可以使用自定义绘制来完全控制按钮的外观.还有"所有者绘制",但对于按钮,此技术在Windows Vista中已过时.自定义绘图的优点是您不必修改按钮样式(例如,您可以保留BS_DEFPUSHBUTTON),并且它也更灵活,因为您只需要执行部分绘图.对于我们的用例,我们需要绘制所有内容.
要使用自定义绘图,请在按钮父级的窗口过程中处理NM_CUSTOMDRAW通知.当NMCUSTOMDRAW::dwDrawStage等于CDDS_PREERASE,做你的图纸,并返回CDRF_SKIPDEFAULT所以Windows没有油漆过你画什么.
为了实现透明性,可以调用DrawThemeParentBackground()父窗口的背景,然后调用DrawIconEx()在背景上透明地绘制图标.
这是一个完整的工作示例程序.为清楚起见省略了错误处理
#include <windows.h>
#include <gdiplus.h>
#include <uxtheme.h> // for DrawThemeParentBackground()
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "uxtheme.lib")
// Common controls manifest entry is required for using custom draw.
// Remove this pragma if you have already included this in the manifest of your project.
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CustomDrawButton( HWND hWnd, NMCUSTOMDRAW const& nmc );
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// Initialize GDI+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL );
// Register window class for main window
WNDCLASS wc{ sizeof(wc) }; // set cbSize and zero-init all other members
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush( RGB( 255, 200, 127 ) );
wc.lpszClassName = L"MyWindowClass";
RegisterClassW( &wc );
// Create main window
HWND hWnd = CreateWindowExW( 0, wc.lpszClassName, L"Test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, nullptr );
ShowWindow( hWnd, nCmdShow );
// Create button
HWND hButton1 = CreateWindow( L"BUTTON", L"Test button", BS_ICON | WS_VISIBLE | WS_CHILD, 50, 50, 228, 228, hWnd, (HMENU) 1, NULL, NULL );
// Assign image to button
Gdiplus::Bitmap* m_pBitmap;
HICON hicon;
m_pBitmap = Gdiplus::Bitmap::FromFile(L"test.png");
m_pBitmap->GetHICON(&hicon);
LRESULT lr = SendMessage( hButton1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon );
// Standard message loop
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NOTIFY:
{
auto pnm = reinterpret_cast<LPNMHDR>( lParam );
if( pnm->code == NM_CUSTOMDRAW )
{
// NOTE: you should check if pnm->hwndFrom really is the button
// you want to draw. Not required in this example because
// we only have one control.
LRESULT res = CustomDrawButton( pnm->hwndFrom, *reinterpret_cast<LPNMCUSTOMDRAW>( lParam ) );
if( res != 0 )
return res;
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CustomDrawButton( HWND hWnd, NMCUSTOMDRAW const& nmc )
{
switch( nmc.dwDrawStage )
{
case CDDS_PREERASE:
{
RECT rc{}; GetClientRect( hWnd, &rc );
// Draw the background of the parent window.
DrawThemeParentBackground( hWnd, nmc.hdc, &rc );
// Get the icon we assigned to the button.
HICON hIcon = reinterpret_cast<HICON>( SendMessage( hWnd, BM_GETIMAGE, IMAGE_ICON, 0 ) );
// Draw the icon transparently over the background.
DrawIconEx( nmc.hdc, 0, 0, hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL );
// Tell Windows we have drawn everything by ourselfs.
return CDRF_SKIPDEFAULT;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我的按钮图像("test.png"):
这就是最终结果的样子: