Commit 7bc76766 authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

Implement titles.

parent e18a31eb
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Tool tip control * Tool tip control
* *
* Copyright 1998, 1999 Eric Kohl * Copyright 1998, 1999 Eric Kohl
* Copyright 2004 Robert Shearman
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -87,6 +88,8 @@ ...@@ -87,6 +88,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(tooltips); WINE_DEFAULT_DEBUG_CHANNEL(tooltips);
static HICON hTooltipIcons[TTI_ERROR+1];
typedef struct typedef struct
{ {
UINT uFlags; UINT uFlags;
...@@ -109,6 +112,7 @@ typedef struct ...@@ -109,6 +112,7 @@ typedef struct
COLORREF clrBk; COLORREF clrBk;
COLORREF clrText; COLORREF clrText;
HFONT hFont; HFONT hFont;
HFONT hTitleFont;
INT xTrackPos; INT xTrackPos;
INT yTrackPos; INT yTrackPos;
INT nMaxTipWidth; INT nMaxTipWidth;
...@@ -120,6 +124,8 @@ typedef struct ...@@ -120,6 +124,8 @@ typedef struct
INT nInitialTime; INT nInitialTime;
RECT rcMargin; RECT rcMargin;
BOOL bToolBelow; BOOL bToolBelow;
LPWSTR pszTitle;
HICON hTitleIcon;
TTTOOL_INFO *tools; TTTOOL_INFO *tools;
} TOOLTIPS_INFO; } TOOLTIPS_INFO;
...@@ -141,10 +147,42 @@ typedef struct ...@@ -141,10 +147,42 @@ typedef struct
#define BALLOON_STEMWIDTH 10 #define BALLOON_STEMWIDTH 10
#define BALLOON_STEMINDENT 20 #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 LRESULT CALLBACK
TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uId, DWORD_PTR dwRef); 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 static VOID
TOOLTIPS_Refresh (HWND hwnd, HDC hdc) TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
{ {
...@@ -165,6 +203,11 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc) ...@@ -165,6 +203,11 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
hBrush = CreateSolidBrush(infoPtr->clrBk); 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) if (dwStyle & TTS_BALLOON)
{ {
/* create a region to store result into */ /* create a region to store result into */
...@@ -176,21 +219,48 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc) ...@@ -176,21 +219,48 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
FillRgn(hdc, hRgn, hBrush); FillRgn(hdc, hRgn, hBrush);
DeleteObject(hBrush); DeleteObject(hBrush);
hBrush = NULL; hBrush = NULL;
}
else
{
/* fill the background */
FillRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
hBrush = NULL;
}
if ((dwStyle & TTS_BALLOON) || infoPtr->pszTitle)
{
/* calculate text rectangle */ /* calculate text rectangle */
rc.left += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.left); rc.left += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.left);
rc.top += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.top); rc.top += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.top);
rc.right -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.right); rc.right -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.right);
rc.bottom -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.bottom); rc.bottom -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.bottom);
if(infoPtr->bToolBelow) rc.top += BALLOON_STEMHEIGHT; 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 else
{ {
/* fill the background */
FillRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
hBrush = NULL;
/* calculate text rectangle */ /* calculate text rectangle */
rc.left += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.left); rc.left += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.left);
rc.top += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.top); rc.top += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.top);
...@@ -198,12 +268,8 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc) ...@@ -198,12 +268,8 @@ TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
rc.bottom -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.bottom); 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 */ /* draw text */
hOldFont = SelectObject (hdc, infoPtr->hFont);
DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags); DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
/* be polite and reset the things we changed in the dc */ /* be polite and reset the things we changed in the dc */
SelectObject (hdc, hOldFont); SelectObject (hdc, hOldFont);
...@@ -359,6 +425,7 @@ TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize) ...@@ -359,6 +425,7 @@ TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
DWORD style = GetWindowLongW(hwnd, GWL_STYLE); DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT; UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
RECT rc = {0, 0, 0, 0}; RECT rc = {0, 0, 0, 0};
SIZE title = {0, 0};
if (infoPtr->nMaxTipWidth > -1) { if (infoPtr->nMaxTipWidth > -1) {
rc.right = infoPtr->nMaxTipWidth; rc.right = infoPtr->nMaxTipWidth;
...@@ -369,16 +436,32 @@ TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize) ...@@ -369,16 +436,32 @@ TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
TRACE("%s\n", debugstr_w(infoPtr->szTipText)); TRACE("%s\n", debugstr_w(infoPtr->szTipText));
hdc = GetDC (hwnd); 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); hOldFont = SelectObject (hdc, infoPtr->hFont);
DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags); DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
SelectObject (hdc, hOldFont); SelectObject (hdc, hOldFont);
ReleaseDC (hwnd, hdc); 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; 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 + infoPtr->rcMargin.bottom + infoPtr->rcMargin.top +
BALLOON_STEMHEIGHT; BALLOON_STEMHEIGHT;
} }
...@@ -1824,6 +1907,56 @@ TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam) ...@@ -1824,6 +1907,56 @@ TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
static LRESULT 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_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
{ {
TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
...@@ -2134,7 +2267,6 @@ static LRESULT ...@@ -2134,7 +2267,6 @@ static LRESULT
TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs) TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
{ {
TOOLTIPS_INFO *infoPtr; TOOLTIPS_INFO *infoPtr;
NONCLIENTMETRICSA nclm;
/* allocate memory for info structure */ /* allocate memory for info structure */
infoPtr = (TOOLTIPS_INFO *)Alloc (sizeof(TOOLTIPS_INFO)); infoPtr = (TOOLTIPS_INFO *)Alloc (sizeof(TOOLTIPS_INFO));
...@@ -2143,18 +2275,15 @@ TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs) ...@@ -2143,18 +2275,15 @@ TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
/* initialize info structure */ /* initialize info structure */
infoPtr->bActive = TRUE; infoPtr->bActive = TRUE;
infoPtr->bTrackActive = FALSE; 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->nMaxTipWidth = -1;
infoPtr->nTool = -1; infoPtr->nTool = -1;
infoPtr->nCurrentTool = -1; infoPtr->nCurrentTool = -1;
infoPtr->nTrackTool = -1; infoPtr->nTrackTool = -1;
/* initialize colours and fonts */
TOOLTIPS_InitSystemSettings(infoPtr);
TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L); TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
...@@ -2196,8 +2325,15 @@ TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) ...@@ -2196,8 +2325,15 @@ TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
Free (infoPtr->tools); 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->hFont);
DeleteObject (infoPtr->hTitleFont);
/* free tool tips info data */ /* free tool tips info data */
Free (infoPtr); Free (infoPtr);
...@@ -2299,9 +2435,13 @@ TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) ...@@ -2299,9 +2435,13 @@ TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
if(!GetObjectW((HFONT)wParam, sizeof(lf), &lf)) if(!GetObjectW((HFONT)wParam, sizeof(lf), &lf))
return 0; return 0;
if(infoPtr->hFont) DeleteObject (infoPtr->hFont); DeleteObject (infoPtr->hFont);
infoPtr->hFont = CreateFontIndirectW(&lf); infoPtr->hFont = CreateFontIndirectW(&lf);
DeleteObject (infoPtr->hTitleFont);
lf.lfWeight = FW_BOLD;
infoPtr->hTitleFont = CreateFontIndirectW(&lf);
if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) { if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
FIXME("full redraw needed!\n"); FIXME("full redraw needed!\n");
} }
...@@ -2402,15 +2542,8 @@ static LRESULT ...@@ -2402,15 +2542,8 @@ static LRESULT
TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam) TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
{ {
TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
NONCLIENTMETRICSA nclm;
infoPtr->clrBk = GetSysColor (COLOR_INFOBK);
infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
DeleteObject (infoPtr->hFont); TOOLTIPS_InitSystemSettings (infoPtr);
nclm.cbSize = sizeof(NONCLIENTMETRICSA);
SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
return 0; return 0;
} }
...@@ -2544,6 +2677,12 @@ TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ...@@ -2544,6 +2677,12 @@ TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case TTM_SETTIPTEXTCOLOR: case TTM_SETTIPTEXTCOLOR:
return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam); 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: case TTM_SETTOOLINFOA:
return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam); return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
...@@ -2644,11 +2783,22 @@ TOOLTIPS_Register (void) ...@@ -2644,11 +2783,22 @@ TOOLTIPS_Register (void)
wndClass.lpszClassName = TOOLTIPS_CLASSA; wndClass.lpszClassName = TOOLTIPS_CLASSA;
RegisterClassA (&wndClass); 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_ERROR_SM), IMAGE_ICON, 0, 0, 0);
} }
VOID VOID
TOOLTIPS_Unregister (void) TOOLTIPS_Unregister (void)
{ {
int i;
for (i = 0; i < TTI_ERROR+1; i++)
DeleteObject(hTooltipIcons[i]);
UnregisterClassA (TOOLTIPS_CLASSA, NULL); UnregisterClassA (TOOLTIPS_CLASSA, NULL);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment