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

commit bbca71c4a5604f4919d792c4b414ae84a05c4594
Author:     David Quintana <[email protected]>
AuthorDate: Fri Jan 19 16:39:46 2018 +0100
Commit:     David Quintana <[email protected]>
CommitDate: Tue Jan 23 22:13:01 2018 +0100

    [EXPLORER] Implement rudimentary uVersion management, and notification 
balloons.
    - uVersion will only be truly useful when Vista+'s V4 style notification 
icons are implemented.
    - Balloon notifications do not yet support queuing and auto-closing.
    - Force the notification icon tooltips to always show even if the taskbar 
isn't foreground.
    [ROSCTRLS.H] Implement CTooltips class which manages a comctl32 tooltips 
window.
---
 base/shell/explorer/trayntfy.cpp | 217 +++++++++++++++++++++++++++++++++----
 sdk/include/reactos/rosctrls.h   | 225 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 421 insertions(+), 21 deletions(-)

diff --git a/base/shell/explorer/trayntfy.cpp b/base/shell/explorer/trayntfy.cpp
index 1864e33e96..7e13d9f131 100644
--- a/base/shell/explorer/trayntfy.cpp
+++ b/base/shell/explorer/trayntfy.cpp
@@ -34,6 +34,12 @@ typedef struct _SYS_PAGER_COPY_DATA
     NOTIFYICONDATA  nicon_data;
 } SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA;
 
+struct InternalIconData : NOTIFYICONDATA
+{
+    // Must keep a separate copy since the original is unioned with uTimeout.
+    UINT uVersionCopy;
+};
+
 
 struct IconWatcherData
 {
@@ -310,15 +316,22 @@ private:
 
 
 class CNotifyToolbar :
-    public CWindowImplBaseT< CToolbar<NOTIFYICONDATA>, CControlWinTraits >
+    public CWindowImplBaseT< CToolbar<InternalIconData>, CControlWinTraits >
 {
     HIMAGELIST m_ImageList;
     int m_VisibleButtonCount;
 
+    HWND m_BalloonsParent;
+    CTooltips * m_Balloons;
+    InternalIconData * m_currentTooltip;
+
 public:
     CNotifyToolbar() :
         m_ImageList(NULL),
-        m_VisibleButtonCount(0)
+        m_VisibleButtonCount(0),
+        m_BalloonsParent(NULL),
+        m_Balloons(NULL),
+        m_currentTooltip(NULL)
     {
     }
 
@@ -331,15 +344,13 @@ public:
         return m_VisibleButtonCount;
     }
 
-    int FindItem(IN HWND hWnd, IN UINT uID, NOTIFYICONDATA ** pdata)
+    int FindItem(IN HWND hWnd, IN UINT uID, InternalIconData ** pdata)
     {
         int count = GetButtonCount();
 
         for (int i = 0; i < count; i++)
         {
-            NOTIFYICONDATA * data;
-
-            data = GetItemData(i);
+            InternalIconData * data = GetItemData(i);
 
             if (data->hWnd == hWnd &&
                 data->uID == uID)
@@ -358,7 +369,7 @@ public:
         int count = GetButtonCount();
         for (int i = 0; i < count; i++)
         {
-            NOTIFYICONDATA * data = GetItemData(i);
+            InternalIconData * data = GetItemData(i);
             if (data->hIcon == handle)
             {
                 TBBUTTON btn;
@@ -373,7 +384,7 @@ public:
     BOOL AddButton(IN CONST NOTIFYICONDATA *iconData)
     {
         TBBUTTON tbBtn;
-        NOTIFYICONDATA * notifyItem;
+        InternalIconData * notifyItem;
         WCHAR text[] = L"";
 
         TRACE("Adding icon %d from hWnd %08x flags%s%s state%s%s", 
@@ -390,7 +401,7 @@ public:
             return FALSE;
         }
 
-        notifyItem = new NOTIFYICONDATA();
+        notifyItem = new InternalIconData();
         ZeroMemory(notifyItem, sizeof(*notifyItem));
 
         notifyItem->hWnd = iconData->hWnd;
@@ -437,6 +448,16 @@ public:
             StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip), 
iconData->szTip);
         }
 
+        if (iconData->uFlags & NIF_INFO)
+        {
+            // NOTE: In Vista+, the uTimeout value is disregarded, and the 
accessibility settings are used always.
+            StrNCpy(notifyItem->szInfo, iconData->szInfo, 
_countof(notifyItem->szInfo));
+            StrNCpy(notifyItem->szInfoTitle, iconData->szInfoTitle, 
_countof(notifyItem->szInfo));
+            notifyItem->dwInfoFlags = iconData->dwInfoFlags;
+            notifyItem->uTimeout = iconData->uTimeout;
+
+        }
+
         m_VisibleButtonCount++;
         if (notifyItem->dwState & NIS_HIDDEN)
         {
@@ -444,17 +465,45 @@ public:
             m_VisibleButtonCount--;
         }
 
-        /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
+        /* TODO: support VERSION_4 (NIF_GUID, NIF_REALTIME, NIF_SHOWTIP) */
 
         CToolbar::AddButton(&tbBtn);
         SetButtonSize(GetSystemMetrics(SM_CXSMICON), 
GetSystemMetrics(SM_CYSMICON));
 
+        if (iconData->uFlags & NIF_INFO)
+        {
+            UpdateBalloonTip(notifyItem);
+        }
+
+        return TRUE;
+    }
+
+    BOOL SwitchVersion(IN CONST NOTIFYICONDATA *iconData)
+    {
+        InternalIconData * notifyItem;
+        int index = FindItem(iconData->hWnd, iconData->uID, &notifyItem);
+        if (index < 0)
+        {
+            WARN("Icon %d from hWnd %08x DOES NOT EXIST!", iconData->uID, 
iconData->hWnd);
+            return FALSE;
+        }
+
+        if (iconData->uVersion != 0 && iconData->uVersion != 
NOTIFYICON_VERSION)
+        {
+            WARN("Tried to set the version of icon %d from hWnd %08x, to an 
unknown value %d. Vista+ program?", iconData->uID, iconData->hWnd, 
iconData->uVersion);
+            return FALSE;
+        }
+
+        // We can not store the version in the uVersion field, because it's 
union'd with uTimeout,
+        // which we also need to keep track of.
+        notifyItem->uVersionCopy = iconData->uVersion;
+
         return TRUE;
     }
 
     BOOL UpdateButton(IN CONST NOTIFYICONDATA *iconData)
     {
-        NOTIFYICONDATA * notifyItem;
+        InternalIconData * notifyItem;
         TBBUTTONINFO tbbi = { 0 };
 
         TRACE("Updating icon %d from hWnd %08x flags%s%s state%s%s",
@@ -536,16 +585,30 @@ public:
             StringCchCopy(notifyItem->szTip, _countof(notifyItem->szTip), 
iconData->szTip);
         }
 
-        /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */
+        if (iconData->uFlags & NIF_INFO)
+        {
+            // NOTE: In Vista+, the uTimeout value is disregarded, and the 
accessibility settings are used always.
+            StrNCpy(notifyItem->szInfo, iconData->szInfo, 
_countof(notifyItem->szInfo));
+            StrNCpy(notifyItem->szInfoTitle, iconData->szInfoTitle, 
_countof(notifyItem->szInfo));
+            notifyItem->dwInfoFlags = iconData->dwInfoFlags;
+            notifyItem->uTimeout = iconData->uTimeout;
+        }
+
+        /* TODO: support VERSION_4 (NIF_GUID, NIF_REALTIME, NIF_SHOWTIP) */
 
         SetButtonInfo(index, &tbbi);
 
+        if (iconData->uFlags & NIF_INFO)
+        {
+            UpdateBalloonTip(notifyItem);
+        }
+
         return TRUE;
     }
 
     BOOL RemoveButton(IN CONST NOTIFYICONDATA *iconData)
     {
-        NOTIFYICONDATA * notifyItem;
+        InternalIconData * notifyItem;
 
         TRACE("Removing icon %d from hWnd %08x", iconData->uID, 
iconData->hWnd);
 
@@ -587,16 +650,86 @@ public:
             }
         }
 
-        delete notifyItem;
+        HideBalloonTip(notifyItem);
+
         DeleteButton(index);
 
+        delete notifyItem;
+
         return TRUE;
     }
 
+    void UpdateBalloonTip(InternalIconData* notifyItem)
+    {
+        size_t len = 0;
+        if (SUCCEEDED(StringCchLength(notifyItem->szInfo, 
_countof(notifyItem->szInfo), &len)) && len > 0)
+        {
+            ShowBalloonTip(notifyItem);
+        }
+        else
+        {
+            HideBalloonTip(notifyItem);
+        }
+    }
+
+    static WPARAM GetTitleIcon(DWORD dwFlags, HICON hIcon)
+    {
+        if (dwFlags & NIIF_USER)
+            return reinterpret_cast<WPARAM>(hIcon);
+
+        return dwFlags & 3;
+    }
+
+    BOOL ShowBalloonTip(IN OUT InternalIconData *notifyItem)
+    {
+        DbgPrint("ShowBalloonTip called for flags=%x text=%ws; title=%ws", 
notifyItem->dwInfoFlags, notifyItem->szInfo, notifyItem->szInfoTitle);
+
+        // TODO: Queueing -> NIF_REALTIME? (Vista+)
+        // TODO: NIIF_NOSOUND, Vista+ flags
+        
+        const WPARAM icon = GetTitleIcon(notifyItem->dwInfoFlags, 
notifyItem->hIcon);
+        BOOL ret = m_Balloons->SetTitle(notifyItem->szInfoTitle, icon);
+        if (!ret)
+            DbgPrint("SetTitle failed, GetLastError=%d", GetLastError());
+
+        const int index = FindItem(notifyItem->hWnd, notifyItem->uID, NULL);
+        RECT rc;
+        GetItemRect(index, &rc);
+        ClientToScreen(&rc); // I have no idea why this is needed! >_<
+        WORD x = (rc.left + rc.right) / 2;
+        WORD y = (rc.top + rc.bottom) / 2;
+        DbgPrint("ClientToScreen returned (%d, %d, %d, %d) x=%d, y=%d",
+            rc.left, rc.top,
+            rc.right, rc.bottom, x, y);
+        m_Balloons->TrackPosition(x, y);
+        m_Balloons->UpdateTipText(m_BalloonsParent, 
reinterpret_cast<LPARAM>(m_hWnd), notifyItem->szInfo);
+        m_Balloons->TrackActivate(m_BalloonsParent, 
reinterpret_cast<LPARAM>(m_hWnd));
+        m_currentTooltip = notifyItem;
+
+        return TRUE;
+    }
+
+    VOID HideBalloonTip(IN OUT InternalIconData *notifyItem)
+    {
+        DbgPrint("HideBalloonTip called");
+
+        if (m_currentTooltip == notifyItem)
+        {
+            // Prevent Re-entry
+            m_currentTooltip = NULL;
+            m_Balloons->TrackDeactivate();
+        }
+    }
+
+    VOID HideCurrentBalloon()
+    {
+        if (m_currentTooltip != NULL)
+            HideBalloonTip(m_currentTooltip);
+    }
+
     VOID GetTooltipText(int index, LPTSTR szTip, DWORD cchTip)
     {
-        NOTIFYICONDATA * notifyItem;
-        notifyItem = GetItemData(index);
+        InternalIconData * notifyItem = GetItemData(index);
 
         if (notifyItem)
         {
@@ -626,7 +759,7 @@ public:
         int count = GetButtonCount();
         for (int i = 0; i < count; i++)
         {
-            NOTIFYICONDATA * data = GetItemData(i);
+            InternalIconData * data = GetItemData(i);
             BOOL hasSharedIcon = data->dwState & NIS_SHAREDICON;
             INT iIcon = hasSharedIcon ? FindExistingSharedIcon(data->hIcon) : 
-1;
             if (iIcon < 0)
@@ -659,7 +792,7 @@ private:
             L"WM_XBUTTONDBLCLK"
         };
 
-        NOTIFYICONDATA * notifyItem = GetItemData(wIndex);
+        InternalIconData * notifyItem = GetItemData(wIndex);
 
         if (!::IsWindow(notifyItem->hWnd))
         {
@@ -770,15 +903,17 @@ private:
         return 0;
     }
 
-
 public:
     BEGIN_MSG_MAP(CNotifyToolbar)
         MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseEvent)
         NOTIFY_CODE_HANDLER(TTN_SHOW, OnTooltipShow)
     END_MSG_MAP()
 
-    void Initialize(HWND hWndParent)
+    void Initialize(HWND hWndParent, CTooltips * tooltips)
     {
+        m_BalloonsParent = hWndParent;
+        m_Balloons = tooltips;
+
         DWORD styles =
             WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
             TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_WRAPABLE | 
TBSTYLE_TRANSPARENT |
@@ -786,6 +921,13 @@ public:
 
         SubclassWindow(CToolbar::Create(hWndParent, styles));
 
+        // Force the toolbar tooltips window to always show tooltips even if 
not foreground
+        HWND tooltipsWnd = (HWND)SendMessageW(TB_GETTOOLTIPS);
+        if (tooltipsWnd)
+        {
+            ::SetWindowLong(tooltipsWnd, GWL_STYLE, 
::GetWindowLong(tooltipsWnd, GWL_STYLE) | TTS_ALWAYSTIP);
+        }
+
         SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
 
         m_ImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), 
GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 0, 1000);        
@@ -810,6 +952,8 @@ class CSysPagerWnd :
 {
     CNotifyToolbar Toolbar;
 
+    CTooltips m_Balloons;
+
 public:
     CSysPagerWnd() {}
     virtual ~CSysPagerWnd() {}
@@ -839,9 +983,27 @@ public:
 
     LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
     {
-        Toolbar.Initialize(m_hWnd);
+        Toolbar.Initialize(m_hWnd, &m_Balloons);
         CIconWatcher::Initialize(m_hWnd);
 
+        HWND hWndTop = GetAncestor(m_hWnd, GA_ROOT);
+
+        m_Balloons.Create(hWndTop, TTS_NOPREFIX | TTS_BALLOON | TTS_CLOSE);
+        
+        TOOLINFOW ti = { 0 };
+        ti.cbSize = TTTOOLINFOW_V1_SIZE;
+        ti.uFlags = TTF_TRACK | TTF_IDISHWND;
+        ti.uId = reinterpret_cast<UINT_PTR>(Toolbar.m_hWnd);
+        ti.hwnd = m_hWnd;
+        ti.lpszText = NULL;
+        ti.lParam = NULL;
+
+        BOOL ret = m_Balloons.AddTool(&ti);
+        if (!ret)
+        {
+            DbgPrint("AddTool failed, LastError=%d (probably meaningless 
unless non-zero)", GetLastError());
+        }
+
         // Explicitly request running applications to re-register their 
systray icons
         ::SendNotifyMessageW(HWND_BROADCAST,
                              RegisterWindowMessageW(L"TaskbarCreated"),
@@ -890,6 +1052,11 @@ public:
                     (void)RemoveIconFromWatcher(iconData);
                 }
                 break;
+            case NIM_SETFOCUS:
+                Toolbar.SetFocus();
+                ret = TRUE;
+            case NIM_SETVERSION:
+                ret = Toolbar.SwitchVersion(iconData);
             default:
                 TRACE("NotifyIconCmd received with unknown code %d.\n", 
data->notify_code);
                 return FALSE;
@@ -996,6 +1163,13 @@ public:
         return 0;
     }
 
+    LRESULT OnBalloonPop(UINT uCode, LPNMHDR hdr , BOOL& bHandled)
+    {
+        Toolbar.HideCurrentBalloon();
+        bHandled = TRUE;
+        return 0;
+    }
+
     void ResizeImagelist()
     {
         Toolbar.ResizeImagelist();
@@ -1009,6 +1183,7 @@ public:
         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
         MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu)
+        NOTIFY_CODE_HANDLER(TTN_POP, OnBalloonPop)
         NOTIFY_CODE_HANDLER(TBN_GETINFOTIPW, OnGetInfoTip)
         NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
     END_MSG_MAP()
diff --git a/sdk/include/reactos/rosctrls.h b/sdk/include/reactos/rosctrls.h
index a5976416d8..f332aca915 100644
--- a/sdk/include/reactos/rosctrls.h
+++ b/sdk/include/reactos/rosctrls.h
@@ -581,3 +581,228 @@ public:
     }
 
 };
+
+class CTooltips :
+    public CWindow
+{
+public: // Configuration methods
+
+    HWND Create(HWND hWndParent, DWORD dwStyles = WS_POPUP | TTS_NOPREFIX, 
DWORD dwExStyles = WS_EX_TOPMOST)
+    {
+        RECT r = { 0 };
+        return CWindow::Create(TOOLTIPS_CLASS, hWndParent, r, L"", dwStyles, 
dwExStyles);
+    }
+
+public: // Relay event
+
+    // Win7+: Can use GetMessageExtraInfo to provide the WPARAM value.
+    VOID RelayEvent(MSG * pMsg, WPARAM extraInfo = 0)
+    {
+        SendMessageW(TTM_RELAYEVENT, extraInfo, 
reinterpret_cast<LPARAM>(pMsg));
+    }
+
+public: // Helpers
+
+    INT GetToolCount()
+    {
+        return SendMessageW(TTM_GETTOOLCOUNT, 0, 0);
+    }
+
+    BOOL AddTool(IN CONST TTTOOLINFOW * pInfo)
+    {
+        return SendMessageW(TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(pInfo));
+    }
+
+    VOID DelTool(IN HWND hwndToolOwner, IN UINT uId)
+    {
+        TTTOOLINFOW info = { sizeof(TTTOOLINFOW), 0 };
+        info.hwnd = hwndToolOwner;
+        info.uId = uId;
+        SendMessageW(TTM_DELTOOL, 0, reinterpret_cast<LPARAM>(&info));
+    }
+
+    VOID NewToolRect(IN HWND hwndToolOwner, IN UINT uId, IN RECT rect)
+    {
+        TTTOOLINFOW info = { sizeof(TTTOOLINFOW), 0 };
+        info.hwnd = hwndToolOwner;
+        info.uId = uId;
+        info.rect = rect;
+        SendMessageW(TTM_NEWTOOLRECT, 0, reinterpret_cast<LPARAM>(&info));
+    }
+
+    BOOL GetToolInfo(IN HWND hwndToolOwner, IN UINT uId, IN OUT TTTOOLINFOW * 
pInfo)
+    {
+        pInfo->hwnd = hwndToolOwner;
+        pInfo->uId = uId;
+        return SendMessageW(TTM_GETTOOLINFO, 0, 
reinterpret_cast<LPARAM>(pInfo));
+    }
+
+    VOID SetToolInfo(IN CONST TTTOOLINFOW * pInfo)
+    {
+        SendMessageW(TTM_SETTOOLINFO, 0, reinterpret_cast<LPARAM>(pInfo));
+    }
+
+    BOOL HitTest(IN CONST TTHITTESTINFOW * pInfo)
+    {
+        return SendMessageW(TTM_HITTEST, 0, reinterpret_cast<LPARAM>(pInfo));
+    }
+
+    VOID GetText(IN HWND hwndToolOwner, IN UINT uId, OUT PWSTR pBuffer, IN 
DWORD cchBuffer)
+    {
+        TTTOOLINFOW info = { sizeof(TTTOOLINFOW), 0 };
+        info.hwnd = hwndToolOwner;
+        info.uId = uId;
+        info.lpszText = pBuffer;
+        SendMessageW(TTM_GETTEXT, cchBuffer, reinterpret_cast<LPARAM>(&info));
+    }
+
+    VOID UpdateTipText(IN HWND hwndToolOwner, IN UINT uId, IN PCWSTR szText, 
IN HINSTANCE hinstResourceOwner = NULL)
+    {
+        TTTOOLINFOW info = { sizeof(TTTOOLINFOW), 0 };
+        info.hwnd = hwndToolOwner;
+        info.uId = uId;
+        info.lpszText = const_cast<PWSTR>(szText);
+        info.hinst = hinstResourceOwner;
+        SendMessageW(TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
+    }
+
+    BOOL EnumTools(IN CONST TTTOOLINFOW * pInfo)
+    {
+        return SendMessageW(TTM_ENUMTOOLS, 0, reinterpret_cast<LPARAM>(pInfo));
+    }
+
+    BOOL GetCurrentTool(OUT OPTIONAL TTTOOLINFOW * pInfo = NULL)
+    {
+        return SendMessageW(TTM_GETCURRENTTOOL, 0, 
reinterpret_cast<LPARAM>(pInfo));
+    }
+
+    VOID GetTitle(TTGETTITLE * pTitleInfo)
+    {
+        SendMessageW(TTM_GETTITLE, 0, reinterpret_cast<LPARAM>(pTitleInfo));
+    }
+
+    BOOL SetTitle(PCWSTR szTitleText, WPARAM icon = 0)
+    {
+        return SendMessageW(TTM_SETTITLE, icon, 
reinterpret_cast<LPARAM>(szTitleText));
+    }
+
+    VOID TrackActivate(IN HWND hwndToolOwner, IN UINT uId)
+    {
+        TTTOOLINFOW info = { sizeof(TTTOOLINFOW), 0 };
+        info.hwnd = hwndToolOwner;
+        info.uId = uId;
+        SendMessageW(TTM_TRACKACTIVATE, TRUE, reinterpret_cast<LPARAM>(&info));
+    }
+
+    VOID TrackDeactivate()
+    {
+        SendMessageW(TTM_TRACKACTIVATE, FALSE, NULL);
+    }
+
+    VOID TrackPosition(IN WORD x, IN WORD y)
+    {
+        SendMessageW(TTM_TRACKPOSITION, 0, MAKELPARAM(x, y));
+    }
+
+    // Opens the tooltip
+    VOID Popup()
+    {
+        SendMessageW(TTM_POPUP);
+    }
+
+    // Closes the tooltip - Pressing the [X] for a TTF_CLOSE balloon is 
equivalent to calling this
+    VOID Pop()
+    {
+        SendMessageW(TTM_POP);
+    }
+
+    // Delay times for AUTOMATIC tooltips (they don't affect balloons)
+    INT GetDelayTime(UINT which)
+    {
+        return SendMessageW(TTM_GETDELAYTIME, which);
+    }
+
+    VOID SetDelayTime(UINT which, WORD time)
+    {
+        SendMessageW(TTM_SETDELAYTIME, which, MAKELPARAM(time, 0));
+    }
+
+    // Activates or deactivates the automatic tooltip display when hovering a 
control
+    VOID Activate(IN BOOL bActivate = TRUE)
+    {
+        SendMessageW(TTM_ACTIVATE, bActivate);
+    }
+
+    // Adjusts the position of a tooltip when used to display trimmed text
+    VOID AdjustRect(IN BOOL bTextToWindow, IN OUT RECT * pRect)
+    {
+        SendMessageW(TTM_ADJUSTRECT, bTextToWindow, 
reinterpret_cast<LPARAM>(pRect));
+    }
+
+    // Useful for TTF_ABSOLUTE|TTF_TRACK tooltip positioning
+    SIZE GetBubbleSize(IN TTTOOLINFOW * pInfo)
+    {
+        DWORD ret = SendMessageW(TTM_GETBUBBLESIZE, 0, 
reinterpret_cast<LPARAM>(pInfo));
+        const SIZE sz = { LOWORD(ret), HIWORD(ret) };
+        return sz;
+    }
+
+    // Fills the RECT with the margin size previously set. Default is 0 
margins.
+    VOID GetMargin(OUT RECT * pRect)
+    {
+        SendMessageW(TTM_GETMARGIN, 0, reinterpret_cast<LPARAM>(pRect));
+    }
+
+    VOID SetMargin(IN RECT * pRect)
+    {
+        SendMessageW(TTM_SETMARGIN, 0, reinterpret_cast<LPARAM>(pRect));
+    }
+
+    // Gets a previously established max width. Returns -1 if no limit is set
+    INT GetMaxTipWidth()
+    {
+        return SendMessageW(TTM_GETMAXTIPWIDTH);
+    }
+
+    INT SetMaxTipWidth(IN OPTIONAL INT width = -1)
+    {
+        return SendMessageW(TTM_SETMAXTIPWIDTH, 0, width);
+    }
+
+    // Get the color of the tooltip text
+    COLORREF GetTipTextColor()
+    {
+        return SendMessageW(TTM_GETTIPTEXTCOLOR);
+    }
+
+    VOID SetTipTextColor(IN COLORREF textColor)
+    {
+        SendMessageW(TTM_SETTIPTEXTCOLOR, textColor);
+    }
+
+    COLORREF GetTipBkColor()
+    {
+        return SendMessageW(TTM_GETTIPBKCOLOR);
+    }
+
+    VOID SetTipBkColor(IN COLORREF textColor)
+    {
+        SendMessageW(TTM_SETTIPBKCOLOR, textColor);
+    }
+
+    VOID SetWindowTheme(IN PCWSTR szThemeName)
+    {
+        SendMessageW(TTM_SETWINDOWTHEME, 0, 
reinterpret_cast<LPARAM>(szThemeName));
+    }
+
+    // Forces redraw
+    VOID Update()
+    {
+        SendMessageW(TTM_UPDATE);
+    }
+
+    HWND WindowFromPoint(IN POINT * pPoint)
+    {
+        return reinterpret_cast<HWND>(SendMessageW(TTM_WINDOWFROMPOINT, 0, 
reinterpret_cast<LPARAM>(pPoint)));
+    }
+};

Reply via email to