У меня есть многоуровневое окно в моей программе, и кажется (визуально) все работает нормально, но код возврата из UpdateLayeredWindow должен иметь ненулевое значение в случае успеха. В моем случае это 0, а GetLastError возвращает 87, то есть для неверного параметра. Может ли кто-нибудь сказать мне, что с моей настройкой что-то не так? Вот полная функция, стили окон: WS_EX_LAYERED|WS_EX_TOPMOST и WS_POPUP.

bool SplashScreen(HWND hwnd, HINSTANCE m_hinstance)
{
    HBITMAP hBitmap = (HBITMAP)LoadImage(m_hinstance, "splash.bmp", IMAGE_BITMAP, 640, 640, LR_LOADFROMFILE);
    PAINTSTRUCT     ps;
    HDC             hdc;
    BITMAP          bitmap;
    HDC             hdcMem;
    HGDIOBJ         oldBitmap;
    int result=0;

    if(!SetLayeredWindowAttributes(hwnd, 0, (255 * 100) / 100, LWA_ALPHA))
    {
        char msg[255];
        sprintf(msg,"Error SetLayeredWindowAttributes: %d",GetLastError());
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    hdc = BeginPaint(hwnd, &ps);
    if(!hdc)
    {
        char msg[255];
        sprintf(msg,"Error BeginPaint: %d",GetLastError());
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    hdcMem = CreateCompatibleDC(hdc);
    if(!hdcMem)
    {
        char msg[255];
        sprintf(msg,"Error CreateCompatibleDC: %d",GetLastError());
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    oldBitmap = SelectObject(hdcMem, hBitmap);

    GetObject(hBitmap, sizeof(bitmap), &bitmap);
    result=BitBlt(hdc, 0, 0, 640, 640, hdcMem, 0, 0, SRCCOPY);
    if(result==0)
    {
        char msg[255];
        sprintf(msg,"Error BitBlt: %d",GetLastError());
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    BLENDFUNCTION blend = { 0 };
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;

    result=UpdateLayeredWindow(hwnd,GetDC(NULL),NULL,NULL,hdcMem,NULL, RGB(0,0,0),&blend, ULW_ALPHA);// Returns non-zero on success(!), in reality works when 0 is returned.
    if(result==0)
    {
        char msg[255];
        sprintf(msg,"Error UpdateLayeredWindow: %d",GetLastError());// Error UpdateLayeredWindow: 87
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    result=SetLayeredWindowAttributes(hwnd, RGB(255,255,255), 0, ULW_COLORKEY);
    if(result==0)
    {
        char msg[255];
        sprintf(msg,"Error SetLayeredWindowAttributes: %d",GetLastError());
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    result=EndPaint(hwnd, &ps);
    if(result==0)
    {
        char msg[255];
        sprintf(msg,"Error EndPaint: %d",GetLastError());
        MessageBox(hwnd,msg,"System",MB_OK);
        return false;
    }

    SelectObject(hdcMem, oldBitmap);
    DeleteDC(hdc);
    DeleteObject(hdcMem);
    return true;
}
3
Vladivarius 9 Фев 2014 в 06:39

1 ответ

Лучший ответ

Вы звоните SetLayeredWindowAttributes() и UpdateLayeredWindow() по одному и тому же HWND. Это не сработает, и документация по этому поводу очень ясна:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633540(v=vs.85).aspx

Обратите внимание, что после вызова SetLayeredWindowAttributes для многоуровневого окна последующие вызовы UpdateLayeredWindow завершатся ошибкой до тех пор, пока бит стиля наложения не будет сброшен и установлен снова.

Не используйте SetLayeredWindowAttributes() и UpdateLayeredWindow() вместе. Это очень разные методологии. Либо используйте SetLayeredWindowAttributes() с традиционным рисунком WM_PAINT, либо используйте UpdateLayeredWindow() с растровым изображением в памяти. Не используйте оба. Судя по тому, что вы показали, вы должны использовать UpdateLayeredWindow() отдельно. Он установит растровое изображение в качестве содержимого окна и одновременно установит прозрачность / альфа окна.

И не используйте Begin/EndPaint() вне обработчика WM_PAINT.

9
Remy Lebeau 9 Фев 2014 в 08:28