移动窗口和调整底部闪烁大小



我正在尝试制作一种从任务栏滑出的弹出式通知窗口。

目前我只是试图让它的工作,如果任务栏是在屏幕的底部,我让它像它应该的工作。

但我遇到的问题是,当窗口开始出现/滑动的底部部分闪烁(取决于有多大我设置了我的m_nIncrement值,它闪烁的底部区域相同的大小作为m_nIncrement值)窗口消失得很好,没有闪烁。

//MyWindow
WNDCLASS wc =
{
    CS_HREDRAW | CS_VREDRAW, __sWndProcDlg, 0, 0, g_hInst, nullptr,
    LoadCursor(nullptr, IDC_ARROW), (HBRUSH)::GetStockObject(BLACK_BRUSH),
    nullptr, m_lpszClassName
};
if (!RegisterClass(&wc))
    return;
m_hWnd = CreateWindowEx(WS_EX_NOACTIVATE, m_lpszClassName, NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, m_hWndParent, NULL, g_hInst, NULL);
//ShowWindow
void _ShowWindow(int _show)
{
    unsigned int nDesktopWidth = m_rcDesktop.right - m_rcDesktop.left;
    unsigned int nDesktopHeight = m_rcDesktop.bottom - m_rcDesktop.top;
    unsigned int nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
    unsigned int nScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
    BOOL bTaskbarOnRight = nDesktopWidth<nScreenWidth && m_rcDesktop.left == 0;
    BOOL bTaskbarOnLeft = nDesktopWidth<nScreenWidth && m_rcDesktop.left != 0;
    BOOL bTaskBarOnTop = nDesktopHeight<nScreenHeight && m_rcDesktop.top != 0;
    BOOL bTaskbarOnBottom = nDesktopHeight<nScreenHeight && m_rcDesktop.top == 0;
    if (_show)
    {
        ShowWindow(m_hWnd, SW_SHOW);
        if (bTaskbarOnBottom)
        {
            m_nCurrentPos.cx = m_rcDesktop.right - m_sMaxSize.cx;
            m_nCurrentPos.cy = m_rcDesktop.bottom - m_nCurrentSize.cy;
            m_nTaskbarPlacement = TASKBAR_ON_BOTTOM;
        }

        KillTimer(m_hWnd, IDT_DISAPPEARING);
        SetTimer(m_hWnd, IDT_APPEARING, 1, nullptr);
    }
    else
    {
        KillTimer(m_hWnd, IDT_APPEARING);
        if (bTaskbarOnRight)
            m_nCurrentPos.cx = m_rcDesktop.right - m_sMaxSize.cx;
        else if (bTaskbarOnLeft)
            m_nCurrentPos.cx = m_rcDesktop.left;
        else if (bTaskBarOnTop)
            m_nCurrentPos.cy = m_rcDesktop.top;
        else //if (bTaskbarOnBottom)
            m_nCurrentPos.cy = m_rcDesktop.bottom - m_nCurrentSize.cy;
        SetTimer(m_hWnd, IDT_DISAPPEARING, 1, NULL);
    }
}
//__OnTimer
LRESULT __OnTimer(HWND hWnd, UINT nIDEvent)
{
    int m_nIncrement = 20;
    if (nIDEvent == IDT_APPEARING)
    {
        switch (m_nTaskbarPlacement)
        {
        case TASKBAR_ON_BOTTOM:
            if (m_nCurrentPos.cy > (m_rcDesktop.bottom - m_sMaxSize.cy))
            {
                m_nCurrentPos.cy -= m_nIncrement;
                m_nCurrentSize.cy = m_rcDesktop.bottom - m_nCurrentPos.cy;
            }
            else
                KillTimer(hWnd, IDT_APPEARING);
            break;
        }
        SetFocus(hWnd);
        SetWindowPos(hWnd, HWND_TOPMOST, m_nCurrentPos.cx, m_nCurrentPos.cy, m_sMaxSize.cx, m_nCurrentSize.cy, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
    }
    else if (nIDEvent == IDT_DISAPPEARING)
    {
        switch (m_nTaskbarPlacement)
        {
        case TASKBAR_ON_BOTTOM:
            if (m_nCurrentPos.cy < m_rcDesktop.bottom)
            {
                m_nCurrentPos.cy += m_nIncrement;
                m_nCurrentSize.cy = m_rcDesktop.bottom - m_nCurrentPos.cy;
            }
            else
            {
                KillTimer(hWnd, IDT_DISAPPEARING);
                MoveWindow(m_hWnd, 0, 0, 0, 0, FALSE);
                ShowWindow(m_hWnd, SW_HIDE);
            }
            break;
        }
        SetWindowPos(hWnd, HWND_TOPMOST, m_nCurrentPos.cx, m_nCurrentPos.cy, m_sMaxSize.cx, m_nCurrentSize.cy, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
    }
    return true;
}

使用AnimateWindow代替。它很容易使用。你可能需要处理WM_PRINT,这也是非常简单的。

如果你想继续写你的代码,那么:

1)从弹出类移除标志CS_HREDRAW &CS_VREDRAW

2)处理WM_ERASEBACKGROUND 最后

。如果是一个弹出窗口,不要调用SetFocus();也许你需要将zorder设置为TOP_MOST

好运

最新更新