Exemple #1
0
void NotificationWnd::UpdateWindowPosition(const WCHAR *message, bool init)
{
    // compute the length of the message
    RECT rc = ClientRect(self).ToRECT();

    HDC hdc = GetDC(self);
    HFONT oldfnt = SelectFont(hdc, font);
    DrawText(hdc, message, -1, &rc, DT_CALCRECT | DT_SINGLELINE | DT_NOPREFIX);
    SelectFont(hdc, oldfnt);
    ReleaseDC(self, hdc);

    RectI rectMsg = RectI::FromRECT(rc);
    if (hasCancel) {
        rectMsg.dy = std::max(rectMsg.dy, 16);
        rectMsg.dx += 20;
    }
    rectMsg.Inflate(PADDING, PADDING);

    if (shrinkLimit < 1.0f) {
        ClientRect rcOrig(self);
        if (rectMsg.dx < rcOrig.dx && rectMsg.dx > rcOrig.dx * shrinkLimit)
            rectMsg.dx = rcOrig.dx;
    }

    // adjust the window to fit the message (only shrink the window when there's no progress bar)
    if (!hasProgress) {
        SetWindowPos(self, nullptr, 0, 0, rectMsg.dx, rectMsg.dy, SWP_NOMOVE | SWP_NOZORDER);
    } else if (init) {
        RectI rect = WindowRect(self);
        rect.dx = std::max(progressWidth + 2 * PADDING, rectMsg.dx);
        rect.dy = rectMsg.dy + PROGRESS_HEIGHT + PADDING / 2;
        SetWindowPos(self, nullptr, 0, 0, rect.dx, rect.dy, SWP_NOMOVE | SWP_NOZORDER);
    } else if (rectMsg.dx > progressWidth + 2 * PADDING) {
        SetWindowPos(self, nullptr, 0, 0, rectMsg.dx, WindowRect(self).dy, SWP_NOMOVE | SWP_NOZORDER);
    }

    // move the window to the right for a right-to-left layout
    if (IsUIRightToLeft()) {
        HWND parent = GetParent(self);
        RectI rect = MapRectToWindow(WindowRect(self), HWND_DESKTOP, parent);
        rect.x = WindowRect(parent).dx - rect.dx - TL_MARGIN - GetSystemMetrics(SM_CXVSCROLL);
        SetWindowPos(self, nullptr, rect.x, rect.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    }
}
    void Update()
    {
        // maintain top/left pos
        CRect rcwnd;
        GetWindowRect(rcwnd);

        // Clear text
        m_wndRTF.SetWindowText(NULL);

        // Stream in new text...
        CComVariant bstr;
        std::string text;
        if(m_vertex)
            m_vertex->GetProperty(PROP_TOOLTIP, bstr);
        if(m_edge)
            m_edge->GetProperty(PROP_TOOLTIP, bstr);
        if (bstr.vt == VT_BSTR)
            text = CW2A(bstr.bstrVal);
        LPCSTR pstrText=text.c_str();
        RtfStream st = { pstrText, 0 }; 
        EDITSTREAM es = { 0 };
        es.dwCookie = (DWORD) &st;
        es.dwError = 0;
        es.pfnCallback = _StreamReadCallback;
        UINT uFormat = pstrText[0]=='{' ? SF_RTF : SF_TEXT;
        m_wndRTF.StreamIn(uFormat, es);

        // Request new layout
        int cx = DEFAULT_WIDTH;
        CRect rc( 0, 0, cx, DEFAULT_HEIGHT);
        m_wndRTF.ResizeClient(cx, DEFAULT_HEIGHT, FALSE);
        m_wndRTF.SetRect(&rc);
        m_wndRTF.RequestResize();
        CRect rcRTF(m_rcRTF);
        CRect rcOrig(m_rcRTF);

        // Resize RTF control until the height changes. This will indicate
        // the minimum/optimal width of the text.
        int iStep = 30;
        while( true ) 
        {
            ATLASSERT(cx>0);
            CRect rc( 0, 0, cx - iStep, DEFAULT_HEIGHT);
            m_wndRTF.ResizeClient(cx - iStep, DEFAULT_HEIGHT, FALSE);
            m_wndRTF.SetRect(&rc);
            m_wndRTF.RequestResize();
            if(rcRTF.Height() != m_rcRTF.Height()) 
            {
                if( iStep <= 1 ) break;
                iStep /= 2;
            }
            else 
            {
                cx -= iStep;
                if( cx <= 0 ) 
                {
                    rcRTF = rcOrig;
                    break;
                }
                rcRTF = m_rcRTF; // Apply better width
            }
        }

        bool notnormal=IsIconic() || IsZoomed();
        m_wndRTF.SetWindowPos(0, &rcRTF, (notnormal?0:SWP_SHOWWINDOW) | SWP_NOACTIVATE | SWP_NOZORDER);
        if(!notnormal)
        {
            DWORD exstyle=GetWndExStyle(0);
            rcwnd.right=rcwnd.left+rcRTF.Width();
            rcwnd.bottom=rcwnd.top+rcRTF.Height();
            ::AdjustWindowRectEx(&rcwnd, GetWndStyle(0), FALSE, exstyle);
            // finally, keep it inside screen bounds
            CRect rcScreen;
            ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, 0);
            if(rcwnd.right > rcScreen.right) 
                rcwnd.OffsetRect(-(rcwnd.right-rcScreen.right), 0);
            if(rcwnd.top < rcScreen.top) 
                rcwnd.OffsetRect(0, rcScreen.top-rcwnd.top);

            SetWindowPos(0, rcwnd, SWP_NOZORDER);
        }
    }