gpt4 book ai didi

c++ - 将 HBITMAP 绘制到分层窗口上。怎么了?

转载 作者:可可西里 更新时间:2023-11-01 14:51:40 26 4
gpt4 key购买 nike

大家好,美好的一天,

我的最终目标是将包含 alpha 的 PNG 文件绘制到屏幕上 - 这意味着不是绘制到自己的窗口中,而是绘制到桌面上的某个位置。将 PNG 加载到 HBITMAP 的部分现在可以工作(以不同的方式测试)但我无法绘制它包括 alpha。

据我所知,执行此操作的最佳方法是使用分层窗口。所以我做了很多工作来重做几个示例和小教程。

下面的代码编译没有问题并且没有提示任何消息(这意味着 showError("#") 函数从未被调用)。

但屏幕上什么都看不到:/

抱歉,它太长了...希望有人愿意至少快速查看它..

LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);


int main(HINSTANCE hInstance)
{


WNDCLASSEX WndClass;
char sClassName[] = "mainClass";
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.style = NULL;
WndClass.lpfnWndProc = WndProc;//WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = NULL;
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = sClassName;
WndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (RegisterClassEx(&WndClass) == 0) showError("-1");





HWND screen = CreateWindowEx(WS_EX_LAYERED,//WS_EX_LEFT
"mainClass",
"UpdateLayeredWind",
WS_DISABLED | WS_VISIBLE,
200,200,260,260,
NULL /*eventuelly, GM window*/,
NULL,
hInstance,
NULL);


if (screen == NULL) showError("0");




HBITMAP img = LoadImageResource("D://ThreadDraw/ThreadDraw-test/ThreadDraw/test.png");
if (img == NULL) showError("1");






BLENDFUNCTION blend = {0};

blend.AlphaFormat = AC_SRC_ALPHA;
blend.SourceConstantAlpha = 155;

POINT ptPos = {200,300};
SIZE sizeWnd = {260,260};
POINT ptPos2 = {200,300};


ShowWindow(screen, SW_SHOW);



while (1)
{


PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;

hdc = BeginPaint(screen, &ps);

hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, img);

GetObject(img, sizeof(bitmap), &bitmap);


if (SetLayout(hdc,LAYOUT_RTL) == GDI_ERROR)
showError("5");



if (!BitBlt(hdc, 0, 0, 64, 64, hdcMem, 0, 0, SRCCOPY))
showError("4");



if (!UpdateLayeredWindow(screen,hdcMem,&ptPos,&sizeWnd,hdc,&ptPos2,RGB(255,255,255),&blend,ULW_ALPHA))//ULW_OPAQUE))
showError("2");



EndPaint(screen, &ps);

SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);


Sleep(10);

}



return 0;
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}

顺便说一下,如果我在 UpdateLayeredWindow 中使用 ULW_OPAQUE 而不是 ULW_ALPHA,则会出现一个大小合适的黑色窗口,因此认为问题必须与 PAINTSTRUKT 或 BitBlt 函数相关。但我尝试了很多方法没有任何变化。

希望有人能帮忙。非常感谢您!

最佳答案

这主要是错误的。您的代码应该:

  • 使用 CreateWindowEx 创建分层窗口。
  • 使用 UpdateLayeredWindow 将位图附加到它。
  • 使用 ShowWindow 显示窗口。 Windows 将负责绘制分层窗口,因此您无需处理 WM_PAINT 或调用 BeginPaint
  • 进入消息循环。

就是这样。

如果您使用的是 Visual Studio,请创建一个新的 Win32 项目,它会为您创建一个带有消息循环的新项目。

更新

这是一个创建透明分层窗口的示例程序。它需要一个函数来加载 PNG 作为透明位图。而且它没有错误检查。

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
LPCTSTR szWindowClass = _T("TransparentClass");

// Register class
WNDCLASSEX wcex = {0};

wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = DefWindowProc;
wcex.hInstance = hInstance;
wcex.lpszClassName = szWindowClass;

RegisterClassEx(&wcex);

HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, 0, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

int width;
int height;
HBITMAP hbmp = LoadPng(L"sample.png", &width, &height);

HDC hdcScreen = GetDC(0);
HDC hdc = CreateCompatibleDC(hdcScreen);
ReleaseDC(0, hdcScreen);
HBITMAP hbmpold = (HBITMAP)SelectObject(hdc, hbmp);

POINT dcOffset = {0, 0};
SIZE size = {width, height};
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(hWnd, 0, 0, &size, hdc, &dcOffset, 0, &bf, ULW_ALPHA);
SelectObject(hdc, hbmpold);
DeleteDC(hdc);
DeleteObject(hbmp);

ShowWindow(hWnd, SW_SHOW);

MSG msg;

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;
}

另一个更新

下面是一些代码,用于将红色、绿色和蓝色值预乘 alpha。它假定 splash_image 指向大小为 width*height 的 32bpp ARGB 数据。

LPBYTE bits = (LPBYTE)splash_image;
int size = width * height;
for (int pixel = 0; pixel != size; ++pixel)
{
bits[0] = bits[0] * bits[3] / 255;
bits[1] = bits[1] * bits[3] / 255;
bits[2] = bits[2] * bits[3] / 255;
bits += 4;
}

关于c++ - 将 HBITMAP 绘制到分层窗口上。怎么了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12626729/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com