Tooltips: Titles
Robert Shearman
rob at codeweavers.com
Tue Sep 7 06:05:59 CDT 2004
Hi,
This patch adds support for titles in tooltips. It also includes the new
functionality in XP SP2 where the icon can be supplied by the
application, not just one of the default types. The attached patch
depends on the new resources patch here:
http://www.winehq.org/hypermail/wine-patches/2004/09/0087.html
Rob
Changelog:
Implement titles.
-------------- next part --------------
Index: wine/dlls/comctl32/tooltips.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/tooltips.c,v
retrieving revision 1.69
diff -u -p -r1.69 tooltips.c
--- wine/dlls/comctl32/tooltips.c 2 Sep 2004 23:00:53 -0000 1.69
+++ wine/dlls/comctl32/tooltips.c 7 Sep 2004 10:40:12 -0000
@@ -2,6 +2,7 @@
* Tool tip control
*
* Copyright 1998, 1999 Eric Kohl
+ * Copyright 2004 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -87,6 +88,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(tooltips);
+static HICON hTooltipIcons[TTI_ERROR+1];
+
typedef struct
{
UINT uFlags;
@@ -109,6 +112,7 @@ typedef struct
COLORREF clrBk;
COLORREF clrText;
HFONT hFont;
+ HFONT hTitleFont;
INT xTrackPos;
INT yTrackPos;
INT nMaxTipWidth;
@@ -120,6 +124,8 @@ typedef struct
INT nInitialTime;
RECT rcMargin;
BOOL bToolBelow;
+ LPWSTR pszTitle;
+ HICON hTitleIcon;
TTTOOL_INFO *tools;
} TOOLTIPS_INFO;
@@ -141,10 +147,42 @@ typedef struct
#define BALLOON_STEMWIDTH 10
#define BALLOON_STEMINDENT 20
+#define BALLOON_ICON_TITLE_SPACING 8 /* horizontal spacing between icon and title */
+#define BALLOON_TITLE_TEXT_SPACING 8 /* vertical spacing between icon/title and main text */
+#define ICON_HEIGHT 16
+#define ICON_WIDTH 16
+
LRESULT CALLBACK
TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uId, DWORD_PTR dwRef);
+static inline UINT_PTR TOOLTIPS_GetTitleIconIndex(HICON hIcon)
+{
+ UINT i;
+ for (i = 0; i <= TTI_ERROR; i++)
+ if (hTooltipIcons[i] == hIcon)
+ return i;
+ return (UINT_PTR)hIcon;
+}
+
+static void
+TOOLTIPS_InitSystemSettings (TOOLTIPS_INFO *infoPtr)
+{
+ NONCLIENTMETRICSW nclm;
+
+ infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
+ infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
+
+ DeleteObject (infoPtr->hFont);
+ nclm.cbSize = sizeof(nclm);
+ SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
+ infoPtr->hFont = CreateFontIndirectW (&nclm.lfStatusFont);
+
+ DeleteObject (infoPtr->hTitleFont);
+ nclm.lfStatusFont.lfWeight = FW_BOLD;
+ infoPtr->hTitleFont = CreateFontIndirectW (&nclm.lfStatusFont);
+}
+
static VOID
TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
{
@@ -165,6 +203,11 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
hBrush = CreateSolidBrush(infoPtr->clrBk);
+ /* already drawn the background; don't need to draw it again
+ * when drawing text */
+ oldBkMode = SetBkMode (hdc, TRANSPARENT);
+ SetTextColor (hdc, infoPtr->clrText);
+
if (dwStyle & TTS_BALLOON)
{
/* create a region to store result into */
@@ -176,21 +219,48 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
FillRgn(hdc, hRgn, hBrush);
DeleteObject(hBrush);
hBrush = NULL;
+ }
+ else
+ {
+ /* fill the background */
+ FillRect(hdc, &rc, hBrush);
+ DeleteObject(hBrush);
+ hBrush = NULL;
+ }
+ if ((dwStyle & TTS_BALLOON) || infoPtr->pszTitle)
+ {
/* calculate text rectangle */
rc.left += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.left);
rc.top += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.top);
rc.right -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.right);
rc.bottom -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.bottom);
if(infoPtr->bToolBelow) rc.top += BALLOON_STEMHEIGHT;
+
+ if (infoPtr->pszTitle)
+ {
+ RECT rcTitle = {rc.left, rc.top, rc.right, rc.bottom};
+ int height;
+ BOOL icon_present;
+
+ /* draw icon */
+ icon_present = infoPtr->hTitleIcon &&
+ DrawIconEx(hdc, rc.left, rc.top, infoPtr->hTitleIcon,
+ ICON_WIDTH, ICON_HEIGHT, 0, NULL, DI_NORMAL);
+ if (icon_present)
+ rcTitle.left += ICON_WIDTH + BALLOON_ICON_TITLE_SPACING;
+
+ rcTitle.bottom = rc.top + ICON_HEIGHT;
+
+ /* draw title text */
+ hOldFont = SelectObject (hdc, infoPtr->hTitleFont);
+ height = DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_BOTTOM | DT_SINGLELINE | DT_NOPREFIX);
+ SelectObject (hdc, hOldFont);
+ rc.top += height + BALLOON_TITLE_TEXT_SPACING;
+ }
}
else
{
- /* fill the background */
- FillRect(hdc, &rc, hBrush);
- DeleteObject(hBrush);
- hBrush = NULL;
-
/* calculate text rectangle */
rc.left += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.left);
rc.top += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.top);
@@ -198,12 +268,8 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
rc.bottom -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.bottom);
}
- /* already drawn the background; don't need to draw it again
- * when drawing text */
- oldBkMode = SetBkMode (hdc, TRANSPARENT);
- SetTextColor (hdc, infoPtr->clrText);
- hOldFont = SelectObject (hdc, infoPtr->hFont);
/* draw text */
+ hOldFont = SelectObject (hdc, infoPtr->hFont);
DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
/* be polite and reset the things we changed in the dc */
SelectObject (hdc, hOldFont);
@@ -359,6 +425,7 @@ TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIP
DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
RECT rc = {0, 0, 0, 0};
+ SIZE title = {0, 0};
if (infoPtr->nMaxTipWidth > -1) {
rc.right = infoPtr->nMaxTipWidth;
@@ -369,16 +436,32 @@ TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIP
TRACE("%s\n", debugstr_w(infoPtr->szTipText));
hdc = GetDC (hwnd);
+ if (infoPtr->pszTitle)
+ {
+ RECT rcTitle = {0, 0, 0, 0};
+ TRACE("title %s\n", debugstr_w(infoPtr->pszTitle));
+ if (infoPtr->hTitleIcon)
+ {
+ title.cx = ICON_WIDTH;
+ title.cy = ICON_HEIGHT;
+ }
+ if (title.cx != 0) title.cx += BALLOON_ICON_TITLE_SPACING;
+ hOldFont = SelectObject (hdc, infoPtr->hTitleFont);
+ DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT);
+ SelectObject (hdc, hOldFont);
+ title.cy = max(title.cy, rcTitle.bottom - rcTitle.top) + BALLOON_TITLE_TEXT_SPACING;
+ title.cx += (rcTitle.right - rcTitle.left);
+ }
hOldFont = SelectObject (hdc, infoPtr->hFont);
DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
SelectObject (hdc, hOldFont);
ReleaseDC (hwnd, hdc);
- if (style & TTS_BALLOON)
+ if ((style & TTS_BALLOON) || infoPtr->pszTitle)
{
- lpSize->cx = rc.right - rc.left + 2*BALLOON_TEXT_MARGIN +
+ lpSize->cx = max(rc.right - rc.left, title.cx) + 2*BALLOON_TEXT_MARGIN +
infoPtr->rcMargin.left + infoPtr->rcMargin.right;
- lpSize->cy = rc.bottom - rc.top + 2*BALLOON_TEXT_MARGIN +
+ lpSize->cy = title.cy + rc.bottom - rc.top + 2*BALLOON_TEXT_MARGIN +
infoPtr->rcMargin.bottom + infoPtr->rcMargin.top +
BALLOON_STEMHEIGHT;
}
@@ -1824,6 +1907,56 @@ TOOLTIPS_SetTipTextColor (HWND hwnd, WPA
static LRESULT
+TOOLTIPS_SetTitleA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+ LPCSTR pszTitle = (LPCSTR)lParam;
+ UINT uTitleIcon = (UINT)wParam;
+ UINT size;
+
+ TRACE("hwnd = %p, title = %s, icon = %p\n", hwnd, pszTitle, (void*)uTitleIcon);
+
+ size = sizeof(WCHAR)*MultiByteToWideChar(CP_ACP, 0, pszTitle, -1, NULL, 0);
+ infoPtr->pszTitle = Alloc(size);
+ if (!infoPtr->pszTitle)
+ return FALSE;
+ MultiByteToWideChar(CP_ACP, 0, pszTitle, -1, infoPtr->pszTitle, size/sizeof(WCHAR));
+ if (uTitleIcon <= TTI_ERROR)
+ infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon];
+ else
+ infoPtr->hTitleIcon = CopyIcon((HICON)wParam);
+
+ return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_SetTitleW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+ TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+ LPCWSTR pszTitle = (LPCWSTR)lParam;
+ UINT uTitleIcon = (UINT)wParam;
+ UINT size;
+
+ TRACE("hwnd = %p, title = %s, icon = %p\n", hwnd, debugstr_w(pszTitle), (void*)uTitleIcon);
+
+ size = (strlenW(pszTitle)+1)*sizeof(WCHAR);
+ infoPtr->pszTitle = Alloc(size);
+ if (!infoPtr->pszTitle)
+ return FALSE;
+ memcpy(infoPtr->pszTitle, pszTitle, size);
+ if (uTitleIcon <= TTI_ERROR)
+ infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon];
+ else
+ infoPtr->hTitleIcon = CopyIcon((HICON)wParam);
+
+ TRACE("icon = %p\n", infoPtr->hTitleIcon);
+
+ return TRUE;
+}
+
+
+static LRESULT
TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
@@ -2134,7 +2267,6 @@ static LRESULT
TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
{
TOOLTIPS_INFO *infoPtr;
- NONCLIENTMETRICSA nclm;
/* allocate memory for info structure */
infoPtr = (TOOLTIPS_INFO *)Alloc (sizeof(TOOLTIPS_INFO));
@@ -2143,18 +2275,15 @@ TOOLTIPS_Create (HWND hwnd, const CREATE
/* initialize info structure */
infoPtr->bActive = TRUE;
infoPtr->bTrackActive = FALSE;
- infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
- infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
-
- nclm.cbSize = sizeof(NONCLIENTMETRICSA);
- SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
- infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
infoPtr->nMaxTipWidth = -1;
infoPtr->nTool = -1;
infoPtr->nCurrentTool = -1;
infoPtr->nTrackTool = -1;
+ /* initialize colours and fonts */
+ TOOLTIPS_InitSystemSettings(infoPtr);
+
TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
@@ -2196,8 +2325,15 @@ TOOLTIPS_Destroy (HWND hwnd, WPARAM wPar
Free (infoPtr->tools);
}
- /* delete font */
+ /* free title string */
+ Free (infoPtr->pszTitle);
+ /* free title icon if not a standard one */
+ if (TOOLTIPS_GetTitleIconIndex(infoPtr->hTitleIcon) > TTI_ERROR)
+ DeleteObject(infoPtr->hTitleIcon);
+
+ /* delete fonts */
DeleteObject (infoPtr->hFont);
+ DeleteObject (infoPtr->hTitleFont);
/* free tool tips info data */
Free (infoPtr);
@@ -2299,9 +2435,13 @@ TOOLTIPS_SetFont (HWND hwnd, WPARAM wPar
if(!GetObjectW((HFONT)wParam, sizeof(lf), &lf))
return 0;
- if(infoPtr->hFont) DeleteObject (infoPtr->hFont);
+ DeleteObject (infoPtr->hFont);
infoPtr->hFont = CreateFontIndirectW(&lf);
+ DeleteObject (infoPtr->hTitleFont);
+ lf.lfWeight = FW_BOLD;
+ infoPtr->hTitleFont = CreateFontIndirectW(&lf);
+
if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
FIXME("full redraw needed!\n");
}
@@ -2402,15 +2542,8 @@ static LRESULT
TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
- NONCLIENTMETRICSA nclm;
-
- infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
- infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
- DeleteObject (infoPtr->hFont);
- nclm.cbSize = sizeof(NONCLIENTMETRICSA);
- SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
- infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
+ TOOLTIPS_InitSystemSettings (infoPtr);
return 0;
}
@@ -2544,6 +2677,12 @@ TOOLTIPS_WindowProc (HWND hwnd, UINT uMs
case TTM_SETTIPTEXTCOLOR:
return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
+ case TTM_SETTITLEA:
+ return TOOLTIPS_SetTitleA (hwnd, wParam, lParam);
+
+ case TTM_SETTITLEW:
+ return TOOLTIPS_SetTitleW (hwnd, wParam, lParam);
+
case TTM_SETTOOLINFOA:
return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
@@ -2644,11 +2783,22 @@ TOOLTIPS_Register (void)
wndClass.lpszClassName = TOOLTIPS_CLASSA;
RegisterClassA (&wndClass);
+
+ hTooltipIcons[TTI_NONE] = NULL;
+ hTooltipIcons[TTI_INFO] = LoadImageW(COMCTL32_hModule,
+ (LPCWSTR)MAKEINTRESOURCE(IDI_TT_INFO_SM), IMAGE_ICON, 0, 0, 0);
+ hTooltipIcons[TTI_WARNING] = LoadImageW(COMCTL32_hModule,
+ (LPCWSTR)MAKEINTRESOURCE(IDI_TT_WARN_SM), IMAGE_ICON, 0, 0, 0);
+ hTooltipIcons[TTI_ERROR] = LoadImageW(COMCTL32_hModule,
+ (LPCWSTR)MAKEINTRESOURCE(IDI_TT_ERRO_SM), IMAGE_ICON, 0, 0, 0);
}
VOID
TOOLTIPS_Unregister (void)
{
+ int i;
+ for (i = 0; i < TTI_ERROR+1; i++)
+ DeleteObject(hTooltipIcons[i]);
UnregisterClassA (TOOLTIPS_CLASSA, NULL);
}
More information about the wine-patches
mailing list