В моем случае предоставленный код не работал, потому что он вызывал исключение, и я не добавил файл манифеста должным образом. Я хотел бы отметить некоторые вещи:
Растровые изображения, сделанные с gimp, не работают; используйте то, что было предложено в теме, которую я связал в своем вопросе, и это будет PixelFormer. В Pixel Former go «file», затем «Import» и выберите свой файл (в моем случае это был прозрачный png круга). Далее go для «экспорта» и выбора растрового изображения BMP (windows растровое изображение, которое он скажет). После того, как вы это сделаете, уже будет выбран A8: R8: G8: B8 (32bpp), и вам нужно будет проверить последние два поля «Предварительно умноженная альфа» и «Порядок строк сверху вниз». Надо сказать, что изображение действительно имеет альфа-канал и оно прозрачно. Не дайте себя одурачить, открывая краску, и вы видите черный фон, и вы думаете, что прозрачности нет - она есть, прозрачность работает ... Если вы откроете ее в фотошопе (я думаю) или изощренно Программа редактирования изображений вы увидите прозрачный фон на вашем изображении.
манифест. xml
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<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>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
Скопируйте вышеприведенное и сохраните его как манифест. xml
Еще одна вещь, которую я хотел бы отметить, это добавление Файл записи манифеста: в моем случае я должен был добавить его в C: \ Users \ Rubel \ source \ repos \ CustomButton2 \ CustomButton2, так что, кто бы ни смотрел на это в будущем, замените его своим каталогом вашего проекта, например , C: \ Users \ blah \ source \ repos \ blah \ blah (бла с названием вашего материала). Вставьте туда свой файл манифеста (в каталоге).
Затем вам нужно добавить его в Visual Studio. Это можно сделать, щелкнув правой кнопкой мыши в своем проекте в обозревателе решений (в моем случае это был CustomButton2) и go в «Инструменте манифеста» в «Ввод и вывод». Здесь введите «Дополнительные файлы манифеста» путь к вашему файлу манифеста (в моем случае это был манифест. xml, но если вы следовали ему, то это также относится и к вашему пути)
и нажмите кнопку ОК.
Вот и все, если вы использовали заданный код (Strive Sun - MSFT), он должен работать. Вот мой окончательный код, если кому-то было интересно:
// CustomButton2.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "CustomButton2.h"
#include <commctrl.h>
#include <gdiplus.h>
#include <system_error>
#define MAX_LOADSTRING 100
#define CRAPPY 567
#define IDC_OWNERDRAWBUTTON 101
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' " "version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
const char g_szClassName[] = "MyClassName";
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
void RegisterClass1(HINSTANCE);
LRESULT CALLBACK WndProc(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);
// TODO: Place code here.
RegisterClass1(hInstance);
HWND hWnd = CreateWindowExA(WS_EX_LAYERED, g_szClassName, "Scenes", WS_OVERLAPPEDWINDOW | WS_EX_LAYERED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hInstance, NULL);
HWND hButton = CreateWindow(TEXT("BUTTON"), TEXT("START EDITING!"), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW | WS_EX_LAYERED, 1, 1,228, 228,
hWnd, (HMENU)CRAPPY, NULL, NULL);
SetWindowSubclass(hButton, &OwnerDrawButtonProc, IDC_OWNERDRAWBUTTON, 0);
//SetLayeredWindowFromBitmapResource(hButton, ID_THECIRCLE, hInstance);
SetLayeredWindowAttributes(hWnd, 0, 249, LWA_ALPHA);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//SetLayeredWindowFromBitmapResource(hButton, ID_THECIRCLE);
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// FUNCTION: RegisterClass1()
//
// PURPOSE: Registers the class
//
// COMMENTS:
//
//
//
//
void RegisterClass1(HINSTANCE hInstance) {
WNDCLASSEXA wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
//wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = g_szClassName;
wc.lpszMenuName = "MENU";
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
}
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_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);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
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, ID_THECIRCLE);
EndPaint(hWnd, &ps);
return 0;
}
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &OwnerDrawButtonProc, 1);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Запуск приложения: ![enter image description here](https://i.stack.imgur.com/5THFX.png)
Я знаю, что это было многословно, но я хотел, чтобы это было легко кто бы ни сталкивался с этим, чтобы они знали, как это сделать.