WinAPI CreateWindow WS_POPUP调整闪烁的大小

时间:2016-10-31 10:11:18

标签: winapi createwindowex setwindowpos

我正在创建一个没有边框的窗口(CreateWindow中的WS_POPUP),并且需要在鼠标结束时调整它的大小,并在鼠标离开应用程序时进行更改。它工作正常,但是当我使用SetWindowPos更改位置时它会闪烁。我需要将y减小30像素并增加高度,因此窗口的底部保持在相同的位置。

以下是代码:

WNDCLASS windowClass;
ZeroMemory(&windowClass, sizeof(WNDCLASS));

windowClass.style = 0;// CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = (WNDPROC) WindowProc;
windowClass.hInstance = hInst;
windowClass.lpszClassName = PROCESS_WINDOW_CLASS;
windowClass.hIcon = NULL;
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);

windowHandle = CreateWindowEx(
    0,
    PROCESS_WINDOW_CLASS,
    L"",
    WS_POPUP | WS_CLIPSIBLINGS,
    x,  //x
    y,  //y
    width, //width
    height, //height
    NULL, 
    NULL, 
    hInst,
    NULL);

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
    case WM_MOUSEMOVE: {
        if (!mouseOver) {
            TRACKMOUSEEVENT tme;

            tme.cbSize = sizeof(TRACKMOUSEEVENT);
            tme.dwFlags = TME_LEAVE;
            tme.hwndTrack = hwnd;
            if (TrackMouseEvent(&tme)) {
                RECT rect;
                GetWindowRect(hwnd, &rect);

                int y = rect.top;
                int height = rect.bottom - y;

                y -= BUTTONS_AREA_HEIGHT;
                height += BUTTONS_AREA_HEIGHT;
                //tried with MoveWindow, DeferWindowPos - same thing
                //MoveWindow(hwnd, rect.left, y, rect.right - rect.left, height, TRUE);

                //HDWP winPos = BeginDeferWindowPos(1);
                //DeferWindowPos(winPos, hwnd, NULL, rect.left, y, rect.right - rect.left, height, 0);
                //EndDeferWindowPos(winPos);

                SetWindowPos(hwnd, NULL, rect.left, y, rect.right - rect.left, height,
                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING);
                rect.top = y;
                rect.bottom = height - y;
                InvalidateRect(hwnd, &rect, FALSE);
                    //0);
                RedrawWindow(hwnd, NULL, NULL, RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_NOERASE);
                mouseOver = TRUE;
            }
        }
    }
    break;
    case WM_MOUSELEAVE: {
        RECT rect;
        GetWindowRect(hwnd, &rect);

        int y = rect.top;
        int height = rect.bottom - y;

        y += BUTTONS_AREA_HEIGHT;
        height -= BUTTONS_AREA_HEIGHT;

        MoveWindow(hwnd, rect.left, y, rect.right - rect.left, height, TRUE);

        //SetWindowPos(hwnd, NULL, rect.left, y, rect.right - rect.left, height,
        //  SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
        //InvalidateRect(hwnd, &rect, FALSE);
        //SetWindowPos(hwnd, NULL, rect.left, y, rect.right - rect.left, height, 0);
        mouseOver = FALSE;
    }
    case WM_CREATE: {
        LONG lExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
        lExStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | 
            WS_SYSMENU | WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);

        SetWindowLongPtr(hwnd, GWL_EXSTYLE, lExStyle | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);

        SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(EXIT_SUCCESS);
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

我尝试了SetWindowPos,MoveWindow等的所有组合,但当鼠标在窗口上方时,似乎窗口首先设置Y位置,然后它在几毫秒后增加高度,这是可见的。

有没有人知道这方面的解决方案?

1 个答案:

答案 0 :(得分:0)

我通过使用SetWindowRgn函数修复了问题。 这仍然没有回答为什么闪烁发生的问题,但它解决了我的问题,因为我能够实现同样的事情。代码如下:

HRGN region = CreateRectRgn(0, BUTTONS_AREA_HEIGHT, width, height);
SetWindowRgn(windowHandle, region, TRUE);
DeleteObject(region);