https://git.reactos.org/?p=reactos.git;a=commitdiff;h=73ba03add1ccf725b85c55b4d0532ed640993d6d

commit 73ba03add1ccf725b85c55b4d0532ed640993d6d
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Thu Jan 18 19:25:46 2024 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Thu Jan 18 19:25:46 2024 +0900

    [SDK] cicuif.h: Add CUIFBalloonButton and CUIFBalloonWindow (#6384)
    
    Supporting TIPs...
    JIRA issue: CORE-19360
    - Implement CUIFBalloonButton class.
    - Half-implement CUIFBalloonWindow class.
---
 sdk/include/reactos/cicero/cicuif.h | 700 +++++++++++++++++++++++++++++++++---
 1 file changed, 660 insertions(+), 40 deletions(-)

diff --git a/sdk/include/reactos/cicero/cicuif.h 
b/sdk/include/reactos/cicero/cicuif.h
index c5f4bfcc845..fc05fb72f33 100644
--- a/sdk/include/reactos/cicero/cicuif.h
+++ b/sdk/include/reactos/cicero/cicuif.h
@@ -23,12 +23,15 @@ class CUIFTheme;
         class CUIFWindow;
             class CUIFToolTip;
             class CUIFShadow;
+            class CUIFBalloonWindow;
+        class CUIFButton;
+            class CUIFButton2;
+                class CUIFToolbarMenuButton;
+                class CUIFToolbarButtonElement;
+            class CUIFBalloonButton;
         class CUIFToolbarButton;
-    class CUIFButton;
-        class CUIFButton2;
-            class CUIFToolbarMenuButton;
-            class CUIFToolbarButtonElement;
-    class CUIFGripper;
+        class CUIFWndFrame;
+        class CUIFGripper;
 class CUIFObjectArray;
 class CUIFColorTable;
     class CUIFColorTableSys;
@@ -203,7 +206,7 @@ protected:
     CUIFWindow *m_pWindow;
     CUIFScheme *m_pScheme;
     CUIFObjectArray m_ObjectArray;
-    DWORD m_dwUnknown3; //FIXME: name and type
+    DWORD m_nObjectID;
     DWORD m_style;
     RECT m_rc;
     BOOL m_bEnable;
@@ -214,9 +217,10 @@ protected:
     DWORD m_dwUnknown4[2]; //FIXME: name and type
     friend class CUIFWindow;
     friend class CUIFToolTip;
+    friend class CUIFBalloonWindow;
 
 public:
-    CUIFObject(CUIFObject *pParent, DWORD dwUnknown3, LPCRECT prc, DWORD 
style);
+    CUIFObject(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, DWORD style);
     virtual ~CUIFObject();
 
     void StartCapture();
@@ -544,7 +548,6 @@ protected:
     CUIFToolTip *m_pToolTip;
     CUIFShadow *m_pShadow;
     BOOL m_bShowShadow;
-    CUIFWindow *m_pShadowOrToolTipOwner;
     friend class CUIFObject;
     friend class CUIFShadow;
     friend class CUIFToolTip;
@@ -574,7 +577,7 @@ public:
     static LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMsg, WPARAM 
wParam, LPARAM lParam);
 
     STDMETHOD_(LPCTSTR, GetClassName)();
-    STDMETHOD_(LPCTSTR, GetWndText)();
+    STDMETHOD_(LPCTSTR, GetWndTitle)();
     STDMETHOD_(DWORD, GetWndStyle)();
     STDMETHOD_(DWORD, GetWndStyleEx)();
     STDMETHOD_(HWND, CreateWnd)(HWND hwndParent);
@@ -620,6 +623,7 @@ public:
 class CUIFToolTip : public CUIFWindow
 {
 protected:
+    CUIFWindow *m_pToolTipOwner;
     CUIFObject *m_pToolTipTarget;
     LPWSTR m_pszToolTipText;
     BOOL m_bShowToolTip;
@@ -662,6 +666,7 @@ public:
 class CUIFShadow : public CUIFWindow
 {
 protected:
+    CUIFWindow *m_pShadowOwner;
     COLORREF m_rgbShadowColor;
     DWORD m_dwUnknown11[2];
     INT m_xShadowDelta;
@@ -722,7 +727,7 @@ protected:
     void DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed);
 
 public:
-    CUIFButton(CUIFObject *pParent, DWORD dwUnknown3, LPCRECT prc, DWORD 
style);
+    CUIFButton(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, DWORD style);
     ~CUIFButton() override;
 
     void SetIcon(HICON hIcon);
@@ -748,7 +753,7 @@ protected:
     SIZE m_BitmapSize;
 
 public:
-    CUIFButton2(CUIFObject *pParent, DWORD dwUnknown3, LPCRECT prc, DWORD 
style);
+    CUIFButton2(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, DWORD 
style);
     ~CUIFButton2() override;
 
     DWORD MakeDrawFlag();
@@ -763,7 +768,7 @@ class CUIFToolbarMenuButton : public CUIFButton2
 public:
     CUIFToolbarButton *m_pToolbarButton;
 
-    CUIFToolbarMenuButton(CUIFToolbarButton *pParent, DWORD dwUnknown3, 
LPCRECT prc, DWORD style);
+    CUIFToolbarMenuButton(CUIFToolbarButton *pParent, DWORD nObjectID, LPCRECT 
prc, DWORD style);
     ~CUIFToolbarMenuButton() override;
 
     STDMETHOD_(void, OnLButtonUp)(LONG x, LONG y) override;
@@ -777,7 +782,7 @@ class CUIFToolbarButtonElement : public CUIFButton2
 public:
     CUIFToolbarButton *m_pToolbarButton;
 
-    CUIFToolbarButtonElement(CUIFToolbarButton *pParent, DWORD dwUnknown3, 
LPCRECT prc, DWORD style);
+    CUIFToolbarButtonElement(CUIFToolbarButton *pParent, DWORD nObjectID, 
LPCRECT prc, DWORD style);
 
     STDMETHOD_(LPCWSTR, GetToolTip)() override;
     STDMETHOD_(void, OnLButtonUp)(LONG x, LONG y) override;
@@ -796,7 +801,7 @@ public:
 
     CUIFToolbarButton(
         CUIFObject *pParent,
-        DWORD dwUnknown3,
+        DWORD nObjectID,
         LPCRECT prc,
         DWORD style,
         DWORD dwToolbarButtonFlags,
@@ -876,6 +881,88 @@ public:
 
 /////////////////////////////////////////////////////////////////////////////
 
+class CUIFBalloonButton : public CUIFButton
+{
+protected:
+    UINT m_nCommandID;
+    friend class CUIFBalloonWindow;
+
+public:
+    CUIFBalloonButton(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, DWORD 
style);
+
+    STDMETHOD_(void, OnPaint)(HDC hDC) override;
+    void DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+// m_style flags for CUIFBalloonWindow
+enum
+{
+    UIF_BALLOON_WINDOW_OK = 0x10000,
+    UIF_BALLOON_WINDOW_YESNO = 0x20000,
+    UIF_BALLOON_WINDOW_TYPE_MASK = 0xF0000,
+};
+
+class CUIFBalloonWindow : public CUIFWindow
+{
+protected:
+    LPWSTR m_pszBalloonText;
+    HRGN m_hRgn;
+    RECT m_rcMargin;
+    DWORD m_dwUnknown6;
+    BOOL m_bHasBkColor;
+    BOOL m_bHasTextColor;
+    COLORREF m_rgbBkColor;
+    COLORREF m_rgbTextColor;
+    POINT m_ptTarget;
+    RECT m_rcExclude;
+    POINT m_ptBalloon;
+    DWORD m_dwUnknown7;
+    UINT m_nBalloonType;
+    DWORD m_dwUnknown8[2];
+    UINT m_cButtons;
+    WPARAM m_nActionID;
+    HWND m_hwndNotif;
+    UINT m_uNotifMsg;
+
+public:
+    CUIFBalloonWindow(HINSTANCE hInst, DWORD style);
+    ~CUIFBalloonWindow() override;
+
+    STDMETHOD_(void, Initialize)() override;
+    STDMETHOD_(LPCTSTR, GetClassName)() override;
+    STDMETHOD_(LPCTSTR, GetWndTitle)() override;
+    STDMETHOD_(void, OnCreate)(HWND hWnd) override;
+    STDMETHOD_(void, OnDestroy)(HWND hWnd) override;
+    STDMETHOD_(void, OnKeyDown)(HWND hWnd, WPARAM wParam, LPARAM lParam) 
override;
+    STDMETHOD_(LRESULT, OnObjectNotify)(CUIFObject *pObject, WPARAM wParam, 
LPARAM lParam) override;
+    STDMETHOD_(void, OnPaint)(HDC hDC) override;
+
+    void AddButton(UINT nCommandId);
+    void AdjustPos();
+    HRGN CreateRegion(LPCRECT prc);
+    void DoneWindowRegion();
+    CUIFBalloonButton *FindButton(UINT nCommandID);
+    CUIFObject *FindUIObject(UINT nObjectID);
+
+    COLORREF GetBalloonBkColor();
+    COLORREF GetBalloonTextColor();
+    void GetButtonSize(LPSIZE pSize);
+    void GetMargin(LPRECT prcMargin);
+    void SetExcludeRect(LPCRECT prcExclude);
+    void SetTargetPos(POINT ptTarget);
+    void SetText(LPCWSTR pszText);
+
+    void InitWindowRegion();
+    void LayoutObject();
+    void PaintFrameProc(HDC hDC, LPCRECT prc);
+    void PaintMessageProc(HDC hDC, LPRECT prc, LPCWSTR pszText);
+    void SendNotification(WPARAM wParam);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
 inline void cicInitUIFLib(void)
 {
     cicInitUIFSys();
@@ -1105,12 +1192,12 @@ CUIFTheme::SetActiveTheme(LPCWSTR pszClassList, INT 
iPartId, INT iStateId)
 
 /// @unimplemented
 inline
-CUIFObject::CUIFObject(CUIFObject *pParent, DWORD dwUnknown3, LPCRECT prc, 
DWORD style)
+CUIFObject::CUIFObject(CUIFObject *pParent, DWORD nObjectID, LPCRECT prc, 
DWORD style)
 {
     m_pszClassList = NULL;
     m_hTheme = NULL;
     m_pParent = pParent;
-    m_dwUnknown3 = dwUnknown3; //FIXME: name and type
+    m_nObjectID = nObjectID;
     m_style = style;
 
     if (prc)
@@ -2500,7 +2587,7 @@ inline LPCTSTR CUIFWindow::GetClassName()
     return TEXT("CiceroUIWndFrame");
 }
 
-inline LPCTSTR CUIFWindow::GetWndText()
+inline LPCTSTR CUIFWindow::GetWndTitle()
 {
     return TEXT("CiceroUIWndFrame");
 }
@@ -2541,7 +2628,7 @@ CUIFWindow::GetWndStyleEx()
 inline STDMETHODIMP_(HWND)
 CUIFWindow::CreateWnd(HWND hwndParent)
 {
-    HWND hWnd = CreateWindowEx(GetWndStyleEx(), GetClassName(), GetWndText(), 
GetWndStyle(),
+    HWND hWnd = CreateWindowEx(GetWndStyleEx(), GetClassName(), GetWndTitle(), 
GetWndStyle(),
                                m_nLeft, m_nTop, m_nWidth, m_nHeight,
                                hwndParent, NULL, m_hInst, this);
     if (m_pToolTip)
@@ -3238,7 +3325,7 @@ CUIFWindow::OnAnimationStart()
 inline CUIFShadow::CUIFShadow(HINSTANCE hInst, DWORD style, CUIFWindow 
*pShadowOwner)
     : CUIFWindow(hInst, (style | UIF_WINDOW_TOOLWINDOW))
 {
-    m_pShadowOrToolTipOwner = pShadowOwner;
+    m_pShadowOwner = pShadowOwner;
     m_rgbShadowColor = RGB(0, 0, 0);
     m_dwUnknown11[0] = 0;
     m_dwUnknown11[1] = 0;
@@ -3248,8 +3335,8 @@ inline CUIFShadow::CUIFShadow(HINSTANCE hInst, DWORD 
style, CUIFWindow *pShadowO
 
 inline CUIFShadow::~CUIFShadow()
 {
-    if (m_pShadowOrToolTipOwner)
-        m_pShadowOrToolTipOwner->m_pShadow = NULL;
+    if (m_pShadowOwner)
+        m_pShadowOwner->m_pShadow = NULL;
 }
 
 /// @unimplemented
@@ -3271,7 +3358,7 @@ inline void CUIFShadow::InitShadow()
 
 inline void CUIFShadow::AdjustWindowPos()
 {
-    HWND hwndOwner = *m_pShadowOrToolTipOwner;
+    HWND hwndOwner = *m_pShadowOwner;
     if (!::IsWindow(m_hWnd))
         return;
 
@@ -3324,7 +3411,7 @@ inline STDMETHODIMP_(LRESULT)
 CUIFShadow::OnWindowPosChanging(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM 
lParam)
 {
     WINDOWPOS *wp = (WINDOWPOS *)lParam;
-    wp->hwndInsertAfter = *m_pShadowOrToolTipOwner;
+    wp->hwndInsertAfter = *m_pShadowOwner;
     return ::DefWindowProc(hWnd, Msg, wParam, lParam);
 }
 
@@ -3369,7 +3456,7 @@ inline
 CUIFToolTip::CUIFToolTip(HINSTANCE hInst, DWORD style, CUIFWindow 
*pToolTipOwner)
     : CUIFWindow(hInst, style)
 {
-    m_pShadowOrToolTipOwner = pToolTipOwner;
+    m_pToolTipOwner = pToolTipOwner;
     m_rcToolTipMargin.left = 2;
     m_rcToolTipMargin.top = 2;
     m_rcToolTipMargin.right = 2;
@@ -3390,8 +3477,8 @@ CUIFToolTip::CUIFToolTip(HINSTANCE hInst, DWORD style, 
CUIFWindow *pToolTipOwner
 inline
 CUIFToolTip::~CUIFToolTip()
 {
-    if (m_pShadowOrToolTipOwner)
-        m_pShadowOrToolTipOwner->m_pToolTip = NULL;
+    if (m_pToolTipOwner)
+        m_pToolTipOwner->m_pToolTip = NULL;
     if (m_pszToolTipText)
         delete[] m_pszToolTipText;
 }
@@ -3455,8 +3542,8 @@ CUIFToolTip::GetTipTextColor()
 inline CUIFObject*
 CUIFToolTip::FindObject(HWND hWnd, POINT pt)
 {
-    if (hWnd == *m_pShadowOrToolTipOwner)
-        return m_pShadowOrToolTipOwner->ObjectFromPoint(pt);
+    if (hWnd == *m_pToolTipOwner)
+        return m_pToolTipOwner->ObjectFromPoint(pt);
     return NULL;
 }
 
@@ -3733,9 +3820,9 @@ inline STDMETHODIMP_(void) CUIFToolTip::OnTimer(WPARAM 
wParam)
 inline
 CUIFButton::CUIFButton(
     CUIFObject *pParent,
-    DWORD dwUnknown3,
+    DWORD nObjectID,
     LPCRECT prc,
-    DWORD style) : CUIFObject(pParent, dwUnknown3, prc, style)
+    DWORD style) : CUIFObject(pParent, nObjectID, prc, style)
 {
     m_ButtonIcon.m_hIcon = NULL;
     m_ButtonIcon.m_hImageList = NULL;
@@ -4128,9 +4215,9 @@ inline void CUIFButton::SetText(LPCWSTR pszText)
 
 inline CUIFButton2::CUIFButton2(
     CUIFObject *pParent,
-    DWORD dwUnknown3,
+    DWORD nObjectID,
     LPCRECT prc,
-    DWORD style) : CUIFButton(pParent, dwUnknown3, prc, style)
+    DWORD style) : CUIFButton(pParent, nObjectID, prc, style)
 {
     m_iStateId = 0;
     m_iPartId = BP_PUSHBUTTON;
@@ -4422,9 +4509,9 @@ CUIFGripper::SetStyle(DWORD style)
 inline
 CUIFToolbarMenuButton::CUIFToolbarMenuButton(
     CUIFToolbarButton *pParent,
-    DWORD dwUnknown3,
+    DWORD nObjectID,
     LPCRECT prc,
-    DWORD style) : CUIFButton2(pParent, dwUnknown3, prc, style)
+    DWORD style) : CUIFButton2(pParent, nObjectID, prc, style)
 {
     m_pToolbarButton = pParent;
 
@@ -4432,7 +4519,7 @@ CUIFToolbarMenuButton::CUIFToolbarMenuButton(
                                OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
DEFAULT_QUALITY,
                                DEFAULT_PITCH | FF_DONTCARE, TEXT("Marlett"));
     SetFont(hFont);
-    SetText(L"u");
+    SetText(L"u"); // downward triangle
 }
 
 inline
@@ -4461,9 +4548,9 @@ CUIFToolbarMenuButton::OnSetCursor(UINT uMsg, LONG x, 
LONG y)
 inline
 CUIFToolbarButtonElement::CUIFToolbarButtonElement(
     CUIFToolbarButton *pParent,
-    DWORD dwUnknown3,
+    DWORD nObjectID,
     LPCRECT prc,
-    DWORD style) : CUIFButton2(pParent, dwUnknown3, prc, style)
+    DWORD style) : CUIFButton2(pParent, nObjectID, prc, style)
 {
     m_pToolbarButton = pParent;
 }
@@ -4497,11 +4584,11 @@ CUIFToolbarButtonElement::OnRButtonUp(LONG x, LONG y)
 
 inline CUIFToolbarButton::CUIFToolbarButton(
     CUIFObject *pParent,
-    DWORD dwUnknown3,
+    DWORD nObjectID,
     LPCRECT prc,
     DWORD style,
     DWORD dwToolbarButtonFlags,
-    LPCWSTR pszUnknownText) : CUIFObject(pParent, dwUnknown3, prc, style)
+    LPCWSTR pszUnknownText) : CUIFObject(pParent, nObjectID, prc, style)
 {
     m_dwToolbarButtonFlags = dwToolbarButtonFlags;
     m_pszUnknownText = pszUnknownText;
@@ -4523,7 +4610,7 @@ inline BOOL CUIFToolbarButton::Init()
         style |= 0x10;
     if (m_dwToolbarButtonFlags & 0x80000)
         style |= UIF_BUTTON_VERTICAL;
-    m_pToolbarButtonElement = new(cicNoThrow) CUIFToolbarButtonElement(this, 
m_dwUnknown3, &rc1, style);
+    m_pToolbarButtonElement = new(cicNoThrow) CUIFToolbarButtonElement(this, 
m_nObjectID, &rc1, style);
     if (!m_pToolbarButtonElement)
         return FALSE;
 
@@ -4837,3 +4924,536 @@ CUIFWndFrame::OnSetCursor(UINT uMsg, LONG x, LONG y)
     ::SetCursor(hCursor);
     return TRUE;
 }
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline
+CUIFBalloonButton::CUIFBalloonButton(
+    CUIFObject *pParent,
+    DWORD nObjectID,
+    LPCRECT prc,
+    DWORD style) : CUIFButton(pParent, nObjectID, prc, style)
+{
+    m_nCommandID = 0;
+}
+
+inline STDMETHODIMP_(void)
+CUIFBalloonButton::OnPaint(HDC hDC)
+{
+    RECT rc = m_rc;
+    ::OffsetRect(&rc, -rc.left, -rc.top);
+
+    HDC hMemDC = ::CreateCompatibleDC(hDC);
+    HBITMAP hbmMem = ::CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
+    HGDIOBJ hbmOld = ::SelectObject(hMemDC, hbmMem);
+
+    BOOL bPressed;
+    COLORREF rgbShadow, rgbBorder;
+    if (m_uButtonStatus == 1)
+    {
+        bPressed = TRUE;
+        rgbShadow = ::GetSysColor(COLOR_BTNSHADOW);
+        rgbBorder = ::GetSysColor(COLOR_BTNHIGHLIGHT);
+    }
+    else
+    {
+        bPressed = FALSE;
+        if (m_uButtonStatus < 4)
+        {
+            rgbShadow = ::GetSysColor(COLOR_BTNHIGHLIGHT);
+            rgbBorder = ::GetSysColor(COLOR_BTNSHADOW);
+        }
+        else
+        {
+            rgbShadow = ::GetSysColor(COLOR_INFOBK);
+            rgbBorder = ::GetSysColor(COLOR_INFOBK);
+        }
+    }
+
+    COLORREF rgbInfoBk = ::GetSysColor(COLOR_INFOBK);
+    HBRUSH hbrBack = ::CreateSolidBrush(rgbInfoBk);
+    ::FillRect(hMemDC, &rc, hbrBack);
+    ::DeleteObject(hbrBack);
+
+    DrawTextProc(hMemDC, &rc, bPressed);
+
+    HBRUSH hNullBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
+    HGDIOBJ hbrOld = ::SelectObject(hMemDC, hNullBrush);
+
+    HPEN hPen = ::CreatePen(PS_SOLID, 0, rgbShadow);
+    HGDIOBJ hPenOld = ::SelectObject(hMemDC, hPen);
+    ::RoundRect(hMemDC, rc.left, rc.top, rc.right - 1, rc.bottom - 1, 6, 6);
+    ::SelectObject(hMemDC, hPenOld);
+    ::DeleteObject(hPen);
+
+    hPen = ::CreatePen(PS_SOLID, 0, rgbBorder);
+    hPenOld = ::SelectObject(hMemDC, hPen);
+    ::RoundRect(hMemDC, rc.left + 1, rc.top + 1, rc.right, rc.bottom, 6, 6);
+    ::SelectObject(hMemDC, hPenOld);
+    ::DeleteObject(hPen);
+
+    hPen = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNFACE));
+    hPenOld = ::SelectObject(hMemDC, hPen);
+    ::RoundRect(hMemDC, rc.left + 1, rc.top + 1, rc.right - 1, rc.bottom - 1, 
6, 6);
+    ::SelectObject(hMemDC, hPenOld);
+    ::DeleteObject(hPen);
+
+    ::SelectObject(hMemDC, hbrOld);
+    ::BitBlt(hDC, m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - 
m_rc.top,
+             hMemDC, rc.left, rc.top, SRCCOPY);
+    ::SelectObject(hMemDC, hbmOld);
+    ::DeleteObject(hbmMem);
+    ::DeleteDC(hMemDC);
+}
+
+inline void
+CUIFBalloonButton::DrawTextProc(HDC hDC, LPCRECT prc, BOOL bPressed)
+{
+    if (!m_pszButtonText)
+        return;
+
+    UINT uFlags = DT_SINGLELINE;
+
+    if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_CENTER)
+        uFlags |= DT_CENTER;
+    else if ((m_style & UIF_BUTTON_H_ALIGN_MASK) == UIF_BUTTON_H_ALIGN_RIGHT)
+        uFlags |= DT_RIGHT;
+
+    if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_MIDDLE)
+        uFlags |= DT_VCENTER;
+    else if ((m_style & UIF_BUTTON_V_ALIGN_MASK) == UIF_BUTTON_V_ALIGN_BOTTOM)
+        uFlags |= DT_BOTTOM;
+
+    COLORREF rgbOldColor = ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT));
+    INT nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
+
+    RECT rc = *prc;
+    if (bPressed)
+        ::OffsetRect(&rc, 1, 1);
+
+    HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
+    ::DrawTextW(hDC, m_pszButtonText, -1, &rc, uFlags);
+    ::SelectObject(hDC, hFontOld);
+
+    ::SetBkMode(hDC, nOldBkMode);
+    ::SetTextColor(hDC, rgbOldColor);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline
+CUIFBalloonWindow::CUIFBalloonWindow(HINSTANCE hInst, DWORD style) : 
CUIFWindow(hInst, style)
+{
+    m_dwUnknown6 = -1;
+    m_nActionID = -1;
+    m_hRgn = NULL;
+    m_pszBalloonText = NULL;
+    m_bHasBkColor = FALSE;
+    m_bHasTextColor = FALSE;
+    m_rgbBkColor = 0;
+    m_rgbTextColor = 0;
+    m_ptTarget.x = 0;
+    m_ptTarget.y = 0;
+    m_rcExclude.left = 0;
+    m_rcExclude.right = 0;
+    m_rcExclude.top = 0;
+    m_rcExclude.bottom = 0;
+    m_dwUnknown7 = 0;
+    m_nBalloonType = 0;
+    m_dwUnknown8[0] = 0;
+    m_dwUnknown8[1] = 0;
+    m_ptBalloon.x = 0;
+    m_ptBalloon.y = 0;
+    m_cButtons = 0;
+    m_hwndNotif = NULL;
+    m_uNotifMsg = 0;
+    m_rcMargin.left = 8;
+    m_rcMargin.top = 8;
+    m_rcMargin.right = 8;
+    m_rcMargin.bottom = 8;
+}
+
+inline
+CUIFBalloonWindow::~CUIFBalloonWindow()
+{
+    if (m_pszBalloonText)
+    {
+        delete[] m_pszBalloonText;
+        m_pszBalloonText = NULL;
+    }
+}
+
+inline STDMETHODIMP_(void)
+CUIFBalloonWindow::Initialize()
+{
+    CUIFWindow::Initialize();
+
+    if ((m_style & UIF_BALLOON_WINDOW_TYPE_MASK) == UIF_BALLOON_WINDOW_OK)
+    {
+        AddButton(IDOK);
+    }
+    else if ((m_style & UIF_BALLOON_WINDOW_TYPE_MASK) == 
UIF_BALLOON_WINDOW_YESNO)
+    {
+        AddButton(IDYES);
+        AddButton(IDNO);
+    }
+}
+
+inline STDMETHODIMP_(LPCTSTR)
+CUIFBalloonWindow::GetClassName()
+{
+    return TEXT("MSIME_PopupMessage");
+}
+
+inline STDMETHODIMP_(LPCTSTR)
+CUIFBalloonWindow::GetWndTitle()
+{
+    return TEXT("MSIME_PopupMessage");
+}
+
+inline STDMETHODIMP_(void)
+CUIFBalloonWindow::OnCreate(HWND hWnd)
+{
+    m_nActionID = -1;
+    AdjustPos();
+}
+
+inline STDMETHODIMP_(void)
+CUIFBalloonWindow::OnDestroy(HWND hWnd)
+{
+    SendNotification(m_nActionID);
+    DoneWindowRegion();
+}
+
+inline STDMETHODIMP_(void)
+CUIFBalloonWindow::OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+    CUIFBalloonButton *pButton = NULL;
+
+    switch (wParam)
+    {
+        case VK_RETURN:
+            pButton = (CUIFBalloonButton *)FindUIObject(0);
+            break;
+        case VK_ESCAPE:
+            m_nActionID = -1;
+            ::DestroyWindow(m_hWnd);
+            return;
+        case TEXT('Y'):
+            pButton = FindButton(IDYES);
+            break;
+        case TEXT('N'):
+            pButton = FindButton(IDNO);
+            break;
+    }
+
+    if (!pButton)
+        return;
+
+    m_nActionID = pButton->m_nCommandID;
+    ::DestroyWindow(m_hWnd);
+}
+
+inline STDMETHODIMP_(LRESULT)
+CUIFBalloonWindow::OnObjectNotify(CUIFObject *pObject, WPARAM wParam, LPARAM 
lParam)
+{
+    CUIFBalloonButton *pButton = (CUIFBalloonButton *)pObject;
+    m_nActionID = pButton->m_nCommandID;
+    ::DestroyWindow(m_hWnd);
+    return 0;
+}
+
+inline STDMETHODIMP_(void)
+CUIFBalloonWindow::OnPaint(HDC hDC)
+{
+    RECT rc;
+    GetRect(&rc);
+    PaintFrameProc(hDC, &rc);
+
+    switch (m_nBalloonType)
+    {
+        case 1:
+            rc.top += 16;
+            break;
+        case 2:
+            rc.right -= 16;
+            break;
+        case 3:
+            rc.left += 16;
+            break;
+        default:
+            rc.bottom -= 16;
+            break;
+    }
+
+    RECT rcMargin;
+    GetMargin(&rcMargin);
+
+    rc.left += rcMargin.left;
+    rc.top += rcMargin.top;
+    rc.right -= rcMargin.right;
+    rc.bottom -= rcMargin.bottom;
+
+    PaintMessageProc(hDC, &rc, m_pszBalloonText);
+}
+
+inline void
+CUIFBalloonWindow::AddButton(UINT nCommandId)
+{
+    RECT rc = { 0, 0, 0, 0 };
+    if (!((IDOK <= nCommandId) && (nCommandId <= IDNO)))
+        return;
+
+    CUIFBalloonButton *pButton = new(cicNoThrow) CUIFBalloonButton(this, 
m_cButtons, &rc, 5);
+    if (!pButton)
+        return;
+
+    pButton->Initialize();
+    pButton->m_nCommandID = nCommandId;
+
+    LPCWSTR pszText; // FIXME: Use resource strings
+    switch (nCommandId)
+    {
+        case IDOK:
+            pszText = L"OK";
+            break;
+        case IDCANCEL:
+            pszText = L"Cancel";
+            break;
+        case IDABORT:
+            pszText = L"&Abort";
+            break;
+        case IDRETRY:
+            pszText = L"&Retry";
+            break;
+        case IDIGNORE:
+            pszText = L"&Ignore";
+            break;
+        case IDYES:
+            pszText = L"&Yes";
+            break;
+        default:
+            pszText = L"&No";
+            break;
+    }
+
+    pButton->SetText(pszText);
+
+    AddUIObj(pButton);
+    ++m_cButtons;
+}
+
+/// @unimplemented
+inline void
+CUIFBalloonWindow::AdjustPos()
+{
+    //FIXME
+}
+
+/// @unimplemented
+inline HRGN
+CUIFBalloonWindow::CreateRegion(LPCRECT prc)
+{
+    //FIXME
+    return NULL;
+}
+
+inline void
+CUIFBalloonWindow::DoneWindowRegion()
+{
+    if (m_hRgn)
+    {
+        ::SetWindowRgn(m_hWnd, NULL, TRUE);
+        ::DeleteObject(m_hRgn);
+        m_hRgn = NULL;
+    }
+}
+
+inline CUIFBalloonButton *
+CUIFBalloonWindow::FindButton(UINT nCommandID)
+{
+    for (UINT iButton = 0; iButton < m_cButtons; ++iButton)
+    {
+        CUIFBalloonButton *pButton = (CUIFBalloonButton 
*)FindUIObject(iButton);
+        if (pButton && (pButton->m_nCommandID == nCommandID))
+            return pButton;
+    }
+    return NULL;
+}
+
+inline CUIFObject *
+CUIFBalloonWindow::FindUIObject(UINT nObjectID)
+{
+    for (size_t iItem = 0; iItem < m_ObjectArray.size(); ++iItem)
+    {
+        CUIFObject *pObject = m_ObjectArray[iItem];
+        if (pObject->m_nObjectID == nObjectID)
+            return pObject;
+    }
+    return NULL;
+}
+
+inline COLORREF
+CUIFBalloonWindow::GetBalloonBkColor()
+{
+    if (m_bHasBkColor )
+        return m_rgbBkColor;
+    else
+        return ::GetSysColor(COLOR_INFOBK);
+}
+
+inline COLORREF
+CUIFBalloonWindow::GetBalloonTextColor()
+{
+    if (m_bHasTextColor)
+        return m_rgbTextColor;
+    else
+        return ::GetSysColor(COLOR_INFOTEXT);
+}
+
+inline void
+CUIFBalloonWindow::GetButtonSize(LPSIZE pSize)
+{
+    HDC hDisplayDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
+
+    TEXTMETRIC tm;
+    HGDIOBJ hFontOld = ::SelectObject(hDisplayDC, m_hFont);
+    ::GetTextMetrics(hDisplayDC, &tm);
+    ::SelectObject(hDisplayDC, hFontOld);
+    ::DeleteDC(hDisplayDC);
+
+    pSize->cx = 16 * tm.tmAveCharWidth;
+    pSize->cy = tm.tmHeight + 10;
+}
+
+inline void
+CUIFBalloonWindow::GetMargin(LPRECT prcMargin)
+{
+    if (prcMargin)
+        *prcMargin = m_rcMargin;
+}
+
+inline void
+CUIFBalloonWindow::SetExcludeRect(LPCRECT prcExclude)
+{
+    m_rcExclude = *prcExclude;
+    AdjustPos();
+}
+
+inline void
+CUIFBalloonWindow::SetTargetPos(POINT ptTarget)
+{
+    m_ptTarget = ptTarget;
+    AdjustPos();
+}
+
+inline void
+CUIFBalloonWindow::SetText(LPCWSTR pszText)
+{
+    if (m_pszBalloonText)
+    {
+        delete[] m_pszBalloonText;
+        m_pszBalloonText = NULL;
+    }
+
+    if (pszText == NULL)
+        pszText = L"";
+
+    size_t cch = wcslen(pszText);
+    m_pszBalloonText = new(cicNoThrow) WCHAR[cch + 1];
+    if (m_pszBalloonText)
+        lstrcpynW(m_pszBalloonText, pszText, cch + 1);
+
+    AdjustPos();
+}
+
+inline void
+CUIFBalloonWindow::InitWindowRegion()
+{
+    RECT rc;
+    GetRect(&rc);
+    m_hRgn = CreateRegion(&rc);
+    if (m_hRgn)
+        ::SetWindowRgn(m_hWnd, m_hRgn, TRUE);
+}
+
+inline void
+CUIFBalloonWindow::LayoutObject()
+{
+    SIZE size;
+    GetButtonSize(&size);
+
+    RECT rc;
+    GetRect(&rc);
+
+    switch (m_nBalloonType)
+    {
+        case 1:
+            rc.top += 16;
+            break;
+        case 2:
+            rc.right -= 16;
+            break;
+        case 3:
+            rc.left += 16;
+            break;
+        default:
+            rc.bottom -= 16;
+            break;
+    }
+
+    RECT rcMargin;
+    GetMargin(&rcMargin);
+    rc.left += rcMargin.left;
+    rc.top += rcMargin.top;
+    rc.right -= rcMargin.right;
+    rc.bottom -= rcMargin.bottom;
+
+    LONG xLeft = (rc.left + rc.right - size.cx * (((m_cButtons - 1) / 2) - 
m_cButtons)) / 2;
+    for (UINT iButton = 0; iButton < m_cButtons; ++iButton)
+    {
+        CUIFObject *UIObject = FindUIObject(iButton);
+        if (!UIObject)
+            continue;
+
+        rcMargin.left = xLeft + iButton * (size.cx * 3 / 2);
+        rcMargin.top = rc.bottom - size.cy;
+        rcMargin.right = rcMargin.left + size.cx;
+        rcMargin.bottom = rc.bottom;
+
+        UIObject->SetRect(&rcMargin);
+        UIObject->Show(TRUE);
+    }
+}
+
+inline void
+CUIFBalloonWindow::PaintFrameProc(HDC hDC, LPCRECT prc)
+{
+    HRGN hRgn = CreateRegion(prc);
+    HBRUSH hbrBack = ::CreateSolidBrush(GetBalloonBkColor());
+    HBRUSH hbrFrame = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOWFRAME));
+    ::FillRgn(hDC, hRgn, hbrBack);
+    ::FrameRgn(hDC, hRgn, hbrFrame, 1, 1);
+    ::DeleteObject(hbrBack);
+    ::DeleteObject(hbrFrame);
+    ::DeleteObject(hRgn);
+}
+
+inline void
+CUIFBalloonWindow::PaintMessageProc(HDC hDC, LPRECT prc, LPCWSTR pszText)
+{
+    HGDIOBJ hFontOld = ::SelectObject(hDC, m_hFont);
+    COLORREF rgbOldColor = ::SetTextColor(hDC, GetBalloonTextColor());
+    INT nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
+    ::DrawTextW(hDC, pszText, -1, prc, DT_WORDBREAK);
+    ::SelectObject(hDC, hFontOld);
+    ::SetTextColor(hDC, rgbOldColor);
+    ::SetBkMode(hDC, nOldBkMode);
+}
+
+inline void
+CUIFBalloonWindow::SendNotification(WPARAM wParam)
+{
+    if (m_hwndNotif)
+        ::PostMessage(m_hwndNotif, m_uNotifMsg, wParam, 0);
+}

Reply via email to