// Test_CustomButton.cpp : Defines the entry point for the application.
// #include "framework.h"
#include "Test_CustomButton.h"
#include <commctrl.h>
#include <system_error> #pragma comment (lib,"Comctl32.lib") #define MAX_LOADSTRING 100
#define IDC_OWNERDRAWBUTTON 101
#define CRAPPY 567 // Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); void SetLayeredWindowFromBitmapResource(
HWND hwnd, UINT bitmapResourceId, HINSTANCE hInstance = nullptr)
{
DWORD exStyle = ::GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED); struct Resources {
HBITMAP hImage = nullptr;
HGDIOBJ hOldImage = nullptr;
HDC hMemDC = nullptr;
~Resources()
{
if (hMemDC)
{
if (hOldImage)
::SelectObject(hMemDC, hOldImage);
::DeleteDC(hMemDC);
}
if (hImage)
::DeleteObject(hImage);
}
} res; if (!hInstance)
hInstance = ::GetModuleHandle(nullptr); res.hImage = reinterpret_cast<HBITMAP>(::LoadImage(
hInstance, MAKEINTRESOURCE(bitmapResourceId), IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION)); BITMAP imgInfo{ 0 };
GetObject(res.hImage, sizeof(imgInfo), &imgInfo); res.hMemDC = ::CreateCompatibleDC(nullptr);
res.hOldImage = ::SelectObject(res.hMemDC, res.hImage); // Assign the image to the child window, making it transparent.
SIZE size{ imgInfo.bmWidth, imgInfo.bmHeight };
POINT ptSrc{ 0, 0 };
BLENDFUNCTION blend{ AC_SRC_OVER, 0, 200, AC_SRC_ALPHA };
UpdateLayeredWindow(hwnd, nullptr, nullptr, &size, res.hMemDC, &ptSrc,
0, &blend, ULW_ALPHA); // Destructor of res object will cleanup resources here!
} int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTCUSTOMBUTTON, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
} HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTCUSTOMBUTTON)); MSG msg; while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} return (int) msg.wParam;
} ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTCUSTOMBUTTON));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTCUSTOMBUTTON);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex);
} BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd); if (!hWnd)
{
return FALSE;
} ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd); return TRUE;
} LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ switch (message)
{
case WM_CREATE:
{
HWND hButton = CreateWindowEx(0, L"button", NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 150, 50, 80, 80, hWnd, (HMENU)IDC_OWNERDRAWBUTTON, hInst, NULL);
SetWindowSubclass(hButton, &OwnerDrawButtonProc, IDC_OWNERDRAWBUTTON, 0);
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// Used be test
HPEN hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
SelectObject(hdc, hPen);
MoveToEx(hdc, 150, 150, NULL);
LineTo(hdc, 200, 60);
LineTo(hdc, 250, 150);
LineTo(hdc, 150, 150);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
} // Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE; case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
} LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_PAINT:
{
RECT rc;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
SetLayeredWindowFromBitmapResource(hWnd, IDB_BITMAP1);
EndPaint(hWnd, &ps);
return 0;
}
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &OwnerDrawButtonProc, 1);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

注意:

在测试时,我发现需要满足以下条件:

  • 要加载的图像必须是32 bpp的,具有预乘alpha通道的自上而下的位图(可以使用PixelFormer工具转换)。

在PixelFormer中,依次转到“文件”,“导入”并选择您的文件(在我的情况下为透明png圆圈)。接下来转到“导出”,然后选择bmp位图(它将显示Windows位图)。完成此操作后,将已经选择了A8:R8:G8:B8(32bpp),接下来必须选中最后两个框“预乘Alpha”和            “自上而下的行顺序”。

这是我的32 bpp图像供您测试。

  • 需要添加一个清单文件,您可以自己创建一个.manifest文件。然后将其添加到编译器中。

因为从win 8开始,WS_EX_LAYERED可用于子控件。

方法:需要清单文件来指定至少Windows 8兼容性(仅Windows 8支持子层)。

参考:针对Windows的应用程序

  • 您只需要将WS_EX_LAYERED样式添加到子控件中,因为您的要求是使按钮透明。

清单文件代码:

<!-- example.exe.manifest -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
type="win32"
name="Contoso.ExampleApplication.ExampleBinary"
version="1.2.3.4"
processorArchitecture="x86"
/>
<description>Contoso Example Application</description>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<!--
UAC settings:
- app should run at same integrity level as calling process
- app does not need to manipulate windows belonging to
higher-integrity-level processes
-->
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"
/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

最后的效果:

win32-创建透明的图片按钮的更多相关文章

  1. NSIS:简单按钮美化插件SkinButton,支持透明PNG图片。

    原文 NSIS:简单按钮美化插件SkinButton,支持透明PNG图片. 征得作者贾可的同意,特发布按钮美化插件SkinButton. 插件说明: 使用GDI+库写的一个简单按钮美化插件,支持透明P ...

  2. Expression Blend4经验分享:制作一个简单的图片按钮样式

    这次分享如何做一个简单的图片按钮经验 在我的个人Silverlight网页上,有个Iphone手机的效果,其中用到大量的图片按钮 http://raimon.6.gwidc.com/Iphone/de ...

  3. xcode UIButton创建、监听按钮点击、自定义按钮 、状态 、内边距

    代码创建 //创建UIButton UIButton * btnType=[[UIButton alloc]init]; //设置UIControlStateNormal状态下的文字颜色 [btnTy ...

  4. Unity 游戏开发技巧集锦之创建透明的材质

    Unity 游戏开发技巧集锦之创建透明的材质 Unity创建透明的材质 生活中不乏透明或者半透明的事物.例如,擦的十分干净的玻璃,看起来就是透明的:一些塑料卡片,看起来就是半透明的,如图3-23所示. ...

  5. 网页中PNG透明背景图片的完美应用

    PNG 图片在网站设计中是不可或缺的部分,最大的特点应该在于 PNG 可以无损压缩,而且还可以设置透明,对于增强网站的图片色彩效果有重要的作用. 但为什么 PNG 图片却没有 GIF 和 JPG 图片 ...

  6. [Xcode 实际操作]四、常用控件-(2)UIButton图片按钮的使用

    目录:[Swift]Xcode实际操作 本文将演示图片按钮的使用 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit class ViewCo ...

  7. Qt 制作透明背景图片与裁剪图片(很实用)

    这两天想做一个五子棋游戏,想从零开始自己绘制各种图片素材,将经验心得整理如下. 制作透明背景图片: void MyPainter::DrawKit() { QImage image(30, 30, Q ...

  8. C# 使用PictureBox实现图片按钮控件

    引言 我们有时候会在程序的文件夹里看见一些图标,而这些图标恰好是作为按钮的背景图片来使用的.鼠标指针在处于不同状态时,有"进入按钮"."按下左键"," ...

  9. 利用box-shadow实现伪边框透明到图片

    前阵子突然看到了一个效果,一张图片,有一个边框,但是边框可以透明到图片.直接上图 贴代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tr ...

  10. [示例] Firemonkey 图片按钮(3态)

    说明:Firemonkey 图片按钮(支持三种状态:MouseOver, MouseDown, MouseUp,可各别指定图片) 原码下载:[示例]TestImageButton_圖片按鈕(3态).z ...

随机推荐

  1. [转帖]Shell三剑客之awk

    目录 awk简述 awk的工作过程 awk的工作原理 awk的基本格式及其内置变量 getline 文本内容匹配过滤打印 对字段进行处理打印 条件判断打印 awk的三元表达式与精准筛选用法 awk的精 ...

  2. [转帖]JVM——内存区域:运行时数据区域详解

    https://www.jianshu.com/p/cded765cfd1b 关注:CodingTechWork,一起学习进步. 引言   我们经常会被问到一个问题是Java和C++有何区别?我们除了 ...

  3. Mysql数据库部分管理命令极简学习总结

    背景 今天遇到一个得很奇怪的问题. Mysql一个运行时间很长的select阻塞了对select里面左连接表做create index 操作的SQL 当时感觉不应该, 一直以为读锁不会与独占更新锁互斥 ...

  4. 使用smem 计算Oracle用户下内存占用情况.

    1. 本来计划使用 ps 命令进行查看, 但是发现ps 最多查询出来的是 RSS的内存数据, 会多添加很多冗余的内存数据量进来, 于是作罢 2. 找了下公司的方神, 说可以使用smem 然后简单看了下 ...

  5. CTT Day3

    T1 忘了叫什么名字 对于一个排列 \(p\),定义它的权值为其有多少个子串是一个值域从 \(1\) 开始的排列.给定排列 \(p\),对于 \(1\le i\le j\le n\),定义 \(f(i ...

  6. css3文字阴影和盒子阴影

    文字阴影 文字阴影的语法格式: text-shadow:水平向右的偏移值 向下的偏移值 迷糊度 阴影的颜色,水平向右的偏移值 向下的偏移值 迷糊度 阴影的颜色; 可以有多个阴影,但是在实际的项目中最多 ...

  7. SignalR系列文章01---MVC项目中创建demo

    1.  新建mvc项目,引入指定的nuget包 2.  新增加一个集成器类添加如下的代码 /// <summary> /// 供客户端调用的服务器端代码 /// </summary& ...

  8. TienChin 活动管理-工程创建

    工程模块的创建,与之前创建渠道管理一样的,所以这里就不贴图带着大家一起动手进行了,表结构我已经给到大家了,这里我只贴一下代码生成器的代码部分即可. @Test void generateActivit ...

  9. JVM底层原理

    目录 1.类加载器与ClassFileFormate 2.JVM内存模型 3.对象在JVM中的创建与内存分配 4.对象引用与垃圾回收算法 5.JVM垃圾回收 6.G1垃圾回收器 7.ZGC垃圾回收器

  10. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-37-如何截图-上篇

    1.简介 这个系列的文章也讲解和分享了差不多三分之一吧,突然有小伙伴或者童鞋们问道playwright有没有截图的方法.答案当然是:肯定有的.宏哥回过头来看看确实这个非常基础的知识点还没有讲解和分享. ...