Visual-C Win32 API分层窗口闪烁

时间:2016-09-24 01:20:03

标签: c windows winapi

我一直在使用windows API摆弄自定义窗口。因此,我一直在使用Extended Layered Windows。我画了窗口,它有效。但是,在调整窗口大小时,调用redraw / UpdateLayeredWindow(和UpdateLayeredWindowIndirect)方法时会出现奇怪的闪烁/毛刺[(屏幕截图)] [1]。我有什么问题吗?

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);
}

以防万一,Window Message Proc。

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:CreateCompatibleDC设备上的DeleteDC,以及在屏幕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);
}

原始闪烁固定。谢谢[Jonathan Pottar] 但是发生了另一个错误:This

1 个答案:

答案 0 :(得分: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);
}

谢天谢地解决了我的问题。