2016-09-24 121 views
0

我一直在使用Windows API自定義窗口擺弄。就這樣,我一直在使用Extended Layered Windows。我畫了窗口,它可以工作。然而,當調整窗口大小時,當重繪/ UpdateLayeredWindow(和UpdateLayeredWindowIndirect)方法被調用時,會出現奇怪的閃爍/閃爍[(Screenshot)] [1]。有什麼我在這裏做錯了嗎?Visual-C Win32 API分層窗口閃爍

void redrawBaseWindow(HWND window) { 
    RECT rect; 
    GetWindowRect(window, &rect); 
    int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025; 
    HDC mainDC = GetDC(NULL); 
    POINT destination = { rect.left,rect.top }; 
    POINT zero = destination; 
    SIZE size = { rect.right - rect.left,rect.bottom - rect.top }; 
    BLENDFUNCTION bf; 
    bf.BlendOp = AC_SRC_OVER; 
    bf.BlendFlags = 0; 
    bf.AlphaFormat = 0; 
    bf.SourceConstantAlpha = 255; 
    HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100)); 
    HBRUSH oldbrush = SelectObject(mainDC, brush); 
    HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); 
    HPEN oldPen = SelectObject(mainDC, pen); 
    HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy); 
    HBITMAP oldBmp = SelectObject(mainDC, bmp); 
    FillRect(mainDC, &rect, CreateSolidBrush(RGB(0, 0, 0))); 
    Rectangle(mainDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2); 
    Rectangle(mainDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom); 
    UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, mainDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect}; 
    UpdateLayeredWindowIndirect(window, &updated); 
    //BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY); 
    SelectObject(mainDC, oldbrush); 
    SelectObject(mainDC, oldBmp); 
    SelectObject(mainDC, oldPen); 
    DeleteObject(brush); 
    DeleteObject(bmp); 
    DeleteObject(pen); 
} 

以防萬一,窗口消息處理。

long __stdcall WndProc(HWND window, unsigned int msg, WPARAM wp, LPARAM lp) { 
    PAINTSTRUCT ps; 
    HDC hdc; 
    TCHAR greeting[] = "Hello, World!"; 
    RECT rect_window; 
    GetWindowRect(window, &rect_window); 
    switch (msg) { 
    case WM_SYSKEYDOWN: 
     MessageBeep(MB_ICONERROR); 
    case WM_CREATE: 
    break; 
case WM_DESTROY: 
    PostQuitMessage(0); 
    break; 
case WM_NCHITTEST:; 
    int x = LOWORD(lp); 
    int y = HIWORD(lp); 
    if (x > rect_window.left && x<rect_window.right && y>rect_window.top && y < rect_window.top + 25) 
     return HTCAPTION; 
    if (x>=rect_window.left-3 && x<=rect_window.left+3) 
     return HTLEFT; 
    if (x >= rect_window.right - 3 && x <= rect_window.right + 3) 
     return HTRIGHT; 
    if (y >= rect_window.top - 3 && y <= rect_window.top + 3) 
     return HTTOP; 
    if (y >= rect_window.bottom - 3 && y <= rect_window.bottom + 3) 
     return HTBOTTOM; 
    break; 
case WM_LBUTTONDOWN: 
    break; 
case WM_SIZE: 
    redrawBaseWindow(window); 
    break; 
case WM_PAINT: 
    break; 
} 
return DefWindowProc(window, msg, wp, lp); 
} 

編輯: Gif of the glitch

編輯2: 使用CreateCompatibleDC值成UpdateLayeredWindow [而且不工作]

void redrawBaseWindow(HWND window) { 
    RECT rect; 
    GetWindowRect(window, &rect); 
    int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025; 
    HDC mainDC = GetDC(NULL); 
    HDC memDC = CreateCompatibleDC(mainDC); 
    POINT destination = { rect.left,rect.top }; 
    POINT zero = destination; 
    SIZE size = { rect.right - rect.left,rect.bottom - rect.top }; 
    BLENDFUNCTION bf; 
    bf.BlendOp = AC_SRC_OVER; 
    bf.BlendFlags = 0; 
    bf.AlphaFormat = 0; 
    bf.SourceConstantAlpha = 255; 
    HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100)); 
    HBRUSH oldbrush = SelectObject(memDC, brush); 
    HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); 
    HPEN oldPen = SelectObject(memDC, pen); 
    HBITMAP bmp = CreateCompatibleBitmap(memDC, size.cx,size.cy); 
    HBITMAP oldBmp = SelectObject(memDC, bmp); 
    FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0))); 
    Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2); 
    Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom); 
    Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left 
    Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right 
    Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left 
    Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right 
    UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect}; 
    UpdateLayeredWindowIndirect(window, &updated); 
    //BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY); 
    SelectObject(memDC, oldbrush); 
    SelectObject(memDC, oldBmp); 
    SelectObject(memDC, oldPen); 
    DeleteObject(brush); 
    DeleteObject(bmp); 
    DeleteObject(pen); 
    ReleaseDC(NULL,mainDC); 
    ReleaseDC(NULL,memDC); 
} 

編輯3:DeleteDC CreateCompatibleDC裝置,以及位圖的創建上在屏幕上DC而不是CompatibleDC

void redrawBaseWindow(HWND window) { 
    RECT rect; 
    GetWindowRect(window, &rect); 
    int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025; 
    HDC mainDC = GetDC(NULL); 
    HDC memDC = CreateCompatibleDC(mainDC); 
    POINT destination = { rect.left,rect.top }; 
    POINT zero = destination; 
    SIZE size = { rect.right - rect.left,rect.bottom - rect.top }; 
    BLENDFUNCTION bf; 
    bf.BlendOp = AC_SRC_OVER; 
    bf.BlendFlags = 0; 
    bf.AlphaFormat = 0; 
    bf.SourceConstantAlpha = 255; 
    HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100)); 
    HBRUSH oldbrush = SelectObject(memDC, brush); 
    HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); 
    HPEN oldPen = SelectObject(memDC, pen); 
    HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy); 
    HBITMAP oldBmp = SelectObject(memDC, bmp); 
    FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0))); 
    Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2); 
    Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom); 
    Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left 
    Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right 
    Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left 
    Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right 
    UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect}; 
    UpdateLayeredWindowIndirect(window, &updated); 
    //BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY); 
    SelectObject(memDC, oldbrush); 
    SelectObject(memDC, oldBmp); 
    SelectObject(memDC, oldPen); 
    DeleteObject(brush); 
    DeleteObject(bmp); 
    DeleteObject(pen); 
    DeleteDC(memDC); 
    ReleaseDC(NULL,mainDC); 
} 

原始閃爍固定。謝謝[喬納森Pottar] 但是已經發生的另一個錯誤:This

+0

請創建一個動畫gif截圖,我看不到您的圖像上的問題。 – Lothar

+0

只需一小會兒 – UnknownRobotik

+1

從'GetDC'獲得的DC中選擇一個不同的位圖有點奇怪,我不確定是否支持將屏幕的DC傳遞給'UpdateLayeredWindow'。正常的用法是將你的位圖選擇到從'CreateCompatibleDC'獲得的內存DC中,渲染並從中更新窗口。你也有一個GDI資源泄漏(不調用'ReleaseDC')。 –

回答

0
void redrawBaseWindow(HWND window) { 
RECT rect; 
GetWindowRect(window, &rect); 
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025; 
HDC mainDC = GetDC(NULL); 
HDC memDC = CreateCompatibleDC(mainDC); 
POINT destination = { rect.left,rect.top }; 
POINT zero = destination; 
SIZE size = { rect.right - rect.left,rect.bottom - rect.top }; 
BLENDFUNCTION bf; 
bf.BlendOp = AC_SRC_OVER; 
bf.BlendFlags = 0; 
bf.AlphaFormat = 0; 
bf.SourceConstantAlpha = 255; 
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100)); 
HBRUSH oldbrush = SelectObject(memDC, brush); 
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); 
HPEN oldPen = SelectObject(memDC, pen); 
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy); 
HBITMAP oldBmp = SelectObject(memDC, bmp); 
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0))); 
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2); 
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom); 
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left 
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right 
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left 
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right 
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect}; 
UpdateLayeredWindowIndirect(window, &updated); 
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY); 
SelectObject(memDC, oldbrush); 
SelectObject(memDC, oldBmp); 
SelectObject(memDC, oldPen); 
DeleteObject(brush); 
DeleteObject(bmp); 
DeleteObject(pen); 
DeleteDC(memDC); 
ReleaseDC(NULL,mainDC); 
} 

這值得慶幸的是固定我的問題。