簡體   English   中英

將HBITMAP繪制到分層窗口上。怎么了?

[英]Draw HBITMAP onto layered window. What's wrong?

大家好,祝大家好,

我的最終目標是在屏幕上繪制一個包含alpha的PNG文件 - 這意味着不要進入自己的窗口,而只是桌面上的某個地方。 將PNG加載到HBITMAP中的部分現在可以正常工作(以不同的方式進行測試),但我無法繪制它,包括alpha。

據我所知,最好的方法是使用alyered窗戶。 所以我花了很多時間來重做幾個例子和小教程。

下面的代碼編譯沒有問題,並且沒有提示任何消息(這意味着永遠不會調用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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM