1c2c66affSColin Finck /* 2c2c66affSColin Finck * Tool tip control 3c2c66affSColin Finck * 4c2c66affSColin Finck * Copyright 1998, 1999 Eric Kohl 5c2c66affSColin Finck * Copyright 2004 Robert Shearman 6c2c66affSColin Finck * 7c2c66affSColin Finck * This library is free software; you can redistribute it and/or 8c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 9c2c66affSColin Finck * License as published by the Free Software Foundation; either 10c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 11c2c66affSColin Finck * 12c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15c2c66affSColin Finck * Lesser General Public License for more details. 16c2c66affSColin Finck * 17c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 18c2c66affSColin Finck * License along with this library; if not, write to the Free Software 19c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20c2c66affSColin Finck * 21c2c66affSColin Finck * NOTES 22c2c66affSColin Finck * 23c2c66affSColin Finck * This code was audited for completeness against the documented features 24c2c66affSColin Finck * of Comctl32.dll version 6.0 on Sep. 08, 2004, by Robert Shearman. 25c2c66affSColin Finck * 26c2c66affSColin Finck * Unless otherwise noted, we believe this code to be complete, as per 27c2c66affSColin Finck * the specification mentioned above. 28c2c66affSColin Finck * If you discover missing features or bugs please note them below. 29c2c66affSColin Finck * 30c2c66affSColin Finck * TODO: 31c2c66affSColin Finck * - Custom draw support. 32c2c66affSColin Finck * - Animation. 33c2c66affSColin Finck * - Links. 34c2c66affSColin Finck * - Messages: 35c2c66affSColin Finck * o TTM_ADJUSTRECT 36c2c66affSColin Finck * o TTM_GETTITLEA 37c2c66affSColin Finck * o TTM_GETTTILEW 38c2c66affSColin Finck * o TTM_POPUP 39c2c66affSColin Finck * - Styles: 40c2c66affSColin Finck * o TTS_NOANIMATE 41c2c66affSColin Finck * o TTS_NOFADE 42c2c66affSColin Finck * o TTS_CLOSE 43c2c66affSColin Finck * 44c2c66affSColin Finck * Testing: 45c2c66affSColin Finck * - Run tests using Waite Group Windows95 API Bible Volume 2. 46c2c66affSColin Finck * The second cdrom (chapter 3) contains executables activate.exe, 47c2c66affSColin Finck * curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe, 48c2c66affSColin Finck * hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe. 49c2c66affSColin Finck * 50c2c66affSColin Finck * Timer logic. 51c2c66affSColin Finck * 52c2c66affSColin Finck * One important point to remember is that tools don't necessarily get 53c2c66affSColin Finck * a WM_MOUSEMOVE once the cursor leaves the tool, an example is when 54c2c66affSColin Finck * a tool sets TTF_IDISHWND (i.e. an entire window is a tool) because 55c2c66affSColin Finck * here WM_MOUSEMOVEs only get sent when the cursor is inside the 56c2c66affSColin Finck * client area. Therefore the only reliable way to know that the 57c2c66affSColin Finck * cursor has left a tool is to keep a timer running and check the 58c2c66affSColin Finck * position every time it expires. This is the role of timer 59c2c66affSColin Finck * ID_TIMERLEAVE. 60c2c66affSColin Finck * 61c2c66affSColin Finck * 62c2c66affSColin Finck * On entering a tool (detected in a relayed WM_MOUSEMOVE) we start 63c2c66affSColin Finck * ID_TIMERSHOW, if this times out and we're still in the tool we show 64c2c66affSColin Finck * the tip. On showing a tip we start both ID_TIMERPOP and 65c2c66affSColin Finck * ID_TIMERLEAVE. On hiding a tooltip we kill ID_TIMERPOP. 66c2c66affSColin Finck * ID_TIMERPOP is restarted on every relayed WM_MOUSEMOVE. If 67c2c66affSColin Finck * ID_TIMERPOP expires the tool is hidden and ID_TIMERPOP is killed. 68c2c66affSColin Finck * ID_TIMERLEAVE remains running - this is important as we need to 69c2c66affSColin Finck * determine when the cursor leaves the tool. 70c2c66affSColin Finck * 71c2c66affSColin Finck * When ID_TIMERLEAVE expires or on a relayed WM_MOUSEMOVE if we're 72c2c66affSColin Finck * still in the tool do nothing (apart from restart ID_TIMERPOP if 73c2c66affSColin Finck * this is a WM_MOUSEMOVE) (ID_TIMERLEAVE remains running). If we've 74c2c66affSColin Finck * left the tool and entered another one then hide the tip and start 75c2c66affSColin Finck * ID_TIMERSHOW with time ReshowTime and kill ID_TIMERLEAVE. If we're 76c2c66affSColin Finck * outside all tools hide the tip and kill ID_TIMERLEAVE. On Relayed 77c2c66affSColin Finck * mouse button messages hide the tip but leave ID_TIMERLEAVE running, 78c2c66affSColin Finck * this again will let us keep track of when the cursor leaves the 79c2c66affSColin Finck * tool. 80c2c66affSColin Finck * 81c2c66affSColin Finck * 82c2c66affSColin Finck * infoPtr->nTool is the tool the mouse was on on the last relayed MM 83c2c66affSColin Finck * or timer expiry or -1 if the mouse was not on a tool. 84c2c66affSColin Finck * 85c2c66affSColin Finck * infoPtr->nCurrentTool is the tool for which the tip is currently 86c2c66affSColin Finck * displaying text for or -1 if the tip is not shown. Actually this 87c2c66affSColin Finck * will only ever be infoPtr-nTool or -1, so it could be changed to a 88c2c66affSColin Finck * BOOL. 89c2c66affSColin Finck * 90c2c66affSColin Finck */ 91c2c66affSColin Finck 92c2c66affSColin Finck 93*b3fb8555SGiannis Adamopoulos 94*b3fb8555SGiannis Adamopoulos #include <stdarg.h> 95*b3fb8555SGiannis Adamopoulos #include <string.h> 96*b3fb8555SGiannis Adamopoulos 97*b3fb8555SGiannis Adamopoulos #include "windef.h" 98*b3fb8555SGiannis Adamopoulos #include "winbase.h" 99*b3fb8555SGiannis Adamopoulos #include "wine/unicode.h" 100*b3fb8555SGiannis Adamopoulos #include "wingdi.h" 101*b3fb8555SGiannis Adamopoulos #include "winuser.h" 102*b3fb8555SGiannis Adamopoulos #include "winnls.h" 103*b3fb8555SGiannis Adamopoulos #include "commctrl.h" 104*b3fb8555SGiannis Adamopoulos #include "comctl32.h" 105*b3fb8555SGiannis Adamopoulos #include "wine/debug.h" 106c2c66affSColin Finck 107c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(tooltips); 108c2c66affSColin Finck 109c2c66affSColin Finck static HICON hTooltipIcons[TTI_ERROR+1]; 110c2c66affSColin Finck 111c2c66affSColin Finck typedef struct 112c2c66affSColin Finck { 113c2c66affSColin Finck UINT uFlags; 114c2c66affSColin Finck UINT uInternalFlags; 115c2c66affSColin Finck HWND hwnd; 116c2c66affSColin Finck BOOL bNotifyUnicode; 117c2c66affSColin Finck UINT_PTR uId; 118c2c66affSColin Finck RECT rect; 119c2c66affSColin Finck HINSTANCE hinst; 120c2c66affSColin Finck LPWSTR lpszText; 121c2c66affSColin Finck LPARAM lParam; 122c2c66affSColin Finck } TTTOOL_INFO; 123c2c66affSColin Finck 124c2c66affSColin Finck 125c2c66affSColin Finck typedef struct 126c2c66affSColin Finck { 127c2c66affSColin Finck HWND hwndSelf; 128c2c66affSColin Finck WCHAR szTipText[INFOTIPSIZE]; 129c2c66affSColin Finck BOOL bActive; 130c2c66affSColin Finck BOOL bTrackActive; 131c2c66affSColin Finck UINT uNumTools; 132c2c66affSColin Finck COLORREF clrBk; 133c2c66affSColin Finck COLORREF clrText; 134c2c66affSColin Finck HFONT hFont; 135c2c66affSColin Finck HFONT hTitleFont; 136c2c66affSColin Finck INT xTrackPos; 137c2c66affSColin Finck INT yTrackPos; 138c2c66affSColin Finck INT nMaxTipWidth; 139c2c66affSColin Finck INT nTool; /* tool that mouse was on on last relayed mouse move */ 140c2c66affSColin Finck INT nCurrentTool; 141c2c66affSColin Finck INT nTrackTool; 142c2c66affSColin Finck INT nReshowTime; 143c2c66affSColin Finck INT nAutoPopTime; 144c2c66affSColin Finck INT nInitialTime; 145c2c66affSColin Finck RECT rcMargin; 146c2c66affSColin Finck BOOL bToolBelow; 147c2c66affSColin Finck LPWSTR pszTitle; 148c2c66affSColin Finck HICON hTitleIcon; 149c2c66affSColin Finck 150c2c66affSColin Finck TTTOOL_INFO *tools; 151c2c66affSColin Finck } TOOLTIPS_INFO; 152c2c66affSColin Finck 153c2c66affSColin Finck #define ID_TIMERSHOW 1 /* show delay timer */ 154c2c66affSColin Finck #define ID_TIMERPOP 2 /* auto pop timer */ 155c2c66affSColin Finck #define ID_TIMERLEAVE 3 /* tool leave timer */ 156c2c66affSColin Finck 157c2c66affSColin Finck 158c2c66affSColin Finck #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongPtrW (hWindow, 0)) 159c2c66affSColin Finck 160c2c66affSColin Finck /* offsets from window edge to start of text */ 161c2c66affSColin Finck #define NORMAL_TEXT_MARGIN 2 162c2c66affSColin Finck #define BALLOON_TEXT_MARGIN (NORMAL_TEXT_MARGIN+8) 163c2c66affSColin Finck /* value used for CreateRoundRectRgn that specifies how much 164c2c66affSColin Finck * each corner is curved */ 165c2c66affSColin Finck #define BALLOON_ROUNDEDNESS 20 166c2c66affSColin Finck #define BALLOON_STEMHEIGHT 13 167c2c66affSColin Finck #define BALLOON_STEMWIDTH 10 168c2c66affSColin Finck #define BALLOON_STEMINDENT 20 169c2c66affSColin Finck 170c2c66affSColin Finck #define BALLOON_ICON_TITLE_SPACING 8 /* horizontal spacing between icon and title */ 171c2c66affSColin Finck #define BALLOON_TITLE_TEXT_SPACING 8 /* vertical spacing between icon/title and main text */ 172c2c66affSColin Finck #define ICON_HEIGHT 16 173c2c66affSColin Finck #define ICON_WIDTH 16 174c2c66affSColin Finck 175c2c66affSColin Finck #define MAX_TEXT_SIZE_A 80 /* maximum retrieving text size by ANSI message */ 176c2c66affSColin Finck 177c2c66affSColin Finck static LRESULT CALLBACK 178c2c66affSColin Finck TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uId, DWORD_PTR dwRef); 179c2c66affSColin Finck 180c2c66affSColin Finck 181c2c66affSColin Finck static inline BOOL TOOLTIPS_IsCallbackString(LPCWSTR str, BOOL isW) 182c2c66affSColin Finck { 183c2c66affSColin Finck if (isW) 184c2c66affSColin Finck return str == LPSTR_TEXTCALLBACKW; 185c2c66affSColin Finck else 186c2c66affSColin Finck return (LPCSTR)str == LPSTR_TEXTCALLBACKA; 187c2c66affSColin Finck } 188c2c66affSColin Finck 189c2c66affSColin Finck static inline UINT_PTR 190c2c66affSColin Finck TOOLTIPS_GetTitleIconIndex(HICON hIcon) 191c2c66affSColin Finck { 192c2c66affSColin Finck UINT i; 193c2c66affSColin Finck for (i = 0; i <= TTI_ERROR; i++) 194c2c66affSColin Finck if (hTooltipIcons[i] == hIcon) 195c2c66affSColin Finck return i; 196c2c66affSColin Finck return (UINT_PTR)hIcon; 197c2c66affSColin Finck } 198c2c66affSColin Finck 199c2c66affSColin Finck static void 200c2c66affSColin Finck TOOLTIPS_InitSystemSettings (TOOLTIPS_INFO *infoPtr) 201c2c66affSColin Finck { 202c2c66affSColin Finck NONCLIENTMETRICSW nclm; 203c2c66affSColin Finck 204c2c66affSColin Finck infoPtr->clrBk = comctl32_color.clrInfoBk; 205c2c66affSColin Finck infoPtr->clrText = comctl32_color.clrInfoText; 206c2c66affSColin Finck 207c2c66affSColin Finck DeleteObject (infoPtr->hFont); 208c2c66affSColin Finck nclm.cbSize = sizeof(nclm); 209c2c66affSColin Finck SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0); 210c2c66affSColin Finck infoPtr->hFont = CreateFontIndirectW (&nclm.lfStatusFont); 211c2c66affSColin Finck 212c2c66affSColin Finck DeleteObject (infoPtr->hTitleFont); 213c2c66affSColin Finck nclm.lfStatusFont.lfWeight = FW_BOLD; 214c2c66affSColin Finck infoPtr->hTitleFont = CreateFontIndirectW (&nclm.lfStatusFont); 215c2c66affSColin Finck } 216c2c66affSColin Finck 217c2c66affSColin Finck /* Custom draw routines */ 218c2c66affSColin Finck static void 219c2c66affSColin Finck TOOLTIPS_customdraw_fill(const TOOLTIPS_INFO *infoPtr, NMTTCUSTOMDRAW *lpnmttcd, 220c2c66affSColin Finck HDC hdc, const RECT *rcBounds, UINT uFlags) 221c2c66affSColin Finck { 222c2c66affSColin Finck ZeroMemory(lpnmttcd, sizeof(NMTTCUSTOMDRAW)); 223c2c66affSColin Finck lpnmttcd->uDrawFlags = uFlags; 224c2c66affSColin Finck lpnmttcd->nmcd.hdr.hwndFrom = infoPtr->hwndSelf; 225c2c66affSColin Finck lpnmttcd->nmcd.hdr.code = NM_CUSTOMDRAW; 226c2c66affSColin Finck if (infoPtr->nCurrentTool != -1) { 227c2c66affSColin Finck TTTOOL_INFO *toolPtr = &infoPtr->tools[infoPtr->nCurrentTool]; 228c2c66affSColin Finck lpnmttcd->nmcd.hdr.idFrom = toolPtr->uId; 229c2c66affSColin Finck } 230c2c66affSColin Finck lpnmttcd->nmcd.hdc = hdc; 231c2c66affSColin Finck lpnmttcd->nmcd.rc = *rcBounds; 232c2c66affSColin Finck /* FIXME - dwItemSpec, uItemState, lItemlParam */ 233c2c66affSColin Finck } 234c2c66affSColin Finck 235c2c66affSColin Finck static inline DWORD 236c2c66affSColin Finck TOOLTIPS_notify_customdraw (DWORD dwDrawStage, NMTTCUSTOMDRAW *lpnmttcd) 237c2c66affSColin Finck { 238c2c66affSColin Finck LRESULT result; 239c2c66affSColin Finck lpnmttcd->nmcd.dwDrawStage = dwDrawStage; 240c2c66affSColin Finck 241c2c66affSColin Finck TRACE("Notifying stage %d, flags %x, id %x\n", lpnmttcd->nmcd.dwDrawStage, 242c2c66affSColin Finck lpnmttcd->uDrawFlags, lpnmttcd->nmcd.hdr.code); 243c2c66affSColin Finck 244c2c66affSColin Finck result = SendMessageW(GetParent(lpnmttcd->nmcd.hdr.hwndFrom), WM_NOTIFY, 245c2c66affSColin Finck 0, (LPARAM)lpnmttcd); 246c2c66affSColin Finck 247c2c66affSColin Finck TRACE("Notify result %x\n", (unsigned int)result); 248c2c66affSColin Finck 249c2c66affSColin Finck return result; 250c2c66affSColin Finck } 251c2c66affSColin Finck 252c2c66affSColin Finck static void 253c2c66affSColin Finck TOOLTIPS_Refresh (const TOOLTIPS_INFO *infoPtr, HDC hdc) 254c2c66affSColin Finck { 255c2c66affSColin Finck RECT rc; 256c2c66affSColin Finck INT oldBkMode; 257c2c66affSColin Finck HFONT hOldFont; 258c2c66affSColin Finck HBRUSH hBrush; 259c2c66affSColin Finck UINT uFlags = DT_EXTERNALLEADING; 260c2c66affSColin Finck HRGN hRgn = NULL; 261c2c66affSColin Finck DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); 262c2c66affSColin Finck NMTTCUSTOMDRAW nmttcd; 263c2c66affSColin Finck DWORD cdmode; 264c2c66affSColin Finck 265c2c66affSColin Finck if (infoPtr->nMaxTipWidth > -1) 266c2c66affSColin Finck uFlags |= DT_WORDBREAK; 267c2c66affSColin Finck if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TTS_NOPREFIX) 268c2c66affSColin Finck uFlags |= DT_NOPREFIX; 269c2c66affSColin Finck GetClientRect (infoPtr->hwndSelf, &rc); 270c2c66affSColin Finck 271c2c66affSColin Finck hBrush = CreateSolidBrush(infoPtr->clrBk); 272c2c66affSColin Finck 273c2c66affSColin Finck oldBkMode = SetBkMode (hdc, TRANSPARENT); 274c2c66affSColin Finck SetTextColor (hdc, infoPtr->clrText); 275c2c66affSColin Finck hOldFont = SelectObject (hdc, infoPtr->hFont); 276c2c66affSColin Finck 277c2c66affSColin Finck /* Custom draw - Call PrePaint once initial properties set up */ 278c2c66affSColin Finck /* Note: Contrary to MSDN, CDRF_SKIPDEFAULT still draws a tooltip */ 279c2c66affSColin Finck TOOLTIPS_customdraw_fill(infoPtr, &nmttcd, hdc, &rc, uFlags); 280c2c66affSColin Finck cdmode = TOOLTIPS_notify_customdraw(CDDS_PREPAINT, &nmttcd); 281c2c66affSColin Finck uFlags = nmttcd.uDrawFlags; 282c2c66affSColin Finck 283c2c66affSColin Finck if (dwStyle & TTS_BALLOON) 284c2c66affSColin Finck { 285c2c66affSColin Finck /* create a region to store result into */ 286c2c66affSColin Finck hRgn = CreateRectRgn(0, 0, 0, 0); 287c2c66affSColin Finck 288c2c66affSColin Finck GetWindowRgn(infoPtr->hwndSelf, hRgn); 289c2c66affSColin Finck 290c2c66affSColin Finck /* fill the background */ 291c2c66affSColin Finck FillRgn(hdc, hRgn, hBrush); 292c2c66affSColin Finck DeleteObject(hBrush); 293c2c66affSColin Finck hBrush = NULL; 294c2c66affSColin Finck } 295c2c66affSColin Finck else 296c2c66affSColin Finck { 297c2c66affSColin Finck /* fill the background */ 298c2c66affSColin Finck FillRect(hdc, &rc, hBrush); 299c2c66affSColin Finck DeleteObject(hBrush); 300c2c66affSColin Finck hBrush = NULL; 301c2c66affSColin Finck } 302c2c66affSColin Finck 303c2c66affSColin Finck if ((dwStyle & TTS_BALLOON) || infoPtr->pszTitle) 304c2c66affSColin Finck { 305c2c66affSColin Finck /* calculate text rectangle */ 306c2c66affSColin Finck rc.left += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.left); 307c2c66affSColin Finck rc.top += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.top); 308c2c66affSColin Finck rc.right -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.right); 309c2c66affSColin Finck rc.bottom -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.bottom); 310c2c66affSColin Finck if(infoPtr->bToolBelow) rc.top += BALLOON_STEMHEIGHT; 311c2c66affSColin Finck 312c2c66affSColin Finck if (infoPtr->pszTitle) 313c2c66affSColin Finck { 314c2c66affSColin Finck RECT rcTitle = {rc.left, rc.top, rc.right, rc.bottom}; 315c2c66affSColin Finck int height; 316c2c66affSColin Finck BOOL icon_present; 317c2c66affSColin Finck HFONT prevFont; 318c2c66affSColin Finck 319c2c66affSColin Finck /* draw icon */ 320c2c66affSColin Finck icon_present = infoPtr->hTitleIcon && 321c2c66affSColin Finck DrawIconEx(hdc, rc.left, rc.top, infoPtr->hTitleIcon, 322c2c66affSColin Finck ICON_WIDTH, ICON_HEIGHT, 0, NULL, DI_NORMAL); 323c2c66affSColin Finck if (icon_present) 324c2c66affSColin Finck rcTitle.left += ICON_WIDTH + BALLOON_ICON_TITLE_SPACING; 325c2c66affSColin Finck 326c2c66affSColin Finck rcTitle.bottom = rc.top + ICON_HEIGHT; 327c2c66affSColin Finck 328c2c66affSColin Finck /* draw title text */ 329c2c66affSColin Finck prevFont = SelectObject (hdc, infoPtr->hTitleFont); 330c2c66affSColin Finck height = DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_BOTTOM | DT_SINGLELINE | DT_NOPREFIX); 331c2c66affSColin Finck SelectObject (hdc, prevFont); 332c2c66affSColin Finck rc.top += height + BALLOON_TITLE_TEXT_SPACING; 333c2c66affSColin Finck } 334c2c66affSColin Finck } 335c2c66affSColin Finck else 336c2c66affSColin Finck { 337c2c66affSColin Finck /* calculate text rectangle */ 338c2c66affSColin Finck rc.left += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.left); 339c2c66affSColin Finck rc.top += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.top); 340c2c66affSColin Finck rc.right -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.right); 341c2c66affSColin Finck rc.bottom -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.bottom); 342c2c66affSColin Finck } 343c2c66affSColin Finck 344c2c66affSColin Finck /* draw text */ 345c2c66affSColin Finck DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags); 346c2c66affSColin Finck 347c2c66affSColin Finck /* Custom draw - Call PostPaint after drawing */ 348c2c66affSColin Finck if (cdmode & CDRF_NOTIFYPOSTPAINT) { 349c2c66affSColin Finck TOOLTIPS_notify_customdraw(CDDS_POSTPAINT, &nmttcd); 350c2c66affSColin Finck } 351c2c66affSColin Finck 352c2c66affSColin Finck /* be polite and reset the things we changed in the dc */ 353c2c66affSColin Finck SelectObject (hdc, hOldFont); 354c2c66affSColin Finck SetBkMode (hdc, oldBkMode); 355c2c66affSColin Finck 356c2c66affSColin Finck if (dwStyle & TTS_BALLOON) 357c2c66affSColin Finck { 358c2c66affSColin Finck /* frame region because default window proc doesn't do it */ 359c2c66affSColin Finck INT width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE); 360c2c66affSColin Finck INT height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE); 361c2c66affSColin Finck 362c2c66affSColin Finck hBrush = GetSysColorBrush(COLOR_WINDOWFRAME); 363c2c66affSColin Finck FrameRgn(hdc, hRgn, hBrush, width, height); 364c2c66affSColin Finck } 365c2c66affSColin Finck 366c2c66affSColin Finck if (hRgn) 367c2c66affSColin Finck DeleteObject(hRgn); 368c2c66affSColin Finck } 369c2c66affSColin Finck 370c2c66affSColin Finck static void TOOLTIPS_GetDispInfoA(const TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr, WCHAR *buffer) 371c2c66affSColin Finck { 372c2c66affSColin Finck NMTTDISPINFOA ttnmdi; 373c2c66affSColin Finck 374c2c66affSColin Finck /* fill NMHDR struct */ 375c2c66affSColin Finck ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA)); 376c2c66affSColin Finck ttnmdi.hdr.hwndFrom = infoPtr->hwndSelf; 377c2c66affSColin Finck ttnmdi.hdr.idFrom = toolPtr->uId; 378c2c66affSColin Finck ttnmdi.hdr.code = TTN_GETDISPINFOA; /* == TTN_NEEDTEXTA */ 379c2c66affSColin Finck ttnmdi.lpszText = ttnmdi.szText; 380c2c66affSColin Finck ttnmdi.uFlags = toolPtr->uFlags; 381c2c66affSColin Finck ttnmdi.lParam = toolPtr->lParam; 382c2c66affSColin Finck 383c2c66affSColin Finck TRACE("hdr.idFrom = %lx\n", ttnmdi.hdr.idFrom); 384c2c66affSColin Finck SendMessageW(toolPtr->hwnd, WM_NOTIFY, toolPtr->uId, (LPARAM)&ttnmdi); 385c2c66affSColin Finck 386c2c66affSColin Finck if (IS_INTRESOURCE(ttnmdi.lpszText)) { 387c2c66affSColin Finck LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText), 388c2c66affSColin Finck buffer, INFOTIPSIZE); 389c2c66affSColin Finck if (ttnmdi.uFlags & TTF_DI_SETITEM) { 390c2c66affSColin Finck toolPtr->hinst = ttnmdi.hinst; 391c2c66affSColin Finck toolPtr->lpszText = (LPWSTR)ttnmdi.lpszText; 392c2c66affSColin Finck } 393c2c66affSColin Finck } 394c2c66affSColin Finck else if (ttnmdi.lpszText == 0) { 395c2c66affSColin Finck buffer[0] = '\0'; 396c2c66affSColin Finck } 397c2c66affSColin Finck else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) { 398c2c66affSColin Finck Str_GetPtrAtoW(ttnmdi.lpszText, buffer, INFOTIPSIZE); 399c2c66affSColin Finck if (ttnmdi.uFlags & TTF_DI_SETITEM) { 400c2c66affSColin Finck toolPtr->hinst = 0; 401c2c66affSColin Finck toolPtr->lpszText = NULL; 402c2c66affSColin Finck Str_SetPtrW(&toolPtr->lpszText, buffer); 403c2c66affSColin Finck } 404c2c66affSColin Finck } 405c2c66affSColin Finck else { 406edd99e8cSAmine Khaldi ERR("recursive text callback\n"); 407c2c66affSColin Finck buffer[0] = '\0'; 408c2c66affSColin Finck } 409c2c66affSColin Finck 410c2c66affSColin Finck /* no text available - try calling parent instead as per native */ 411c2c66affSColin Finck /* FIXME: Unsure if SETITEM should save the value or not */ 412c2c66affSColin Finck if (buffer[0] == 0x00) { 413c2c66affSColin Finck 414c2c66affSColin Finck SendMessageW(GetParent(toolPtr->hwnd), WM_NOTIFY, toolPtr->uId, (LPARAM)&ttnmdi); 415c2c66affSColin Finck 416c2c66affSColin Finck if (IS_INTRESOURCE(ttnmdi.lpszText)) { 417c2c66affSColin Finck LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText), 418c2c66affSColin Finck buffer, INFOTIPSIZE); 419c2c66affSColin Finck } else if (ttnmdi.lpszText && 420c2c66affSColin Finck ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) { 421c2c66affSColin Finck Str_GetPtrAtoW(ttnmdi.lpszText, buffer, INFOTIPSIZE); 422c2c66affSColin Finck } 423c2c66affSColin Finck } 424c2c66affSColin Finck } 425c2c66affSColin Finck 426c2c66affSColin Finck static void TOOLTIPS_GetDispInfoW(const TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr, WCHAR *buffer) 427c2c66affSColin Finck { 428c2c66affSColin Finck NMTTDISPINFOW ttnmdi; 429c2c66affSColin Finck 430c2c66affSColin Finck /* fill NMHDR struct */ 431c2c66affSColin Finck ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOW)); 432c2c66affSColin Finck ttnmdi.hdr.hwndFrom = infoPtr->hwndSelf; 433c2c66affSColin Finck ttnmdi.hdr.idFrom = toolPtr->uId; 434c2c66affSColin Finck ttnmdi.hdr.code = TTN_GETDISPINFOW; /* == TTN_NEEDTEXTW */ 435c2c66affSColin Finck ttnmdi.lpszText = ttnmdi.szText; 436c2c66affSColin Finck ttnmdi.uFlags = toolPtr->uFlags; 437c2c66affSColin Finck ttnmdi.lParam = toolPtr->lParam; 438c2c66affSColin Finck 439c2c66affSColin Finck TRACE("hdr.idFrom = %lx\n", ttnmdi.hdr.idFrom); 440c2c66affSColin Finck SendMessageW(toolPtr->hwnd, WM_NOTIFY, toolPtr->uId, (LPARAM)&ttnmdi); 441c2c66affSColin Finck 442c2c66affSColin Finck if (IS_INTRESOURCE(ttnmdi.lpszText)) { 443c2c66affSColin Finck LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText), 444c2c66affSColin Finck buffer, INFOTIPSIZE); 445c2c66affSColin Finck if (ttnmdi.uFlags & TTF_DI_SETITEM) { 446c2c66affSColin Finck toolPtr->hinst = ttnmdi.hinst; 447c2c66affSColin Finck toolPtr->lpszText = ttnmdi.lpszText; 448c2c66affSColin Finck } 449c2c66affSColin Finck } 450c2c66affSColin Finck else if (ttnmdi.lpszText == 0) { 451c2c66affSColin Finck buffer[0] = '\0'; 452c2c66affSColin Finck } 453c2c66affSColin Finck else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKW) { 454c2c66affSColin Finck Str_GetPtrW(ttnmdi.lpszText, buffer, INFOTIPSIZE); 455c2c66affSColin Finck if (ttnmdi.uFlags & TTF_DI_SETITEM) { 456c2c66affSColin Finck toolPtr->hinst = 0; 457c2c66affSColin Finck toolPtr->lpszText = NULL; 458c2c66affSColin Finck Str_SetPtrW(&toolPtr->lpszText, buffer); 459c2c66affSColin Finck } 460c2c66affSColin Finck } 461c2c66affSColin Finck else { 462edd99e8cSAmine Khaldi ERR("recursive text callback\n"); 463c2c66affSColin Finck buffer[0] = '\0'; 464c2c66affSColin Finck } 465c2c66affSColin Finck 466c2c66affSColin Finck /* no text available - try calling parent instead as per native */ 467c2c66affSColin Finck /* FIXME: Unsure if SETITEM should save the value or not */ 468c2c66affSColin Finck if (buffer[0] == 0x00) { 469c2c66affSColin Finck 470c2c66affSColin Finck SendMessageW(GetParent(toolPtr->hwnd), WM_NOTIFY, toolPtr->uId, (LPARAM)&ttnmdi); 471c2c66affSColin Finck 472c2c66affSColin Finck if (IS_INTRESOURCE(ttnmdi.lpszText)) { 473c2c66affSColin Finck LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText), 474c2c66affSColin Finck buffer, INFOTIPSIZE); 475c2c66affSColin Finck } else if (ttnmdi.lpszText && 476c2c66affSColin Finck ttnmdi.lpszText != LPSTR_TEXTCALLBACKW) { 477c2c66affSColin Finck Str_GetPtrW(ttnmdi.lpszText, buffer, INFOTIPSIZE); 478c2c66affSColin Finck } 479c2c66affSColin Finck } 480c2c66affSColin Finck 481c2c66affSColin Finck } 482c2c66affSColin Finck 483c2c66affSColin Finck static void 484c2c66affSColin Finck TOOLTIPS_GetTipText (const TOOLTIPS_INFO *infoPtr, INT nTool, WCHAR *buffer) 485c2c66affSColin Finck { 486c2c66affSColin Finck TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool]; 487c2c66affSColin Finck 488c2c66affSColin Finck if (IS_INTRESOURCE(toolPtr->lpszText)) { 489c2c66affSColin Finck /* load a resource */ 490c2c66affSColin Finck TRACE("load res string %p %x\n", 491c2c66affSColin Finck toolPtr->hinst, LOWORD(toolPtr->lpszText)); 492c2c66affSColin Finck if (!LoadStringW (toolPtr->hinst, LOWORD(toolPtr->lpszText), buffer, INFOTIPSIZE)) 493c2c66affSColin Finck buffer[0] = '\0'; 494c2c66affSColin Finck } 495c2c66affSColin Finck else if (toolPtr->lpszText) { 496c2c66affSColin Finck if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) { 497c2c66affSColin Finck if (toolPtr->bNotifyUnicode) 498c2c66affSColin Finck TOOLTIPS_GetDispInfoW(infoPtr, toolPtr, buffer); 499c2c66affSColin Finck else 500c2c66affSColin Finck TOOLTIPS_GetDispInfoA(infoPtr, toolPtr, buffer); 501c2c66affSColin Finck } 502c2c66affSColin Finck else { 503c2c66affSColin Finck /* the item is a usual (unicode) text */ 504c2c66affSColin Finck lstrcpynW (buffer, toolPtr->lpszText, INFOTIPSIZE); 505c2c66affSColin Finck } 506c2c66affSColin Finck } 507c2c66affSColin Finck else { 508c2c66affSColin Finck /* no text available */ 509c2c66affSColin Finck buffer[0] = '\0'; 510c2c66affSColin Finck } 511c2c66affSColin Finck 512c2c66affSColin Finck if (!(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & TTS_NOPREFIX)) { 513c2c66affSColin Finck WCHAR *ptrW; 514c2c66affSColin Finck if ((ptrW = strchrW(buffer, '\t'))) 515c2c66affSColin Finck *ptrW = 0; 516c2c66affSColin Finck } 517c2c66affSColin Finck 518c2c66affSColin Finck TRACE("%s\n", debugstr_w(buffer)); 519c2c66affSColin Finck } 520c2c66affSColin Finck 521c2c66affSColin Finck 522c2c66affSColin Finck static void 523c2c66affSColin Finck TOOLTIPS_CalcTipSize (const TOOLTIPS_INFO *infoPtr, LPSIZE lpSize) 524c2c66affSColin Finck { 525c2c66affSColin Finck HDC hdc; 526c2c66affSColin Finck HFONT hOldFont; 527c2c66affSColin Finck DWORD style = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); 528c2c66affSColin Finck UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT; 529c2c66affSColin Finck RECT rc = {0, 0, 0, 0}; 530c2c66affSColin Finck SIZE title = {0, 0}; 531c2c66affSColin Finck 532c2c66affSColin Finck if (infoPtr->nMaxTipWidth > -1) { 533c2c66affSColin Finck rc.right = infoPtr->nMaxTipWidth; 534c2c66affSColin Finck uFlags |= DT_WORDBREAK; 535c2c66affSColin Finck } 536c2c66affSColin Finck if (style & TTS_NOPREFIX) 537c2c66affSColin Finck uFlags |= DT_NOPREFIX; 538c2c66affSColin Finck TRACE("%s\n", debugstr_w(infoPtr->szTipText)); 539c2c66affSColin Finck 540c2c66affSColin Finck hdc = GetDC (infoPtr->hwndSelf); 541c2c66affSColin Finck if (infoPtr->pszTitle) 542c2c66affSColin Finck { 543c2c66affSColin Finck RECT rcTitle = {0, 0, 0, 0}; 544c2c66affSColin Finck TRACE("title %s\n", debugstr_w(infoPtr->pszTitle)); 545c2c66affSColin Finck if (infoPtr->hTitleIcon) 546c2c66affSColin Finck { 547c2c66affSColin Finck title.cx = ICON_WIDTH; 548c2c66affSColin Finck title.cy = ICON_HEIGHT; 549c2c66affSColin Finck } 550c2c66affSColin Finck if (title.cx != 0) title.cx += BALLOON_ICON_TITLE_SPACING; 551c2c66affSColin Finck hOldFont = SelectObject (hdc, infoPtr->hTitleFont); 552c2c66affSColin Finck DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT); 553c2c66affSColin Finck SelectObject (hdc, hOldFont); 554c2c66affSColin Finck title.cy = max(title.cy, rcTitle.bottom - rcTitle.top) + BALLOON_TITLE_TEXT_SPACING; 555c2c66affSColin Finck title.cx += (rcTitle.right - rcTitle.left); 556c2c66affSColin Finck } 557c2c66affSColin Finck hOldFont = SelectObject (hdc, infoPtr->hFont); 558c2c66affSColin Finck DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags); 559c2c66affSColin Finck SelectObject (hdc, hOldFont); 560c2c66affSColin Finck ReleaseDC (infoPtr->hwndSelf, hdc); 561c2c66affSColin Finck 562c2c66affSColin Finck if ((style & TTS_BALLOON) || infoPtr->pszTitle) 563c2c66affSColin Finck { 564c2c66affSColin Finck lpSize->cx = max(rc.right - rc.left, title.cx) + 2*BALLOON_TEXT_MARGIN + 565c2c66affSColin Finck infoPtr->rcMargin.left + infoPtr->rcMargin.right; 566c2c66affSColin Finck lpSize->cy = title.cy + rc.bottom - rc.top + 2*BALLOON_TEXT_MARGIN + 567c2c66affSColin Finck infoPtr->rcMargin.bottom + infoPtr->rcMargin.top + 568c2c66affSColin Finck BALLOON_STEMHEIGHT; 569c2c66affSColin Finck } 570c2c66affSColin Finck else 571c2c66affSColin Finck { 572c2c66affSColin Finck lpSize->cx = rc.right - rc.left + 2*NORMAL_TEXT_MARGIN + 573c2c66affSColin Finck infoPtr->rcMargin.left + infoPtr->rcMargin.right; 574c2c66affSColin Finck lpSize->cy = rc.bottom - rc.top + 2*NORMAL_TEXT_MARGIN + 575c2c66affSColin Finck infoPtr->rcMargin.bottom + infoPtr->rcMargin.top; 576c2c66affSColin Finck } 577c2c66affSColin Finck } 578c2c66affSColin Finck 579c2c66affSColin Finck 580c2c66affSColin Finck static void 581c2c66affSColin Finck TOOLTIPS_Show (TOOLTIPS_INFO *infoPtr, BOOL track_activate) 582c2c66affSColin Finck { 583c2c66affSColin Finck TTTOOL_INFO *toolPtr; 584c2c66affSColin Finck HMONITOR monitor; 585c2c66affSColin Finck MONITORINFO mon_info; 586c2c66affSColin Finck RECT rect; 587c2c66affSColin Finck SIZE size; 588c2c66affSColin Finck NMHDR hdr; 589c2c66affSColin Finck int ptfx = 0; 590c2c66affSColin Finck DWORD style = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); 591edd99e8cSAmine Khaldi INT nTool, current; 592c2c66affSColin Finck 593c2c66affSColin Finck if (track_activate) 594c2c66affSColin Finck { 595c2c66affSColin Finck if (infoPtr->nTrackTool == -1) 596c2c66affSColin Finck { 597edd99e8cSAmine Khaldi TRACE("invalid tracking tool %d\n", infoPtr->nTrackTool); 598c2c66affSColin Finck return; 599c2c66affSColin Finck } 600c2c66affSColin Finck nTool = infoPtr->nTrackTool; 601c2c66affSColin Finck } 602c2c66affSColin Finck else 603c2c66affSColin Finck { 604c2c66affSColin Finck if (infoPtr->nTool == -1) 605c2c66affSColin Finck { 606edd99e8cSAmine Khaldi TRACE("invalid tool %d\n", infoPtr->nTool); 607c2c66affSColin Finck return; 608c2c66affSColin Finck } 609c2c66affSColin Finck nTool = infoPtr->nTool; 610c2c66affSColin Finck } 611c2c66affSColin Finck 612edd99e8cSAmine Khaldi TRACE("Show tooltip pre %d, %p\n", nTool, infoPtr->hwndSelf); 613edd99e8cSAmine Khaldi 614edd99e8cSAmine Khaldi current = infoPtr->nCurrentTool; 615edd99e8cSAmine Khaldi if (!track_activate) 616edd99e8cSAmine Khaldi infoPtr->nCurrentTool = infoPtr->nTool; 617c2c66affSColin Finck 618c2c66affSColin Finck TOOLTIPS_GetTipText (infoPtr, nTool, infoPtr->szTipText); 619c2c66affSColin Finck 620c2c66affSColin Finck if (infoPtr->szTipText[0] == '\0') 621edd99e8cSAmine Khaldi { 622edd99e8cSAmine Khaldi infoPtr->nCurrentTool = current; 623c2c66affSColin Finck return; 624edd99e8cSAmine Khaldi } 625c2c66affSColin Finck 626c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 627c2c66affSColin Finck TOOLTIPS_CalcTipSize (infoPtr, &size); 628*b3fb8555SGiannis Adamopoulos 629*b3fb8555SGiannis Adamopoulos TRACE("Show tooltip %d, %s, size %d x %d\n", nTool, debugstr_w(infoPtr->szTipText), 630*b3fb8555SGiannis Adamopoulos size.cx, size.cy); 631c2c66affSColin Finck 632c2c66affSColin Finck if (track_activate && (toolPtr->uFlags & TTF_TRACK)) 633c2c66affSColin Finck { 634c2c66affSColin Finck rect.left = infoPtr->xTrackPos; 635c2c66affSColin Finck rect.top = infoPtr->yTrackPos; 636c2c66affSColin Finck ptfx = rect.left; 637c2c66affSColin Finck 638c2c66affSColin Finck if (toolPtr->uFlags & TTF_CENTERTIP) 639c2c66affSColin Finck { 640c2c66affSColin Finck rect.left -= (size.cx / 2); 641c2c66affSColin Finck if (!(style & TTS_BALLOON)) 642c2c66affSColin Finck rect.top -= (size.cy / 2); 643c2c66affSColin Finck } 644c2c66affSColin Finck if (!(infoPtr->bToolBelow = (infoPtr->yTrackPos + size.cy <= GetSystemMetrics(SM_CYSCREEN)))) 645c2c66affSColin Finck rect.top -= size.cy; 646c2c66affSColin Finck 647c2c66affSColin Finck if (!(toolPtr->uFlags & TTF_ABSOLUTE)) 648c2c66affSColin Finck { 649c2c66affSColin Finck if (style & TTS_BALLOON) 650c2c66affSColin Finck rect.left -= BALLOON_STEMINDENT; 651c2c66affSColin Finck else 652c2c66affSColin Finck { 653c2c66affSColin Finck RECT rcTool; 654c2c66affSColin Finck 655c2c66affSColin Finck if (toolPtr->uFlags & TTF_IDISHWND) 656c2c66affSColin Finck GetWindowRect ((HWND)toolPtr->uId, &rcTool); 657c2c66affSColin Finck else 658c2c66affSColin Finck { 659c2c66affSColin Finck rcTool = toolPtr->rect; 660c2c66affSColin Finck MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rcTool, 2); 661c2c66affSColin Finck } 662c2c66affSColin Finck 663c2c66affSColin Finck /* smart placement */ 664c2c66affSColin Finck if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) && 665c2c66affSColin Finck (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom)) 666c2c66affSColin Finck rect.left = rcTool.right; 667c2c66affSColin Finck } 668c2c66affSColin Finck } 669c2c66affSColin Finck } 670c2c66affSColin Finck else 671c2c66affSColin Finck { 672c2c66affSColin Finck if (toolPtr->uFlags & TTF_CENTERTIP) 673c2c66affSColin Finck { 674c2c66affSColin Finck RECT rc; 675c2c66affSColin Finck 676c2c66affSColin Finck if (toolPtr->uFlags & TTF_IDISHWND) 677c2c66affSColin Finck GetWindowRect ((HWND)toolPtr->uId, &rc); 678c2c66affSColin Finck else { 679c2c66affSColin Finck rc = toolPtr->rect; 680c2c66affSColin Finck MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2); 681c2c66affSColin Finck } 682c2c66affSColin Finck rect.left = (rc.left + rc.right - size.cx) / 2; 683c2c66affSColin Finck if (style & TTS_BALLOON) 684c2c66affSColin Finck { 685c2c66affSColin Finck ptfx = rc.left + ((rc.right - rc.left) / 2); 686c2c66affSColin Finck 687c2c66affSColin Finck /* CENTERTIP ballon tooltips default to below the field 688c2c66affSColin Finck * if they fit on the screen */ 689c2c66affSColin Finck if (rc.bottom + size.cy > GetSystemMetrics(SM_CYSCREEN)) 690c2c66affSColin Finck { 691c2c66affSColin Finck rect.top = rc.top - size.cy; 692c2c66affSColin Finck infoPtr->bToolBelow = FALSE; 693c2c66affSColin Finck } 694c2c66affSColin Finck else 695c2c66affSColin Finck { 696c2c66affSColin Finck infoPtr->bToolBelow = TRUE; 697c2c66affSColin Finck rect.top = rc.bottom; 698c2c66affSColin Finck } 699c2c66affSColin Finck rect.left = max(0, rect.left - BALLOON_STEMINDENT); 700c2c66affSColin Finck } 701c2c66affSColin Finck else 702c2c66affSColin Finck { 703c2c66affSColin Finck rect.top = rc.bottom + 2; 704c2c66affSColin Finck infoPtr->bToolBelow = TRUE; 705c2c66affSColin Finck } 706c2c66affSColin Finck } 707c2c66affSColin Finck else 708c2c66affSColin Finck { 709c2c66affSColin Finck GetCursorPos ((LPPOINT)&rect); 710c2c66affSColin Finck if (style & TTS_BALLOON) 711c2c66affSColin Finck { 712c2c66affSColin Finck ptfx = rect.left; 713c2c66affSColin Finck if(rect.top - size.cy >= 0) 714c2c66affSColin Finck { 715c2c66affSColin Finck rect.top -= size.cy; 716c2c66affSColin Finck infoPtr->bToolBelow = FALSE; 717c2c66affSColin Finck } 718c2c66affSColin Finck else 719c2c66affSColin Finck { 720c2c66affSColin Finck infoPtr->bToolBelow = TRUE; 721c2c66affSColin Finck rect.top += 20; 722c2c66affSColin Finck } 723c2c66affSColin Finck rect.left = max(0, rect.left - BALLOON_STEMINDENT); 724c2c66affSColin Finck } 725c2c66affSColin Finck else 726c2c66affSColin Finck { 727c2c66affSColin Finck rect.top += 20; 728c2c66affSColin Finck infoPtr->bToolBelow = TRUE; 729c2c66affSColin Finck } 730c2c66affSColin Finck } 731c2c66affSColin Finck } 732c2c66affSColin Finck 733c2c66affSColin Finck TRACE("pos %d - %d\n", rect.left, rect.top); 734c2c66affSColin Finck 735c2c66affSColin Finck rect.right = rect.left + size.cx; 736c2c66affSColin Finck rect.bottom = rect.top + size.cy; 737c2c66affSColin Finck 738c2c66affSColin Finck /* check position */ 739c2c66affSColin Finck 740c2c66affSColin Finck monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY ); 741c2c66affSColin Finck mon_info.cbSize = sizeof(mon_info); 742c2c66affSColin Finck GetMonitorInfoW( monitor, &mon_info ); 743c2c66affSColin Finck 744c2c66affSColin Finck if( rect.right > mon_info.rcWork.right ) { 745c2c66affSColin Finck rect.left -= rect.right - mon_info.rcWork.right + 2; 746c2c66affSColin Finck rect.right = mon_info.rcWork.right - 2; 747c2c66affSColin Finck } 748c2c66affSColin Finck if (rect.left < mon_info.rcWork.left) rect.left = mon_info.rcWork.left; 749c2c66affSColin Finck 750c2c66affSColin Finck if( rect.bottom > mon_info.rcWork.bottom ) { 751c2c66affSColin Finck RECT rc; 752c2c66affSColin Finck 753c2c66affSColin Finck if (toolPtr->uFlags & TTF_IDISHWND) 754c2c66affSColin Finck GetWindowRect ((HWND)toolPtr->uId, &rc); 755c2c66affSColin Finck else { 756c2c66affSColin Finck rc = toolPtr->rect; 757c2c66affSColin Finck MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2); 758c2c66affSColin Finck } 759c2c66affSColin Finck rect.bottom = rc.top - 2; 760c2c66affSColin Finck rect.top = rect.bottom - size.cy; 761c2c66affSColin Finck } 762c2c66affSColin Finck 763c2c66affSColin Finck AdjustWindowRectEx (&rect, GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE), 764c2c66affSColin Finck FALSE, GetWindowLongW (infoPtr->hwndSelf, GWL_EXSTYLE)); 765c2c66affSColin Finck 766c2c66affSColin Finck if (style & TTS_BALLOON) 767c2c66affSColin Finck { 768c2c66affSColin Finck HRGN hRgn; 769c2c66affSColin Finck HRGN hrStem; 770c2c66affSColin Finck POINT pts[3]; 771c2c66affSColin Finck 772c2c66affSColin Finck ptfx -= rect.left; 773c2c66affSColin Finck 774c2c66affSColin Finck if(infoPtr->bToolBelow) 775c2c66affSColin Finck { 776c2c66affSColin Finck pts[0].x = ptfx; 777c2c66affSColin Finck pts[0].y = 0; 778c2c66affSColin Finck pts[1].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2)); 779c2c66affSColin Finck pts[1].y = BALLOON_STEMHEIGHT; 780c2c66affSColin Finck pts[2].x = pts[1].x + BALLOON_STEMWIDTH; 781c2c66affSColin Finck pts[2].y = pts[1].y; 782c2c66affSColin Finck if(pts[2].x > (rect.right - rect.left) - BALLOON_STEMINDENT) 783c2c66affSColin Finck { 784c2c66affSColin Finck pts[2].x = (rect.right - rect.left) - BALLOON_STEMINDENT; 785c2c66affSColin Finck pts[1].x = pts[2].x - BALLOON_STEMWIDTH; 786c2c66affSColin Finck } 787c2c66affSColin Finck } 788c2c66affSColin Finck else 789c2c66affSColin Finck { 790c2c66affSColin Finck pts[0].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2)); 791c2c66affSColin Finck pts[0].y = (rect.bottom - rect.top) - BALLOON_STEMHEIGHT; 792c2c66affSColin Finck pts[1].x = pts[0].x + BALLOON_STEMWIDTH; 793c2c66affSColin Finck pts[1].y = pts[0].y; 794c2c66affSColin Finck pts[2].x = ptfx; 795c2c66affSColin Finck pts[2].y = (rect.bottom - rect.top); 796c2c66affSColin Finck if(pts[1].x > (rect.right - rect.left) - BALLOON_STEMINDENT) 797c2c66affSColin Finck { 798c2c66affSColin Finck pts[1].x = (rect.right - rect.left) - BALLOON_STEMINDENT; 799c2c66affSColin Finck pts[0].x = pts[1].x - BALLOON_STEMWIDTH; 800c2c66affSColin Finck } 801c2c66affSColin Finck } 802c2c66affSColin Finck 803*b3fb8555SGiannis Adamopoulos hrStem = CreatePolygonRgn(pts, ARRAY_SIZE(pts), ALTERNATE); 804c2c66affSColin Finck 805c2c66affSColin Finck hRgn = CreateRoundRectRgn(0, 806c2c66affSColin Finck (infoPtr->bToolBelow ? BALLOON_STEMHEIGHT : 0), 807c2c66affSColin Finck rect.right - rect.left, 808c2c66affSColin Finck (infoPtr->bToolBelow ? rect.bottom - rect.top : rect.bottom - rect.top - BALLOON_STEMHEIGHT), 809c2c66affSColin Finck BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS); 810c2c66affSColin Finck 811c2c66affSColin Finck CombineRgn(hRgn, hRgn, hrStem, RGN_OR); 812c2c66affSColin Finck DeleteObject(hrStem); 813c2c66affSColin Finck 814c2c66affSColin Finck SetWindowRgn(infoPtr->hwndSelf, hRgn, FALSE); 815c2c66affSColin Finck /* we don't free the region handle as the system deletes it when 816c2c66affSColin Finck * it is no longer needed */ 817c2c66affSColin Finck } 818c2c66affSColin Finck 819*b3fb8555SGiannis Adamopoulos SetWindowPos (infoPtr->hwndSelf, NULL, rect.left, rect.top, 820*b3fb8555SGiannis Adamopoulos rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE); 821*b3fb8555SGiannis Adamopoulos 822*b3fb8555SGiannis Adamopoulos hdr.hwndFrom = infoPtr->hwndSelf; 823*b3fb8555SGiannis Adamopoulos hdr.idFrom = toolPtr->uId; 824*b3fb8555SGiannis Adamopoulos hdr.code = TTN_SHOW; 825*b3fb8555SGiannis Adamopoulos SendMessageW (toolPtr->hwnd, WM_NOTIFY, toolPtr->uId, (LPARAM)&hdr); 826*b3fb8555SGiannis Adamopoulos 827*b3fb8555SGiannis Adamopoulos SetWindowPos (infoPtr->hwndSelf, HWND_TOPMOST, 0, 0, 0, 0, 828*b3fb8555SGiannis Adamopoulos SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOACTIVATE); 829c2c66affSColin Finck 830c2c66affSColin Finck /* repaint the tooltip */ 831c2c66affSColin Finck InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); 832c2c66affSColin Finck UpdateWindow(infoPtr->hwndSelf); 833c2c66affSColin Finck 834c2c66affSColin Finck if (!track_activate) 835c2c66affSColin Finck { 836c2c66affSColin Finck SetTimer (infoPtr->hwndSelf, ID_TIMERPOP, infoPtr->nAutoPopTime, 0); 837edd99e8cSAmine Khaldi TRACE("timer 2 started\n"); 838c2c66affSColin Finck SetTimer (infoPtr->hwndSelf, ID_TIMERLEAVE, infoPtr->nReshowTime, 0); 839edd99e8cSAmine Khaldi TRACE("timer 3 started\n"); 840c2c66affSColin Finck } 841c2c66affSColin Finck } 842c2c66affSColin Finck 843c2c66affSColin Finck 844c2c66affSColin Finck static void 845c2c66affSColin Finck TOOLTIPS_Hide (TOOLTIPS_INFO *infoPtr) 846c2c66affSColin Finck { 847c2c66affSColin Finck TTTOOL_INFO *toolPtr; 848c2c66affSColin Finck NMHDR hdr; 849c2c66affSColin Finck 850edd99e8cSAmine Khaldi TRACE("Hide tooltip %d, %p.\n", infoPtr->nCurrentTool, infoPtr->hwndSelf); 851c2c66affSColin Finck 852c2c66affSColin Finck if (infoPtr->nCurrentTool == -1) 853c2c66affSColin Finck return; 854c2c66affSColin Finck 855c2c66affSColin Finck toolPtr = &infoPtr->tools[infoPtr->nCurrentTool]; 856c2c66affSColin Finck KillTimer (infoPtr->hwndSelf, ID_TIMERPOP); 857c2c66affSColin Finck 858c2c66affSColin Finck hdr.hwndFrom = infoPtr->hwndSelf; 859c2c66affSColin Finck hdr.idFrom = toolPtr->uId; 860c2c66affSColin Finck hdr.code = TTN_POP; 861c2c66affSColin Finck SendMessageW (toolPtr->hwnd, WM_NOTIFY, toolPtr->uId, (LPARAM)&hdr); 862c2c66affSColin Finck 863c2c66affSColin Finck infoPtr->nCurrentTool = -1; 864c2c66affSColin Finck 865c2c66affSColin Finck SetWindowPos (infoPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0, 866c2c66affSColin Finck SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); 867c2c66affSColin Finck } 868c2c66affSColin Finck 869c2c66affSColin Finck 870c2c66affSColin Finck static void 871c2c66affSColin Finck TOOLTIPS_TrackShow (TOOLTIPS_INFO *infoPtr) 872c2c66affSColin Finck { 873c2c66affSColin Finck TOOLTIPS_Show(infoPtr, TRUE); 874c2c66affSColin Finck } 875c2c66affSColin Finck 876c2c66affSColin Finck 877c2c66affSColin Finck static void 878c2c66affSColin Finck TOOLTIPS_TrackHide (const TOOLTIPS_INFO *infoPtr) 879c2c66affSColin Finck { 880c2c66affSColin Finck TTTOOL_INFO *toolPtr; 881c2c66affSColin Finck NMHDR hdr; 882c2c66affSColin Finck 883c2c66affSColin Finck TRACE("hide tracking tooltip %d\n", infoPtr->nTrackTool); 884c2c66affSColin Finck 885c2c66affSColin Finck if (infoPtr->nTrackTool == -1) 886c2c66affSColin Finck return; 887c2c66affSColin Finck 888c2c66affSColin Finck toolPtr = &infoPtr->tools[infoPtr->nTrackTool]; 889c2c66affSColin Finck 890c2c66affSColin Finck hdr.hwndFrom = infoPtr->hwndSelf; 891c2c66affSColin Finck hdr.idFrom = toolPtr->uId; 892c2c66affSColin Finck hdr.code = TTN_POP; 893c2c66affSColin Finck SendMessageW (toolPtr->hwnd, WM_NOTIFY, toolPtr->uId, (LPARAM)&hdr); 894c2c66affSColin Finck 895c2c66affSColin Finck SetWindowPos (infoPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0, 896c2c66affSColin Finck SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); 897c2c66affSColin Finck } 898c2c66affSColin Finck 899c2c66affSColin Finck /* Structure layout is the same for TTTOOLINFOW and TTTOOLINFOA, 900c2c66affSColin Finck this helper is used in both cases. */ 901c2c66affSColin Finck static INT 902c2c66affSColin Finck TOOLTIPS_GetToolFromInfoT (const TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *lpToolInfo) 903c2c66affSColin Finck { 904c2c66affSColin Finck TTTOOL_INFO *toolPtr; 905c2c66affSColin Finck UINT nTool; 906c2c66affSColin Finck 907c2c66affSColin Finck for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { 908c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 909c2c66affSColin Finck 910c2c66affSColin Finck if (!(toolPtr->uFlags & TTF_IDISHWND) && 911c2c66affSColin Finck (lpToolInfo->hwnd == toolPtr->hwnd) && 912c2c66affSColin Finck (lpToolInfo->uId == toolPtr->uId)) 913c2c66affSColin Finck return nTool; 914c2c66affSColin Finck } 915c2c66affSColin Finck 916c2c66affSColin Finck for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { 917c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 918c2c66affSColin Finck 919c2c66affSColin Finck if ((toolPtr->uFlags & TTF_IDISHWND) && 920c2c66affSColin Finck (lpToolInfo->uId == toolPtr->uId)) 921c2c66affSColin Finck return nTool; 922c2c66affSColin Finck } 923c2c66affSColin Finck 924c2c66affSColin Finck return -1; 925c2c66affSColin Finck } 926c2c66affSColin Finck 927c2c66affSColin Finck 928c2c66affSColin Finck static INT 929c2c66affSColin Finck TOOLTIPS_GetToolFromPoint (const TOOLTIPS_INFO *infoPtr, HWND hwnd, const POINT *lpPt) 930c2c66affSColin Finck { 931c2c66affSColin Finck TTTOOL_INFO *toolPtr; 932c2c66affSColin Finck UINT nTool; 933c2c66affSColin Finck 934c2c66affSColin Finck for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { 935c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 936c2c66affSColin Finck 937c2c66affSColin Finck if (!(toolPtr->uFlags & TTF_IDISHWND)) { 938c2c66affSColin Finck if (hwnd != toolPtr->hwnd) 939c2c66affSColin Finck continue; 940c2c66affSColin Finck if (!PtInRect (&toolPtr->rect, *lpPt)) 941c2c66affSColin Finck continue; 942c2c66affSColin Finck return nTool; 943c2c66affSColin Finck } 944c2c66affSColin Finck } 945c2c66affSColin Finck 946c2c66affSColin Finck for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { 947c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 948c2c66affSColin Finck 949c2c66affSColin Finck if (toolPtr->uFlags & TTF_IDISHWND) { 950c2c66affSColin Finck if ((HWND)toolPtr->uId == hwnd) 951c2c66affSColin Finck return nTool; 952c2c66affSColin Finck } 953c2c66affSColin Finck } 954c2c66affSColin Finck 955c2c66affSColin Finck return -1; 956c2c66affSColin Finck } 957c2c66affSColin Finck 958c2c66affSColin Finck static inline void 959edd99e8cSAmine Khaldi TOOLTIPS_CopyInfoT (const TOOLTIPS_INFO *infoPtr, INT index, TTTOOLINFOW *ti, BOOL isW) 960c2c66affSColin Finck { 961edd99e8cSAmine Khaldi const TTTOOL_INFO *toolPtr = &infoPtr->tools[index]; 962edd99e8cSAmine Khaldi 963edd99e8cSAmine Khaldi ti->uFlags = toolPtr->uFlags; 964edd99e8cSAmine Khaldi ti->hwnd = toolPtr->hwnd; 965edd99e8cSAmine Khaldi ti->uId = toolPtr->uId; 966edd99e8cSAmine Khaldi ti->rect = toolPtr->rect; 967edd99e8cSAmine Khaldi ti->hinst = toolPtr->hinst; 968edd99e8cSAmine Khaldi 969c2c66affSColin Finck if (ti->lpszText) { 970c2c66affSColin Finck if (toolPtr->lpszText == NULL || 971c2c66affSColin Finck IS_INTRESOURCE(toolPtr->lpszText) || 972c2c66affSColin Finck toolPtr->lpszText == LPSTR_TEXTCALLBACKW) 973c2c66affSColin Finck ti->lpszText = toolPtr->lpszText; 974c2c66affSColin Finck else if (isW) 975c2c66affSColin Finck strcpyW (ti->lpszText, toolPtr->lpszText); 976c2c66affSColin Finck else 977c2c66affSColin Finck /* ANSI version, the buffer is maximum 80 bytes without null. */ 978c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, toolPtr->lpszText, -1, 979c2c66affSColin Finck (LPSTR)ti->lpszText, MAX_TEXT_SIZE_A, NULL, NULL); 980c2c66affSColin Finck } 981edd99e8cSAmine Khaldi 982edd99e8cSAmine Khaldi if (ti->cbSize >= TTTOOLINFOW_V2_SIZE) 983edd99e8cSAmine Khaldi ti->lParam = toolPtr->lParam; 984edd99e8cSAmine Khaldi 985edd99e8cSAmine Khaldi /* lpReserved is intentionally not set. */ 986c2c66affSColin Finck } 987c2c66affSColin Finck 988c2c66affSColin Finck static BOOL 989c2c66affSColin Finck TOOLTIPS_IsWindowActive (HWND hwnd) 990c2c66affSColin Finck { 991c2c66affSColin Finck HWND hwndActive = GetActiveWindow (); 992c2c66affSColin Finck if (!hwndActive) 993c2c66affSColin Finck return FALSE; 994c2c66affSColin Finck if (hwndActive == hwnd) 995c2c66affSColin Finck return TRUE; 996c2c66affSColin Finck return IsChild (hwndActive, hwnd); 997c2c66affSColin Finck } 998c2c66affSColin Finck 999c2c66affSColin Finck 1000c2c66affSColin Finck static INT 1001c2c66affSColin Finck TOOLTIPS_CheckTool (const TOOLTIPS_INFO *infoPtr, BOOL bShowTest) 1002c2c66affSColin Finck { 1003c2c66affSColin Finck POINT pt; 1004c2c66affSColin Finck HWND hwndTool; 1005c2c66affSColin Finck INT nTool; 1006c2c66affSColin Finck 1007c2c66affSColin Finck GetCursorPos (&pt); 1008c2c66affSColin Finck hwndTool = (HWND)SendMessageW (infoPtr->hwndSelf, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt); 1009c2c66affSColin Finck if (hwndTool == 0) 1010c2c66affSColin Finck return -1; 1011c2c66affSColin Finck 1012c2c66affSColin Finck ScreenToClient (hwndTool, &pt); 1013c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt); 1014c2c66affSColin Finck if (nTool == -1) 1015c2c66affSColin Finck return -1; 1016c2c66affSColin Finck 1017c2c66affSColin Finck if (!(GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) 1018c2c66affSColin Finck { 1019c2c66affSColin Finck TTTOOL_INFO *ti = &infoPtr->tools[nTool]; 1020c2c66affSColin Finck HWND hwnd = (ti->uFlags & TTF_IDISHWND) ? (HWND)ti->uId : ti->hwnd; 1021c2c66affSColin Finck 1022c2c66affSColin Finck if (!TOOLTIPS_IsWindowActive(hwnd)) 1023c2c66affSColin Finck { 1024c2c66affSColin Finck TRACE("not active: hwnd %p, parent %p, active %p\n", 1025c2c66affSColin Finck hwnd, GetParent(hwnd), GetActiveWindow()); 1026c2c66affSColin Finck return -1; 1027c2c66affSColin Finck } 1028c2c66affSColin Finck } 1029c2c66affSColin Finck 1030c2c66affSColin Finck TRACE("tool %d\n", nTool); 1031c2c66affSColin Finck 1032c2c66affSColin Finck return nTool; 1033c2c66affSColin Finck } 1034c2c66affSColin Finck 1035c2c66affSColin Finck 1036c2c66affSColin Finck static LRESULT 1037c2c66affSColin Finck TOOLTIPS_Activate (TOOLTIPS_INFO *infoPtr, BOOL activate) 1038c2c66affSColin Finck { 1039c2c66affSColin Finck infoPtr->bActive = activate; 1040c2c66affSColin Finck 1041edd99e8cSAmine Khaldi TRACE("activate %d\n", activate); 1042c2c66affSColin Finck 1043c2c66affSColin Finck if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1)) 1044c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 1045c2c66affSColin Finck 1046c2c66affSColin Finck return 0; 1047c2c66affSColin Finck } 1048c2c66affSColin Finck 1049c2c66affSColin Finck 1050c2c66affSColin Finck static LRESULT 1051c2c66affSColin Finck TOOLTIPS_AddToolT (TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *ti, BOOL isW) 1052c2c66affSColin Finck { 1053c2c66affSColin Finck TTTOOL_INFO *toolPtr; 1054c2c66affSColin Finck INT nResult; 1055c2c66affSColin Finck 1056c2c66affSColin Finck if (!ti) return FALSE; 1057c2c66affSColin Finck 1058edd99e8cSAmine Khaldi TRACE("add tool (%p) %p %ld%s\n", infoPtr->hwndSelf, ti->hwnd, ti->uId, 1059c2c66affSColin Finck (ti->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : ""); 1060c2c66affSColin Finck 1061*b3fb8555SGiannis Adamopoulos if (ti->cbSize > TTTOOLINFOW_V3_SIZE && isW) 1062c2c66affSColin Finck return FALSE; 1063c2c66affSColin Finck 1064c2c66affSColin Finck if (infoPtr->uNumTools == 0) { 1065c2c66affSColin Finck infoPtr->tools = Alloc (sizeof(TTTOOL_INFO)); 1066c2c66affSColin Finck toolPtr = infoPtr->tools; 1067c2c66affSColin Finck } 1068c2c66affSColin Finck else { 1069c2c66affSColin Finck TTTOOL_INFO *oldTools = infoPtr->tools; 1070c2c66affSColin Finck infoPtr->tools = 1071c2c66affSColin Finck Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1)); 1072c2c66affSColin Finck memcpy (infoPtr->tools, oldTools, 1073c2c66affSColin Finck infoPtr->uNumTools * sizeof(TTTOOL_INFO)); 1074c2c66affSColin Finck Free (oldTools); 1075c2c66affSColin Finck toolPtr = &infoPtr->tools[infoPtr->uNumTools]; 1076c2c66affSColin Finck } 1077c2c66affSColin Finck 1078c2c66affSColin Finck infoPtr->uNumTools++; 1079c2c66affSColin Finck 1080c2c66affSColin Finck /* copy tool data */ 1081c2c66affSColin Finck toolPtr->uFlags = ti->uFlags; 1082c2c66affSColin Finck toolPtr->uInternalFlags = (ti->uFlags & (TTF_SUBCLASS | TTF_IDISHWND)); 1083c2c66affSColin Finck toolPtr->hwnd = ti->hwnd; 1084c2c66affSColin Finck toolPtr->uId = ti->uId; 1085c2c66affSColin Finck toolPtr->rect = ti->rect; 1086c2c66affSColin Finck toolPtr->hinst = ti->hinst; 1087c2c66affSColin Finck 1088c2c66affSColin Finck if (ti->cbSize >= TTTOOLINFOW_V1_SIZE) { 1089c2c66affSColin Finck if (IS_INTRESOURCE(ti->lpszText)) { 1090c2c66affSColin Finck TRACE("add string id %x\n", LOWORD(ti->lpszText)); 1091c2c66affSColin Finck toolPtr->lpszText = ti->lpszText; 1092c2c66affSColin Finck } 1093c2c66affSColin Finck else if (ti->lpszText) { 1094c2c66affSColin Finck if (TOOLTIPS_IsCallbackString(ti->lpszText, isW)) { 1095edd99e8cSAmine Khaldi TRACE("add CALLBACK\n"); 1096c2c66affSColin Finck toolPtr->lpszText = LPSTR_TEXTCALLBACKW; 1097c2c66affSColin Finck } 1098c2c66affSColin Finck else if (isW) { 1099c2c66affSColin Finck INT len = lstrlenW (ti->lpszText); 1100edd99e8cSAmine Khaldi TRACE("add text %s\n", debugstr_w(ti->lpszText)); 1101c2c66affSColin Finck toolPtr->lpszText = Alloc ((len + 1)*sizeof(WCHAR)); 1102c2c66affSColin Finck strcpyW (toolPtr->lpszText, ti->lpszText); 1103c2c66affSColin Finck } 1104c2c66affSColin Finck else { 1105c2c66affSColin Finck INT len = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ti->lpszText, -1, NULL, 0); 1106edd99e8cSAmine Khaldi TRACE("add text \"%s\"\n", debugstr_a((char *)ti->lpszText)); 1107c2c66affSColin Finck toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); 1108c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, (LPSTR)ti->lpszText, -1, toolPtr->lpszText, len); 1109c2c66affSColin Finck } 1110c2c66affSColin Finck } 1111c2c66affSColin Finck } 1112c2c66affSColin Finck 1113c2c66affSColin Finck if (ti->cbSize >= TTTOOLINFOW_V2_SIZE) 1114c2c66affSColin Finck toolPtr->lParam = ti->lParam; 1115c2c66affSColin Finck 1116c2c66affSColin Finck /* install subclassing hook */ 1117c2c66affSColin Finck if (toolPtr->uInternalFlags & TTF_SUBCLASS) { 1118c2c66affSColin Finck if (toolPtr->uInternalFlags & TTF_IDISHWND) { 1119c2c66affSColin Finck SetWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1, 1120c2c66affSColin Finck (DWORD_PTR)infoPtr->hwndSelf); 1121c2c66affSColin Finck } 1122c2c66affSColin Finck else { 1123c2c66affSColin Finck SetWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1, 1124c2c66affSColin Finck (DWORD_PTR)infoPtr->hwndSelf); 1125c2c66affSColin Finck } 1126edd99e8cSAmine Khaldi TRACE("subclassing installed\n"); 1127c2c66affSColin Finck } 1128c2c66affSColin Finck 1129c2c66affSColin Finck nResult = SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT, 1130c2c66affSColin Finck (WPARAM)infoPtr->hwndSelf, NF_QUERY); 1131c2c66affSColin Finck if (nResult == NFR_ANSI) { 1132c2c66affSColin Finck toolPtr->bNotifyUnicode = FALSE; 1133c2c66affSColin Finck TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n"); 1134c2c66affSColin Finck } else if (nResult == NFR_UNICODE) { 1135c2c66affSColin Finck toolPtr->bNotifyUnicode = TRUE; 1136c2c66affSColin Finck TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n"); 1137c2c66affSColin Finck } else { 1138edd99e8cSAmine Khaldi TRACE (" -- WM_NOTIFYFORMAT returns: %d\n", nResult); 1139c2c66affSColin Finck } 1140c2c66affSColin Finck 1141c2c66affSColin Finck return TRUE; 1142c2c66affSColin Finck } 1143c2c66affSColin Finck 1144edd99e8cSAmine Khaldi static void TOOLTIPS_ResetSubclass (const TTTOOL_INFO *toolPtr) 1145edd99e8cSAmine Khaldi { 1146edd99e8cSAmine Khaldi /* Reset subclassing data. */ 1147edd99e8cSAmine Khaldi if (toolPtr->uInternalFlags & TTF_SUBCLASS) 1148edd99e8cSAmine Khaldi SetWindowSubclass(toolPtr->uInternalFlags & TTF_IDISHWND ? (HWND)toolPtr->uId : toolPtr->hwnd, 1149edd99e8cSAmine Khaldi TOOLTIPS_SubclassProc, 1, 0); 1150edd99e8cSAmine Khaldi } 1151c2c66affSColin Finck 1152c2c66affSColin Finck static LRESULT 1153c2c66affSColin Finck TOOLTIPS_DelToolT (TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *ti, BOOL isW) 1154c2c66affSColin Finck { 1155c2c66affSColin Finck TTTOOL_INFO *toolPtr; 1156c2c66affSColin Finck INT nTool; 1157c2c66affSColin Finck 1158c2c66affSColin Finck if (!ti) return 0; 1159c2c66affSColin Finck if (isW && ti->cbSize > TTTOOLINFOW_V2_SIZE && 1160c2c66affSColin Finck ti->cbSize != TTTOOLINFOW_V3_SIZE) 1161c2c66affSColin Finck return 0; 1162c2c66affSColin Finck if (infoPtr->uNumTools == 0) 1163c2c66affSColin Finck return 0; 1164c2c66affSColin Finck 1165c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, ti); 1166c2c66affSColin Finck 1167c2c66affSColin Finck TRACE("tool %d\n", nTool); 1168c2c66affSColin Finck 1169c2c66affSColin Finck if (nTool == -1) 1170c2c66affSColin Finck return 0; 1171c2c66affSColin Finck 1172c2c66affSColin Finck /* make sure the tooltip has disappeared before deleting it */ 1173c2c66affSColin Finck TOOLTIPS_Hide(infoPtr); 1174c2c66affSColin Finck 1175c2c66affSColin Finck /* delete text string */ 1176c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 1177c2c66affSColin Finck if (toolPtr->lpszText) { 1178c2c66affSColin Finck if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && 1179c2c66affSColin Finck !IS_INTRESOURCE(toolPtr->lpszText) ) 1180c2c66affSColin Finck Free (toolPtr->lpszText); 1181c2c66affSColin Finck } 1182c2c66affSColin Finck 1183edd99e8cSAmine Khaldi TOOLTIPS_ResetSubclass (toolPtr); 1184c2c66affSColin Finck 1185c2c66affSColin Finck /* delete tool from tool list */ 1186c2c66affSColin Finck if (infoPtr->uNumTools == 1) { 1187c2c66affSColin Finck Free (infoPtr->tools); 1188c2c66affSColin Finck infoPtr->tools = NULL; 1189c2c66affSColin Finck } 1190c2c66affSColin Finck else { 1191c2c66affSColin Finck TTTOOL_INFO *oldTools = infoPtr->tools; 1192c2c66affSColin Finck infoPtr->tools = 1193c2c66affSColin Finck Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1)); 1194c2c66affSColin Finck 1195c2c66affSColin Finck if (nTool > 0) 1196c2c66affSColin Finck memcpy (&infoPtr->tools[0], &oldTools[0], 1197c2c66affSColin Finck nTool * sizeof(TTTOOL_INFO)); 1198c2c66affSColin Finck 1199c2c66affSColin Finck if (nTool < infoPtr->uNumTools - 1) 1200c2c66affSColin Finck memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1], 1201c2c66affSColin Finck (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO)); 1202c2c66affSColin Finck 1203c2c66affSColin Finck Free (oldTools); 1204c2c66affSColin Finck } 1205c2c66affSColin Finck 1206c2c66affSColin Finck /* update any indices affected by delete */ 1207c2c66affSColin Finck 1208c2c66affSColin Finck /* destroying tool that mouse was on on last relayed mouse move */ 1209c2c66affSColin Finck if (infoPtr->nTool == nTool) 1210c2c66affSColin Finck /* -1 means no current tool (0 means first tool) */ 1211c2c66affSColin Finck infoPtr->nTool = -1; 1212c2c66affSColin Finck else if (infoPtr->nTool > nTool) 1213c2c66affSColin Finck infoPtr->nTool--; 1214c2c66affSColin Finck 1215c2c66affSColin Finck if (infoPtr->nTrackTool == nTool) 1216c2c66affSColin Finck /* -1 means no current tool (0 means first tool) */ 1217c2c66affSColin Finck infoPtr->nTrackTool = -1; 1218c2c66affSColin Finck else if (infoPtr->nTrackTool > nTool) 1219c2c66affSColin Finck infoPtr->nTrackTool--; 1220c2c66affSColin Finck 1221c2c66affSColin Finck if (infoPtr->nCurrentTool == nTool) 1222c2c66affSColin Finck /* -1 means no current tool (0 means first tool) */ 1223c2c66affSColin Finck infoPtr->nCurrentTool = -1; 1224c2c66affSColin Finck else if (infoPtr->nCurrentTool > nTool) 1225c2c66affSColin Finck infoPtr->nCurrentTool--; 1226c2c66affSColin Finck 1227c2c66affSColin Finck infoPtr->uNumTools--; 1228c2c66affSColin Finck 1229c2c66affSColin Finck return 0; 1230c2c66affSColin Finck } 1231c2c66affSColin Finck 1232c2c66affSColin Finck static LRESULT 1233c2c66affSColin Finck TOOLTIPS_EnumToolsT (const TOOLTIPS_INFO *infoPtr, UINT uIndex, TTTOOLINFOW *ti, 1234c2c66affSColin Finck BOOL isW) 1235c2c66affSColin Finck { 1236edd99e8cSAmine Khaldi if (!ti || ti->cbSize < TTTOOLINFOW_V1_SIZE) 1237c2c66affSColin Finck return FALSE; 1238c2c66affSColin Finck if (uIndex >= infoPtr->uNumTools) 1239c2c66affSColin Finck return FALSE; 1240c2c66affSColin Finck 1241c2c66affSColin Finck TRACE("index=%u\n", uIndex); 1242c2c66affSColin Finck 1243edd99e8cSAmine Khaldi TOOLTIPS_CopyInfoT (infoPtr, uIndex, ti, isW); 1244c2c66affSColin Finck 1245c2c66affSColin Finck return TRUE; 1246c2c66affSColin Finck } 1247c2c66affSColin Finck 1248c2c66affSColin Finck static LRESULT 1249c2c66affSColin Finck TOOLTIPS_GetBubbleSize (const TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *lpToolInfo) 1250c2c66affSColin Finck { 1251c2c66affSColin Finck INT nTool; 1252c2c66affSColin Finck SIZE size; 1253c2c66affSColin Finck 1254c2c66affSColin Finck if (lpToolInfo == NULL) 1255c2c66affSColin Finck return FALSE; 1256c2c66affSColin Finck if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) 1257c2c66affSColin Finck return FALSE; 1258c2c66affSColin Finck 1259c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, lpToolInfo); 1260c2c66affSColin Finck if (nTool == -1) return 0; 1261c2c66affSColin Finck 1262c2c66affSColin Finck TRACE("tool %d\n", nTool); 1263c2c66affSColin Finck 1264c2c66affSColin Finck TOOLTIPS_CalcTipSize (infoPtr, &size); 1265c2c66affSColin Finck TRACE("size %d x %d\n", size.cx, size.cy); 1266c2c66affSColin Finck 1267c2c66affSColin Finck return MAKELRESULT(size.cx, size.cy); 1268c2c66affSColin Finck } 1269c2c66affSColin Finck 1270c2c66affSColin Finck static LRESULT 1271c2c66affSColin Finck TOOLTIPS_GetCurrentToolT (const TOOLTIPS_INFO *infoPtr, TTTOOLINFOW *ti, BOOL isW) 1272c2c66affSColin Finck { 1273c2c66affSColin Finck if (ti) { 1274c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOW_V1_SIZE) 1275c2c66affSColin Finck return FALSE; 1276c2c66affSColin Finck 1277edd99e8cSAmine Khaldi if (infoPtr->nCurrentTool != -1) 1278edd99e8cSAmine Khaldi TOOLTIPS_CopyInfoT (infoPtr, infoPtr->nCurrentTool, ti, isW); 1279c2c66affSColin Finck } 1280edd99e8cSAmine Khaldi 1281edd99e8cSAmine Khaldi return infoPtr->nCurrentTool != -1; 1282c2c66affSColin Finck } 1283c2c66affSColin Finck 1284c2c66affSColin Finck 1285c2c66affSColin Finck static LRESULT 1286c2c66affSColin Finck TOOLTIPS_GetDelayTime (const TOOLTIPS_INFO *infoPtr, DWORD duration) 1287c2c66affSColin Finck { 1288c2c66affSColin Finck switch (duration) { 1289c2c66affSColin Finck case TTDT_RESHOW: 1290c2c66affSColin Finck return infoPtr->nReshowTime; 1291c2c66affSColin Finck 1292c2c66affSColin Finck case TTDT_AUTOPOP: 1293c2c66affSColin Finck return infoPtr->nAutoPopTime; 1294c2c66affSColin Finck 1295c2c66affSColin Finck case TTDT_INITIAL: 1296c2c66affSColin Finck case TTDT_AUTOMATIC: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */ 1297c2c66affSColin Finck return infoPtr->nInitialTime; 1298c2c66affSColin Finck 1299c2c66affSColin Finck default: 1300c2c66affSColin Finck WARN("Invalid duration flag %x\n", duration); 1301c2c66affSColin Finck break; 1302c2c66affSColin Finck } 1303c2c66affSColin Finck 1304c2c66affSColin Finck return -1; 1305c2c66affSColin Finck } 1306c2c66affSColin Finck 1307c2c66affSColin Finck 1308c2c66affSColin Finck static LRESULT 1309c2c66affSColin Finck TOOLTIPS_GetMargin (const TOOLTIPS_INFO *infoPtr, RECT *rect) 1310c2c66affSColin Finck { 1311c2c66affSColin Finck if (rect) 1312c2c66affSColin Finck *rect = infoPtr->rcMargin; 1313c2c66affSColin Finck 1314c2c66affSColin Finck return 0; 1315c2c66affSColin Finck } 1316c2c66affSColin Finck 1317c2c66affSColin Finck 1318c2c66affSColin Finck static inline LRESULT 1319c2c66affSColin Finck TOOLTIPS_GetMaxTipWidth (const TOOLTIPS_INFO *infoPtr) 1320c2c66affSColin Finck { 1321c2c66affSColin Finck return infoPtr->nMaxTipWidth; 1322c2c66affSColin Finck } 1323c2c66affSColin Finck 1324c2c66affSColin Finck 1325c2c66affSColin Finck static LRESULT 1326c2c66affSColin Finck TOOLTIPS_GetTextT (const TOOLTIPS_INFO *infoPtr, TTTOOLINFOW *ti, BOOL isW) 1327c2c66affSColin Finck { 1328c2c66affSColin Finck INT nTool; 1329c2c66affSColin Finck 1330c2c66affSColin Finck if (!ti) return 0; 1331c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOW_V1_SIZE) 1332c2c66affSColin Finck return 0; 1333c2c66affSColin Finck 1334c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, ti); 1335c2c66affSColin Finck if (nTool == -1) return 0; 1336c2c66affSColin Finck 1337c2c66affSColin Finck if (infoPtr->tools[nTool].lpszText == NULL) 1338c2c66affSColin Finck return 0; 1339c2c66affSColin Finck 1340c2c66affSColin Finck if (isW) { 1341c2c66affSColin Finck ti->lpszText[0] = '\0'; 1342c2c66affSColin Finck TOOLTIPS_GetTipText(infoPtr, nTool, ti->lpszText); 1343c2c66affSColin Finck } 1344c2c66affSColin Finck else { 1345c2c66affSColin Finck WCHAR buffer[INFOTIPSIZE]; 1346c2c66affSColin Finck 1347c2c66affSColin Finck /* NB this API is broken, there is no way for the app to determine 1348c2c66affSColin Finck what size buffer it requires nor a way to specify how long the 1349c2c66affSColin Finck one it supplies is. According to the test result, it's up to 1350c2c66affSColin Finck 80 bytes by the ANSI version. */ 1351c2c66affSColin Finck 1352c2c66affSColin Finck buffer[0] = '\0'; 1353c2c66affSColin Finck TOOLTIPS_GetTipText(infoPtr, nTool, buffer); 1354c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, buffer, -1, (LPSTR)ti->lpszText, 1355c2c66affSColin Finck MAX_TEXT_SIZE_A, NULL, NULL); 1356c2c66affSColin Finck } 1357c2c66affSColin Finck 1358c2c66affSColin Finck return 0; 1359c2c66affSColin Finck } 1360c2c66affSColin Finck 1361c2c66affSColin Finck 1362c2c66affSColin Finck static inline LRESULT 1363c2c66affSColin Finck TOOLTIPS_GetTipBkColor (const TOOLTIPS_INFO *infoPtr) 1364c2c66affSColin Finck { 1365c2c66affSColin Finck return infoPtr->clrBk; 1366c2c66affSColin Finck } 1367c2c66affSColin Finck 1368c2c66affSColin Finck 1369c2c66affSColin Finck static inline LRESULT 1370c2c66affSColin Finck TOOLTIPS_GetTipTextColor (const TOOLTIPS_INFO *infoPtr) 1371c2c66affSColin Finck { 1372c2c66affSColin Finck return infoPtr->clrText; 1373c2c66affSColin Finck } 1374c2c66affSColin Finck 1375c2c66affSColin Finck 1376c2c66affSColin Finck static inline LRESULT 1377c2c66affSColin Finck TOOLTIPS_GetToolCount (const TOOLTIPS_INFO *infoPtr) 1378c2c66affSColin Finck { 1379c2c66affSColin Finck return infoPtr->uNumTools; 1380c2c66affSColin Finck } 1381c2c66affSColin Finck 1382c2c66affSColin Finck 1383c2c66affSColin Finck static LRESULT 1384c2c66affSColin Finck TOOLTIPS_GetToolInfoT (const TOOLTIPS_INFO *infoPtr, TTTOOLINFOW *ti, BOOL isW) 1385c2c66affSColin Finck { 1386c2c66affSColin Finck INT nTool; 1387edd99e8cSAmine Khaldi HWND hwnd; 1388c2c66affSColin Finck 1389c2c66affSColin Finck if (!ti) return FALSE; 1390c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOW_V1_SIZE) 1391c2c66affSColin Finck return FALSE; 1392c2c66affSColin Finck if (infoPtr->uNumTools == 0) 1393c2c66affSColin Finck return FALSE; 1394c2c66affSColin Finck 1395c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, ti); 1396c2c66affSColin Finck if (nTool == -1) 1397c2c66affSColin Finck return FALSE; 1398c2c66affSColin Finck 1399c2c66affSColin Finck TRACE("tool %d\n", nTool); 1400c2c66affSColin Finck 1401edd99e8cSAmine Khaldi hwnd = ti->hwnd; 1402edd99e8cSAmine Khaldi TOOLTIPS_CopyInfoT (infoPtr, nTool, ti, isW); 1403edd99e8cSAmine Khaldi ti->hwnd = hwnd; 1404c2c66affSColin Finck 1405c2c66affSColin Finck return TRUE; 1406c2c66affSColin Finck } 1407c2c66affSColin Finck 1408c2c66affSColin Finck 1409c2c66affSColin Finck static LRESULT 1410c2c66affSColin Finck TOOLTIPS_HitTestT (const TOOLTIPS_INFO *infoPtr, LPTTHITTESTINFOW lptthit, 1411c2c66affSColin Finck BOOL isW) 1412c2c66affSColin Finck { 1413c2c66affSColin Finck INT nTool; 1414c2c66affSColin Finck 1415c2c66affSColin Finck if (lptthit == 0) 1416c2c66affSColin Finck return FALSE; 1417c2c66affSColin Finck 1418c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt); 1419c2c66affSColin Finck if (nTool == -1) 1420c2c66affSColin Finck return FALSE; 1421c2c66affSColin Finck 1422edd99e8cSAmine Khaldi TRACE("tool %d\n", nTool); 1423c2c66affSColin Finck 1424c2c66affSColin Finck /* copy tool data */ 1425edd99e8cSAmine Khaldi if (lptthit->ti.cbSize >= TTTOOLINFOW_V1_SIZE) 1426edd99e8cSAmine Khaldi TOOLTIPS_CopyInfoT (infoPtr, nTool, &lptthit->ti, isW); 1427c2c66affSColin Finck 1428c2c66affSColin Finck return TRUE; 1429c2c66affSColin Finck } 1430c2c66affSColin Finck 1431c2c66affSColin Finck 1432c2c66affSColin Finck static LRESULT 1433c2c66affSColin Finck TOOLTIPS_NewToolRectT (TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *ti) 1434c2c66affSColin Finck { 1435c2c66affSColin Finck INT nTool; 1436c2c66affSColin Finck 1437c2c66affSColin Finck if (!ti) return 0; 1438c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOW_V1_SIZE) 1439c2c66affSColin Finck return FALSE; 1440c2c66affSColin Finck 1441c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, ti); 1442c2c66affSColin Finck 1443c2c66affSColin Finck TRACE("nTool = %d, rect = %s\n", nTool, wine_dbgstr_rect(&ti->rect)); 1444c2c66affSColin Finck 1445c2c66affSColin Finck if (nTool == -1) return 0; 1446c2c66affSColin Finck 1447c2c66affSColin Finck infoPtr->tools[nTool].rect = ti->rect; 1448c2c66affSColin Finck 1449c2c66affSColin Finck return 0; 1450c2c66affSColin Finck } 1451c2c66affSColin Finck 1452c2c66affSColin Finck 1453c2c66affSColin Finck static inline LRESULT 1454c2c66affSColin Finck TOOLTIPS_Pop (TOOLTIPS_INFO *infoPtr) 1455c2c66affSColin Finck { 1456c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 1457c2c66affSColin Finck 1458c2c66affSColin Finck return 0; 1459c2c66affSColin Finck } 1460c2c66affSColin Finck 1461c2c66affSColin Finck 1462c2c66affSColin Finck static LRESULT 1463c2c66affSColin Finck TOOLTIPS_RelayEvent (TOOLTIPS_INFO *infoPtr, LPMSG lpMsg) 1464c2c66affSColin Finck { 1465c2c66affSColin Finck POINT pt; 1466c2c66affSColin Finck INT nOldTool; 1467c2c66affSColin Finck 1468c2c66affSColin Finck if (!lpMsg) { 1469edd99e8cSAmine Khaldi ERR("lpMsg == NULL\n"); 1470c2c66affSColin Finck return 0; 1471c2c66affSColin Finck } 1472c2c66affSColin Finck 1473c2c66affSColin Finck switch (lpMsg->message) { 1474c2c66affSColin Finck case WM_LBUTTONDOWN: 1475c2c66affSColin Finck case WM_LBUTTONUP: 1476c2c66affSColin Finck case WM_MBUTTONDOWN: 1477c2c66affSColin Finck case WM_MBUTTONUP: 1478c2c66affSColin Finck case WM_RBUTTONDOWN: 1479c2c66affSColin Finck case WM_RBUTTONUP: 1480c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 1481c2c66affSColin Finck break; 1482c2c66affSColin Finck 1483c2c66affSColin Finck case WM_MOUSEMOVE: 1484c2c66affSColin Finck pt.x = (short)LOWORD(lpMsg->lParam); 1485c2c66affSColin Finck pt.y = (short)HIWORD(lpMsg->lParam); 1486c2c66affSColin Finck nOldTool = infoPtr->nTool; 1487c2c66affSColin Finck infoPtr->nTool = TOOLTIPS_GetToolFromPoint(infoPtr, lpMsg->hwnd, 1488c2c66affSColin Finck &pt); 1489c2c66affSColin Finck TRACE("tool (%p) %d %d %d\n", infoPtr->hwndSelf, nOldTool, 1490c2c66affSColin Finck infoPtr->nTool, infoPtr->nCurrentTool); 1491c2c66affSColin Finck TRACE("WM_MOUSEMOVE (%p %s)\n", infoPtr->hwndSelf, wine_dbgstr_point(&pt)); 1492c2c66affSColin Finck 1493c2c66affSColin Finck if (infoPtr->nTool != nOldTool) { 1494c2c66affSColin Finck if(infoPtr->nTool == -1) { /* Moved out of all tools */ 1495c2c66affSColin Finck TOOLTIPS_Hide(infoPtr); 1496c2c66affSColin Finck KillTimer(infoPtr->hwndSelf, ID_TIMERLEAVE); 1497c2c66affSColin Finck } else if (nOldTool == -1) { /* Moved from outside */ 1498c2c66affSColin Finck if(infoPtr->bActive) { 1499c2c66affSColin Finck SetTimer(infoPtr->hwndSelf, ID_TIMERSHOW, infoPtr->nInitialTime, 0); 1500edd99e8cSAmine Khaldi TRACE("timer 1 started\n"); 1501c2c66affSColin Finck } 1502c2c66affSColin Finck } else { /* Moved from one to another */ 1503c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 1504c2c66affSColin Finck KillTimer(infoPtr->hwndSelf, ID_TIMERLEAVE); 1505c2c66affSColin Finck if(infoPtr->bActive) { 1506c2c66affSColin Finck SetTimer (infoPtr->hwndSelf, ID_TIMERSHOW, infoPtr->nReshowTime, 0); 1507edd99e8cSAmine Khaldi TRACE("timer 1 started\n"); 1508c2c66affSColin Finck } 1509c2c66affSColin Finck } 1510c2c66affSColin Finck } else if(infoPtr->nCurrentTool != -1) { /* restart autopop */ 1511c2c66affSColin Finck KillTimer(infoPtr->hwndSelf, ID_TIMERPOP); 1512c2c66affSColin Finck SetTimer(infoPtr->hwndSelf, ID_TIMERPOP, infoPtr->nAutoPopTime, 0); 1513c2c66affSColin Finck TRACE("timer 2 restarted\n"); 1514c2c66affSColin Finck } else if(infoPtr->nTool != -1 && infoPtr->bActive) { 1515c2c66affSColin Finck /* previous show attempt didn't result in tooltip so try again */ 1516c2c66affSColin Finck SetTimer(infoPtr->hwndSelf, ID_TIMERSHOW, infoPtr->nInitialTime, 0); 1517edd99e8cSAmine Khaldi TRACE("timer 1 started\n"); 1518c2c66affSColin Finck } 1519c2c66affSColin Finck break; 1520c2c66affSColin Finck } 1521c2c66affSColin Finck 1522c2c66affSColin Finck return 0; 1523c2c66affSColin Finck } 1524c2c66affSColin Finck 1525c2c66affSColin Finck 1526c2c66affSColin Finck static LRESULT 1527c2c66affSColin Finck TOOLTIPS_SetDelayTime (TOOLTIPS_INFO *infoPtr, DWORD duration, INT nTime) 1528c2c66affSColin Finck { 1529c2c66affSColin Finck switch (duration) { 1530c2c66affSColin Finck case TTDT_AUTOMATIC: 1531c2c66affSColin Finck if (nTime <= 0) 1532c2c66affSColin Finck nTime = GetDoubleClickTime(); 1533c2c66affSColin Finck infoPtr->nReshowTime = nTime / 5; 1534c2c66affSColin Finck infoPtr->nAutoPopTime = nTime * 10; 1535c2c66affSColin Finck infoPtr->nInitialTime = nTime; 1536c2c66affSColin Finck break; 1537c2c66affSColin Finck 1538c2c66affSColin Finck case TTDT_RESHOW: 1539c2c66affSColin Finck if(nTime < 0) 1540c2c66affSColin Finck nTime = GetDoubleClickTime() / 5; 1541c2c66affSColin Finck infoPtr->nReshowTime = nTime; 1542c2c66affSColin Finck break; 1543c2c66affSColin Finck 1544c2c66affSColin Finck case TTDT_AUTOPOP: 1545c2c66affSColin Finck if(nTime < 0) 1546c2c66affSColin Finck nTime = GetDoubleClickTime() * 10; 1547c2c66affSColin Finck infoPtr->nAutoPopTime = nTime; 1548c2c66affSColin Finck break; 1549c2c66affSColin Finck 1550c2c66affSColin Finck case TTDT_INITIAL: 1551c2c66affSColin Finck if(nTime < 0) 1552c2c66affSColin Finck nTime = GetDoubleClickTime(); 1553c2c66affSColin Finck infoPtr->nInitialTime = nTime; 1554c2c66affSColin Finck break; 1555c2c66affSColin Finck 1556c2c66affSColin Finck default: 1557c2c66affSColin Finck WARN("Invalid duration flag %x\n", duration); 1558c2c66affSColin Finck break; 1559c2c66affSColin Finck } 1560c2c66affSColin Finck 1561c2c66affSColin Finck return 0; 1562c2c66affSColin Finck } 1563c2c66affSColin Finck 1564c2c66affSColin Finck 1565c2c66affSColin Finck static LRESULT 1566c2c66affSColin Finck TOOLTIPS_SetMargin (TOOLTIPS_INFO *infoPtr, const RECT *rect) 1567c2c66affSColin Finck { 1568c2c66affSColin Finck if (rect) 1569c2c66affSColin Finck infoPtr->rcMargin = *rect; 1570c2c66affSColin Finck 1571c2c66affSColin Finck return 0; 1572c2c66affSColin Finck } 1573c2c66affSColin Finck 1574c2c66affSColin Finck 1575c2c66affSColin Finck static inline LRESULT 1576c2c66affSColin Finck TOOLTIPS_SetMaxTipWidth (TOOLTIPS_INFO *infoPtr, INT MaxWidth) 1577c2c66affSColin Finck { 1578c2c66affSColin Finck INT nTemp = infoPtr->nMaxTipWidth; 1579c2c66affSColin Finck 1580c2c66affSColin Finck infoPtr->nMaxTipWidth = MaxWidth; 1581c2c66affSColin Finck 1582c2c66affSColin Finck return nTemp; 1583c2c66affSColin Finck } 1584c2c66affSColin Finck 1585c2c66affSColin Finck 1586c2c66affSColin Finck static inline LRESULT 1587c2c66affSColin Finck TOOLTIPS_SetTipBkColor (TOOLTIPS_INFO *infoPtr, COLORREF clrBk) 1588c2c66affSColin Finck { 1589c2c66affSColin Finck infoPtr->clrBk = clrBk; 1590c2c66affSColin Finck 1591c2c66affSColin Finck return 0; 1592c2c66affSColin Finck } 1593c2c66affSColin Finck 1594c2c66affSColin Finck 1595c2c66affSColin Finck static inline LRESULT 1596c2c66affSColin Finck TOOLTIPS_SetTipTextColor (TOOLTIPS_INFO *infoPtr, COLORREF clrText) 1597c2c66affSColin Finck { 1598c2c66affSColin Finck infoPtr->clrText = clrText; 1599c2c66affSColin Finck 1600c2c66affSColin Finck return 0; 1601c2c66affSColin Finck } 1602c2c66affSColin Finck 1603c2c66affSColin Finck 1604c2c66affSColin Finck static LRESULT 1605c2c66affSColin Finck TOOLTIPS_SetTitleT (TOOLTIPS_INFO *infoPtr, UINT_PTR uTitleIcon, LPCWSTR pszTitle, 1606c2c66affSColin Finck BOOL isW) 1607c2c66affSColin Finck { 1608c2c66affSColin Finck UINT size; 1609c2c66affSColin Finck 1610c2c66affSColin Finck TRACE("hwnd = %p, title = %s, icon = %p\n", infoPtr->hwndSelf, debugstr_w(pszTitle), 1611c2c66affSColin Finck (void*)uTitleIcon); 1612c2c66affSColin Finck 1613c2c66affSColin Finck Free(infoPtr->pszTitle); 1614c2c66affSColin Finck 1615c2c66affSColin Finck if (pszTitle) 1616c2c66affSColin Finck { 1617c2c66affSColin Finck if (isW) 1618c2c66affSColin Finck { 1619c2c66affSColin Finck size = (strlenW(pszTitle)+1)*sizeof(WCHAR); 1620c2c66affSColin Finck infoPtr->pszTitle = Alloc(size); 1621c2c66affSColin Finck if (!infoPtr->pszTitle) 1622c2c66affSColin Finck return FALSE; 1623c2c66affSColin Finck memcpy(infoPtr->pszTitle, pszTitle, size); 1624c2c66affSColin Finck } 1625c2c66affSColin Finck else 1626c2c66affSColin Finck { 1627c2c66affSColin Finck size = sizeof(WCHAR)*MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszTitle, -1, NULL, 0); 1628c2c66affSColin Finck infoPtr->pszTitle = Alloc(size); 1629c2c66affSColin Finck if (!infoPtr->pszTitle) 1630c2c66affSColin Finck return FALSE; 1631c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszTitle, -1, infoPtr->pszTitle, size/sizeof(WCHAR)); 1632c2c66affSColin Finck } 1633c2c66affSColin Finck } 1634c2c66affSColin Finck else 1635c2c66affSColin Finck infoPtr->pszTitle = NULL; 1636c2c66affSColin Finck 1637c2c66affSColin Finck if (uTitleIcon <= TTI_ERROR) 1638c2c66affSColin Finck infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon]; 1639c2c66affSColin Finck else 1640c2c66affSColin Finck infoPtr->hTitleIcon = CopyIcon((HICON)uTitleIcon); 1641c2c66affSColin Finck 1642c2c66affSColin Finck TRACE("icon = %p\n", infoPtr->hTitleIcon); 1643c2c66affSColin Finck 1644c2c66affSColin Finck return TRUE; 1645c2c66affSColin Finck } 1646c2c66affSColin Finck 1647c2c66affSColin Finck 1648c2c66affSColin Finck static LRESULT 1649c2c66affSColin Finck TOOLTIPS_SetToolInfoT (TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *ti, BOOL isW) 1650c2c66affSColin Finck { 1651c2c66affSColin Finck TTTOOL_INFO *toolPtr; 1652c2c66affSColin Finck INT nTool; 1653c2c66affSColin Finck 1654c2c66affSColin Finck if (!ti) return 0; 1655c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOW_V1_SIZE) 1656c2c66affSColin Finck return 0; 1657c2c66affSColin Finck 1658c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, ti); 1659c2c66affSColin Finck if (nTool == -1) return 0; 1660c2c66affSColin Finck 1661c2c66affSColin Finck TRACE("tool %d\n", nTool); 1662c2c66affSColin Finck 1663c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 1664c2c66affSColin Finck 1665c2c66affSColin Finck /* copy tool data */ 1666c2c66affSColin Finck toolPtr->uFlags = ti->uFlags; 1667c2c66affSColin Finck toolPtr->hwnd = ti->hwnd; 1668c2c66affSColin Finck toolPtr->uId = ti->uId; 1669c2c66affSColin Finck toolPtr->rect = ti->rect; 1670c2c66affSColin Finck toolPtr->hinst = ti->hinst; 1671c2c66affSColin Finck 1672c2c66affSColin Finck if (IS_INTRESOURCE(ti->lpszText)) { 1673edd99e8cSAmine Khaldi TRACE("set string id %x\n", LOWORD(ti->lpszText)); 1674c2c66affSColin Finck toolPtr->lpszText = ti->lpszText; 1675c2c66affSColin Finck } 1676c2c66affSColin Finck else { 1677c2c66affSColin Finck if (TOOLTIPS_IsCallbackString(ti->lpszText, isW)) 1678c2c66affSColin Finck toolPtr->lpszText = LPSTR_TEXTCALLBACKW; 1679c2c66affSColin Finck else { 1680c2c66affSColin Finck if ( (toolPtr->lpszText) && 1681c2c66affSColin Finck !IS_INTRESOURCE(toolPtr->lpszText) ) { 1682c2c66affSColin Finck if( toolPtr->lpszText != LPSTR_TEXTCALLBACKW) 1683c2c66affSColin Finck Free (toolPtr->lpszText); 1684c2c66affSColin Finck toolPtr->lpszText = NULL; 1685c2c66affSColin Finck } 1686c2c66affSColin Finck if (ti->lpszText) { 1687c2c66affSColin Finck if (isW) { 1688c2c66affSColin Finck INT len = lstrlenW (ti->lpszText); 1689c2c66affSColin Finck toolPtr->lpszText = Alloc ((len+1)*sizeof(WCHAR)); 1690c2c66affSColin Finck strcpyW (toolPtr->lpszText, ti->lpszText); 1691c2c66affSColin Finck } 1692c2c66affSColin Finck else { 1693c2c66affSColin Finck INT len = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ti->lpszText, 1694c2c66affSColin Finck -1, NULL, 0); 1695c2c66affSColin Finck toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); 1696c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, (LPSTR)ti->lpszText, -1, 1697c2c66affSColin Finck toolPtr->lpszText, len); 1698c2c66affSColin Finck } 1699c2c66affSColin Finck } 1700c2c66affSColin Finck } 1701c2c66affSColin Finck } 1702c2c66affSColin Finck 1703c2c66affSColin Finck if (ti->cbSize >= TTTOOLINFOW_V2_SIZE) 1704c2c66affSColin Finck toolPtr->lParam = ti->lParam; 1705c2c66affSColin Finck 1706c2c66affSColin Finck if (infoPtr->nCurrentTool == nTool) 1707c2c66affSColin Finck { 1708c2c66affSColin Finck TOOLTIPS_GetTipText (infoPtr, infoPtr->nCurrentTool, infoPtr->szTipText); 1709c2c66affSColin Finck 1710c2c66affSColin Finck if (infoPtr->szTipText[0] == 0) 1711c2c66affSColin Finck TOOLTIPS_Hide(infoPtr); 1712c2c66affSColin Finck else 1713c2c66affSColin Finck TOOLTIPS_Show (infoPtr, FALSE); 1714c2c66affSColin Finck } 1715c2c66affSColin Finck 1716c2c66affSColin Finck return 0; 1717c2c66affSColin Finck } 1718c2c66affSColin Finck 1719c2c66affSColin Finck 1720c2c66affSColin Finck static LRESULT 1721c2c66affSColin Finck TOOLTIPS_TrackActivate (TOOLTIPS_INFO *infoPtr, BOOL track_activate, const TTTOOLINFOA *ti) 1722c2c66affSColin Finck { 1723c2c66affSColin Finck if (track_activate) { 1724c2c66affSColin Finck 1725c2c66affSColin Finck if (!ti) return 0; 1726c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOA_V1_SIZE) 1727c2c66affSColin Finck return FALSE; 1728c2c66affSColin Finck 1729c2c66affSColin Finck /* activate */ 1730c2c66affSColin Finck infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoT (infoPtr, (const TTTOOLINFOW*)ti); 1731c2c66affSColin Finck if (infoPtr->nTrackTool != -1) { 1732edd99e8cSAmine Khaldi TRACE("activated\n"); 1733c2c66affSColin Finck infoPtr->bTrackActive = TRUE; 1734c2c66affSColin Finck TOOLTIPS_TrackShow (infoPtr); 1735c2c66affSColin Finck } 1736c2c66affSColin Finck } 1737c2c66affSColin Finck else { 1738c2c66affSColin Finck /* deactivate */ 1739c2c66affSColin Finck TOOLTIPS_TrackHide (infoPtr); 1740c2c66affSColin Finck 1741c2c66affSColin Finck infoPtr->bTrackActive = FALSE; 1742c2c66affSColin Finck infoPtr->nTrackTool = -1; 1743c2c66affSColin Finck 1744edd99e8cSAmine Khaldi TRACE("deactivated\n"); 1745c2c66affSColin Finck } 1746c2c66affSColin Finck 1747c2c66affSColin Finck return 0; 1748c2c66affSColin Finck } 1749c2c66affSColin Finck 1750c2c66affSColin Finck 1751c2c66affSColin Finck static LRESULT 1752c2c66affSColin Finck TOOLTIPS_TrackPosition (TOOLTIPS_INFO *infoPtr, LPARAM coord) 1753c2c66affSColin Finck { 1754c2c66affSColin Finck infoPtr->xTrackPos = (INT)LOWORD(coord); 1755c2c66affSColin Finck infoPtr->yTrackPos = (INT)HIWORD(coord); 1756c2c66affSColin Finck 1757c2c66affSColin Finck if (infoPtr->bTrackActive) { 1758c2c66affSColin Finck TRACE("[%d %d]\n", 1759c2c66affSColin Finck infoPtr->xTrackPos, infoPtr->yTrackPos); 1760c2c66affSColin Finck 1761c2c66affSColin Finck TOOLTIPS_TrackShow (infoPtr); 1762c2c66affSColin Finck } 1763c2c66affSColin Finck 1764c2c66affSColin Finck return 0; 1765c2c66affSColin Finck } 1766c2c66affSColin Finck 1767c2c66affSColin Finck 1768c2c66affSColin Finck static LRESULT 1769c2c66affSColin Finck TOOLTIPS_Update (TOOLTIPS_INFO *infoPtr) 1770c2c66affSColin Finck { 1771c2c66affSColin Finck if (infoPtr->nCurrentTool != -1) 1772c2c66affSColin Finck UpdateWindow (infoPtr->hwndSelf); 1773c2c66affSColin Finck 1774c2c66affSColin Finck return 0; 1775c2c66affSColin Finck } 1776c2c66affSColin Finck 1777c2c66affSColin Finck 1778c2c66affSColin Finck static LRESULT 1779c2c66affSColin Finck TOOLTIPS_UpdateTipTextT (TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *ti, BOOL isW) 1780c2c66affSColin Finck { 1781c2c66affSColin Finck TTTOOL_INFO *toolPtr; 1782c2c66affSColin Finck INT nTool; 1783c2c66affSColin Finck 1784c2c66affSColin Finck if (!ti) return 0; 1785c2c66affSColin Finck if (ti->cbSize < TTTOOLINFOW_V1_SIZE) 1786c2c66affSColin Finck return FALSE; 1787c2c66affSColin Finck 1788c2c66affSColin Finck nTool = TOOLTIPS_GetToolFromInfoT (infoPtr, ti); 1789c2c66affSColin Finck if (nTool == -1) 1790c2c66affSColin Finck return 0; 1791c2c66affSColin Finck 1792c2c66affSColin Finck TRACE("tool %d\n", nTool); 1793c2c66affSColin Finck 1794c2c66affSColin Finck toolPtr = &infoPtr->tools[nTool]; 1795c2c66affSColin Finck 1796c2c66affSColin Finck /* copy tool text */ 1797c2c66affSColin Finck toolPtr->hinst = ti->hinst; 1798c2c66affSColin Finck 1799c2c66affSColin Finck if (IS_INTRESOURCE(ti->lpszText)){ 1800c2c66affSColin Finck toolPtr->lpszText = ti->lpszText; 1801c2c66affSColin Finck } 1802c2c66affSColin Finck else if (ti->lpszText) { 1803c2c66affSColin Finck if (TOOLTIPS_IsCallbackString(ti->lpszText, isW)) 1804c2c66affSColin Finck toolPtr->lpszText = LPSTR_TEXTCALLBACKW; 1805c2c66affSColin Finck else { 1806c2c66affSColin Finck if ( (toolPtr->lpszText) && 1807c2c66affSColin Finck !IS_INTRESOURCE(toolPtr->lpszText) ) { 1808c2c66affSColin Finck if( toolPtr->lpszText != LPSTR_TEXTCALLBACKW) 1809c2c66affSColin Finck Free (toolPtr->lpszText); 1810c2c66affSColin Finck toolPtr->lpszText = NULL; 1811c2c66affSColin Finck } 1812c2c66affSColin Finck if (ti->lpszText) { 1813c2c66affSColin Finck if (isW) { 1814c2c66affSColin Finck INT len = lstrlenW (ti->lpszText); 1815c2c66affSColin Finck toolPtr->lpszText = Alloc ((len+1)*sizeof(WCHAR)); 1816c2c66affSColin Finck strcpyW (toolPtr->lpszText, ti->lpszText); 1817c2c66affSColin Finck } 1818c2c66affSColin Finck else { 1819c2c66affSColin Finck INT len = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ti->lpszText, 1820c2c66affSColin Finck -1, NULL, 0); 1821c2c66affSColin Finck toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); 1822c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, (LPSTR)ti->lpszText, -1, 1823c2c66affSColin Finck toolPtr->lpszText, len); 1824c2c66affSColin Finck } 1825c2c66affSColin Finck } 1826c2c66affSColin Finck } 1827c2c66affSColin Finck } 1828c2c66affSColin Finck 1829c2c66affSColin Finck if(infoPtr->nCurrentTool == -1) return 0; 1830c2c66affSColin Finck /* force repaint */ 1831c2c66affSColin Finck if (infoPtr->bActive) 1832c2c66affSColin Finck TOOLTIPS_Show (infoPtr, FALSE); 1833c2c66affSColin Finck else if (infoPtr->bTrackActive) 1834c2c66affSColin Finck TOOLTIPS_Show (infoPtr, TRUE); 1835c2c66affSColin Finck 1836c2c66affSColin Finck return 0; 1837c2c66affSColin Finck } 1838c2c66affSColin Finck 1839c2c66affSColin Finck 1840c2c66affSColin Finck static LRESULT 1841c2c66affSColin Finck TOOLTIPS_Create (HWND hwnd) 1842c2c66affSColin Finck { 1843c2c66affSColin Finck TOOLTIPS_INFO *infoPtr; 1844c2c66affSColin Finck 1845c2c66affSColin Finck /* allocate memory for info structure */ 1846c2c66affSColin Finck infoPtr = Alloc (sizeof(TOOLTIPS_INFO)); 1847c2c66affSColin Finck SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); 1848c2c66affSColin Finck 1849c2c66affSColin Finck /* initialize info structure */ 1850c2c66affSColin Finck infoPtr->bActive = TRUE; 1851c2c66affSColin Finck infoPtr->bTrackActive = FALSE; 1852c2c66affSColin Finck 1853c2c66affSColin Finck infoPtr->nMaxTipWidth = -1; 1854c2c66affSColin Finck infoPtr->nTool = -1; 1855c2c66affSColin Finck infoPtr->nCurrentTool = -1; 1856c2c66affSColin Finck infoPtr->nTrackTool = -1; 1857c2c66affSColin Finck infoPtr->hwndSelf = hwnd; 1858c2c66affSColin Finck 1859c2c66affSColin Finck /* initialize colours and fonts */ 1860c2c66affSColin Finck TOOLTIPS_InitSystemSettings(infoPtr); 1861c2c66affSColin Finck 1862c2c66affSColin Finck TOOLTIPS_SetDelayTime(infoPtr, TTDT_AUTOMATIC, 0); 1863c2c66affSColin Finck 1864c2c66affSColin Finck SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); 1865c2c66affSColin Finck 1866c2c66affSColin Finck return 0; 1867c2c66affSColin Finck } 1868c2c66affSColin Finck 1869c2c66affSColin Finck 1870c2c66affSColin Finck static LRESULT 1871c2c66affSColin Finck TOOLTIPS_Destroy (TOOLTIPS_INFO *infoPtr) 1872c2c66affSColin Finck { 1873c2c66affSColin Finck TTTOOL_INFO *toolPtr; 1874c2c66affSColin Finck UINT i; 1875c2c66affSColin Finck 1876c2c66affSColin Finck /* free tools */ 1877c2c66affSColin Finck if (infoPtr->tools) { 1878c2c66affSColin Finck for (i = 0; i < infoPtr->uNumTools; i++) { 1879c2c66affSColin Finck toolPtr = &infoPtr->tools[i]; 1880c2c66affSColin Finck if (toolPtr->lpszText) { 1881c2c66affSColin Finck if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && 1882c2c66affSColin Finck !IS_INTRESOURCE(toolPtr->lpszText) ) 1883c2c66affSColin Finck { 1884c2c66affSColin Finck Free (toolPtr->lpszText); 1885c2c66affSColin Finck toolPtr->lpszText = NULL; 1886c2c66affSColin Finck } 1887c2c66affSColin Finck } 1888c2c66affSColin Finck 1889edd99e8cSAmine Khaldi TOOLTIPS_ResetSubclass (toolPtr); 1890c2c66affSColin Finck } 1891edd99e8cSAmine Khaldi 1892c2c66affSColin Finck Free (infoPtr->tools); 1893c2c66affSColin Finck } 1894c2c66affSColin Finck 1895c2c66affSColin Finck /* free title string */ 1896c2c66affSColin Finck Free (infoPtr->pszTitle); 1897c2c66affSColin Finck /* free title icon if not a standard one */ 1898c2c66affSColin Finck if (TOOLTIPS_GetTitleIconIndex(infoPtr->hTitleIcon) > TTI_ERROR) 1899c2c66affSColin Finck DeleteObject(infoPtr->hTitleIcon); 1900c2c66affSColin Finck 1901c2c66affSColin Finck /* delete fonts */ 1902c2c66affSColin Finck DeleteObject (infoPtr->hFont); 1903c2c66affSColin Finck DeleteObject (infoPtr->hTitleFont); 1904c2c66affSColin Finck 1905c2c66affSColin Finck /* free tool tips info data */ 1906c2c66affSColin Finck SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0); 1907c2c66affSColin Finck Free (infoPtr); 1908c2c66affSColin Finck 1909c2c66affSColin Finck return 0; 1910c2c66affSColin Finck } 1911c2c66affSColin Finck 1912c2c66affSColin Finck 1913c2c66affSColin Finck static inline LRESULT 1914c2c66affSColin Finck TOOLTIPS_GetFont (const TOOLTIPS_INFO *infoPtr) 1915c2c66affSColin Finck { 1916c2c66affSColin Finck return (LRESULT)infoPtr->hFont; 1917c2c66affSColin Finck } 1918c2c66affSColin Finck 1919c2c66affSColin Finck 1920c2c66affSColin Finck static LRESULT 1921c2c66affSColin Finck TOOLTIPS_MouseMessage (TOOLTIPS_INFO *infoPtr) 1922c2c66affSColin Finck { 1923c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 1924c2c66affSColin Finck 1925c2c66affSColin Finck return 0; 1926c2c66affSColin Finck } 1927c2c66affSColin Finck 1928c2c66affSColin Finck 1929c2c66affSColin Finck static LRESULT 1930c2c66affSColin Finck TOOLTIPS_NCCreate (HWND hwnd) 1931c2c66affSColin Finck { 1932c2c66affSColin Finck DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE); 1933c2c66affSColin Finck DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE); 1934c2c66affSColin Finck 1935c2c66affSColin Finck dwStyle &= ~(WS_CHILD | /*WS_MAXIMIZE |*/ WS_BORDER | WS_DLGFRAME); 1936c2c66affSColin Finck dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS); 1937c2c66affSColin Finck 1938c2c66affSColin Finck /* WS_BORDER only draws a border round the window rect, not the 1939c2c66affSColin Finck * window region, therefore it is useless to us in balloon mode */ 1940c2c66affSColin Finck if (dwStyle & TTS_BALLOON) dwStyle &= ~WS_BORDER; 1941c2c66affSColin Finck 1942c2c66affSColin Finck SetWindowLongW (hwnd, GWL_STYLE, dwStyle); 1943c2c66affSColin Finck 1944c2c66affSColin Finck dwExStyle |= WS_EX_TOOLWINDOW; 1945c2c66affSColin Finck SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle); 1946c2c66affSColin Finck 1947c2c66affSColin Finck return TRUE; 1948c2c66affSColin Finck } 1949c2c66affSColin Finck 1950c2c66affSColin Finck 1951c2c66affSColin Finck static LRESULT 1952c2c66affSColin Finck TOOLTIPS_NCHitTest (const TOOLTIPS_INFO *infoPtr, WPARAM wParam, LPARAM lParam) 1953c2c66affSColin Finck { 1954c2c66affSColin Finck INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool; 1955c2c66affSColin Finck 1956c2c66affSColin Finck TRACE(" nTool=%d\n", nTool); 1957c2c66affSColin Finck 1958c2c66affSColin Finck if ((nTool > -1) && (nTool < infoPtr->uNumTools)) { 1959c2c66affSColin Finck if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) { 1960edd99e8cSAmine Khaldi TRACE("-- in transparent mode\n"); 1961c2c66affSColin Finck return HTTRANSPARENT; 1962c2c66affSColin Finck } 1963c2c66affSColin Finck } 1964c2c66affSColin Finck 1965c2c66affSColin Finck return DefWindowProcW (infoPtr->hwndSelf, WM_NCHITTEST, wParam, lParam); 1966c2c66affSColin Finck } 1967c2c66affSColin Finck 1968c2c66affSColin Finck 1969c2c66affSColin Finck static LRESULT 1970c2c66affSColin Finck TOOLTIPS_NotifyFormat (TOOLTIPS_INFO *infoPtr, WPARAM wParam, LPARAM lParam) 1971c2c66affSColin Finck { 1972c2c66affSColin Finck #ifdef __REACTOS__ 1973c2c66affSColin Finck TTTOOL_INFO *toolPtr = infoPtr->tools; 1974c2c66affSColin Finck LRESULT nResult; 1975c2c66affSColin Finck 1976c2c66affSColin Finck TRACE("infoPtr=%p wParam=%lx lParam=%p\n", infoPtr, wParam, (PVOID)lParam); 1977c2c66affSColin Finck 1978c2c66affSColin Finck if (lParam == NF_QUERY) { 1979c2c66affSColin Finck if (toolPtr->bNotifyUnicode) { 1980c2c66affSColin Finck return NFR_UNICODE; 1981c2c66affSColin Finck } else { 1982c2c66affSColin Finck return NFR_ANSI; 1983c2c66affSColin Finck } 1984c2c66affSColin Finck } 1985c2c66affSColin Finck else if (lParam == NF_REQUERY) { 1986c2c66affSColin Finck nResult = SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT, 1987c2c66affSColin Finck (WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY); 1988c2c66affSColin Finck if (nResult == NFR_ANSI) { 1989c2c66affSColin Finck toolPtr->bNotifyUnicode = FALSE; 1990c2c66affSColin Finck TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n"); 1991c2c66affSColin Finck } else if (nResult == NFR_UNICODE) { 1992c2c66affSColin Finck toolPtr->bNotifyUnicode = TRUE; 1993c2c66affSColin Finck TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n"); 1994c2c66affSColin Finck } else { 1995c2c66affSColin Finck TRACE (" -- WM_NOTIFYFORMAT returns: error!\n"); 1996c2c66affSColin Finck } 1997c2c66affSColin Finck return nResult; 1998c2c66affSColin Finck } 1999c2c66affSColin Finck #else 2000c2c66affSColin Finck FIXME ("hwnd=%p wParam=%lx lParam=%lx\n", infoPtr->hwndSelf, wParam, lParam); 2001c2c66affSColin Finck #endif 2002c2c66affSColin Finck 2003c2c66affSColin Finck return 0; 2004c2c66affSColin Finck } 2005c2c66affSColin Finck 2006c2c66affSColin Finck 2007c2c66affSColin Finck static LRESULT 2008c2c66affSColin Finck TOOLTIPS_Paint (const TOOLTIPS_INFO *infoPtr, HDC hDC) 2009c2c66affSColin Finck { 2010c2c66affSColin Finck HDC hdc; 2011c2c66affSColin Finck PAINTSTRUCT ps; 2012c2c66affSColin Finck 2013c2c66affSColin Finck hdc = (hDC == NULL) ? BeginPaint (infoPtr->hwndSelf, &ps) : hDC; 2014c2c66affSColin Finck TOOLTIPS_Refresh (infoPtr, hdc); 2015c2c66affSColin Finck if (!hDC) 2016c2c66affSColin Finck EndPaint (infoPtr->hwndSelf, &ps); 2017c2c66affSColin Finck return 0; 2018c2c66affSColin Finck } 2019c2c66affSColin Finck 2020c2c66affSColin Finck 2021c2c66affSColin Finck static LRESULT 2022c2c66affSColin Finck TOOLTIPS_SetFont (TOOLTIPS_INFO *infoPtr, HFONT hFont, BOOL redraw) 2023c2c66affSColin Finck { 2024c2c66affSColin Finck LOGFONTW lf; 2025c2c66affSColin Finck 2026c2c66affSColin Finck if(!GetObjectW(hFont, sizeof(lf), &lf)) 2027c2c66affSColin Finck return 0; 2028c2c66affSColin Finck 2029c2c66affSColin Finck DeleteObject (infoPtr->hFont); 2030c2c66affSColin Finck infoPtr->hFont = CreateFontIndirectW(&lf); 2031c2c66affSColin Finck 2032c2c66affSColin Finck DeleteObject (infoPtr->hTitleFont); 2033c2c66affSColin Finck lf.lfWeight = FW_BOLD; 2034c2c66affSColin Finck infoPtr->hTitleFont = CreateFontIndirectW(&lf); 2035c2c66affSColin Finck 2036edd99e8cSAmine Khaldi if (redraw && infoPtr->nCurrentTool != -1) 2037edd99e8cSAmine Khaldi FIXME("full redraw needed\n"); 2038c2c66affSColin Finck 2039c2c66affSColin Finck return 0; 2040c2c66affSColin Finck } 2041c2c66affSColin Finck 2042c2c66affSColin Finck /****************************************************************** 2043c2c66affSColin Finck * TOOLTIPS_GetTextLength 2044c2c66affSColin Finck * 2045c2c66affSColin Finck * This function is called when the tooltip receive a 2046c2c66affSColin Finck * WM_GETTEXTLENGTH message. 2047c2c66affSColin Finck * 2048c2c66affSColin Finck * returns the length, in characters, of the tip text 2049c2c66affSColin Finck */ 2050c2c66affSColin Finck static inline LRESULT 2051c2c66affSColin Finck TOOLTIPS_GetTextLength(const TOOLTIPS_INFO *infoPtr) 2052c2c66affSColin Finck { 2053c2c66affSColin Finck return strlenW(infoPtr->szTipText); 2054c2c66affSColin Finck } 2055c2c66affSColin Finck 2056c2c66affSColin Finck /****************************************************************** 2057c2c66affSColin Finck * TOOLTIPS_OnWMGetText 2058c2c66affSColin Finck * 2059c2c66affSColin Finck * This function is called when the tooltip receive a 2060c2c66affSColin Finck * WM_GETTEXT message. 2061c2c66affSColin Finck * wParam : specifies the maximum number of characters to be copied 2062c2c66affSColin Finck * lParam : is the pointer to the buffer that will receive 2063c2c66affSColin Finck * the tip text 2064c2c66affSColin Finck * 2065c2c66affSColin Finck * returns the number of characters copied 2066c2c66affSColin Finck */ 2067c2c66affSColin Finck static LRESULT 2068c2c66affSColin Finck TOOLTIPS_OnWMGetText (const TOOLTIPS_INFO *infoPtr, WPARAM size, LPWSTR pszText) 2069c2c66affSColin Finck { 2070c2c66affSColin Finck LRESULT res; 2071c2c66affSColin Finck 2072c2c66affSColin Finck if(!size) 2073c2c66affSColin Finck return 0; 2074c2c66affSColin Finck 2075c2c66affSColin Finck res = min(strlenW(infoPtr->szTipText)+1, size); 2076c2c66affSColin Finck memcpy(pszText, infoPtr->szTipText, res*sizeof(WCHAR)); 2077c2c66affSColin Finck pszText[res-1] = '\0'; 2078c2c66affSColin Finck return res-1; 2079c2c66affSColin Finck } 2080c2c66affSColin Finck 2081c2c66affSColin Finck static LRESULT 2082c2c66affSColin Finck TOOLTIPS_Timer (TOOLTIPS_INFO *infoPtr, INT iTimer) 2083c2c66affSColin Finck { 2084c2c66affSColin Finck INT nOldTool; 2085c2c66affSColin Finck 2086edd99e8cSAmine Khaldi TRACE("timer %d (%p) expired\n", iTimer, infoPtr->hwndSelf); 2087c2c66affSColin Finck 2088c2c66affSColin Finck switch (iTimer) { 2089c2c66affSColin Finck case ID_TIMERSHOW: 2090c2c66affSColin Finck KillTimer (infoPtr->hwndSelf, ID_TIMERSHOW); 2091c2c66affSColin Finck nOldTool = infoPtr->nTool; 2092c2c66affSColin Finck if ((infoPtr->nTool = TOOLTIPS_CheckTool (infoPtr, TRUE)) == nOldTool) 2093c2c66affSColin Finck TOOLTIPS_Show (infoPtr, FALSE); 2094c2c66affSColin Finck break; 2095c2c66affSColin Finck 2096c2c66affSColin Finck case ID_TIMERPOP: 2097c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 2098c2c66affSColin Finck break; 2099c2c66affSColin Finck 2100c2c66affSColin Finck case ID_TIMERLEAVE: 2101c2c66affSColin Finck nOldTool = infoPtr->nTool; 2102c2c66affSColin Finck infoPtr->nTool = TOOLTIPS_CheckTool (infoPtr, FALSE); 2103c2c66affSColin Finck TRACE("tool (%p) %d %d %d\n", infoPtr->hwndSelf, nOldTool, 2104c2c66affSColin Finck infoPtr->nTool, infoPtr->nCurrentTool); 2105c2c66affSColin Finck if (infoPtr->nTool != nOldTool) { 2106c2c66affSColin Finck if(infoPtr->nTool == -1) { /* Moved out of all tools */ 2107c2c66affSColin Finck TOOLTIPS_Hide(infoPtr); 2108c2c66affSColin Finck KillTimer(infoPtr->hwndSelf, ID_TIMERLEAVE); 2109c2c66affSColin Finck } else if (nOldTool == -1) { /* Moved from outside */ 2110c2c66affSColin Finck ERR("How did this happen?\n"); 2111c2c66affSColin Finck } else { /* Moved from one to another */ 2112c2c66affSColin Finck TOOLTIPS_Hide (infoPtr); 2113c2c66affSColin Finck KillTimer(infoPtr->hwndSelf, ID_TIMERLEAVE); 2114c2c66affSColin Finck if(infoPtr->bActive) { 2115c2c66affSColin Finck SetTimer (infoPtr->hwndSelf, ID_TIMERSHOW, infoPtr->nReshowTime, 0); 2116c2c66affSColin Finck TRACE("timer 1 started!\n"); 2117c2c66affSColin Finck } 2118c2c66affSColin Finck } 2119c2c66affSColin Finck } 2120c2c66affSColin Finck break; 2121c2c66affSColin Finck 2122c2c66affSColin Finck default: 2123c2c66affSColin Finck ERR("Unknown timer id %d\n", iTimer); 2124c2c66affSColin Finck break; 2125c2c66affSColin Finck } 2126c2c66affSColin Finck return 0; 2127c2c66affSColin Finck } 2128c2c66affSColin Finck 2129c2c66affSColin Finck 2130c2c66affSColin Finck static LRESULT 2131c2c66affSColin Finck TOOLTIPS_WinIniChange (TOOLTIPS_INFO *infoPtr) 2132c2c66affSColin Finck { 2133c2c66affSColin Finck TOOLTIPS_InitSystemSettings (infoPtr); 2134c2c66affSColin Finck 2135c2c66affSColin Finck return 0; 2136c2c66affSColin Finck } 2137c2c66affSColin Finck 2138c2c66affSColin Finck 2139c2c66affSColin Finck static LRESULT CALLBACK 2140edd99e8cSAmine Khaldi TOOLTIPS_SubclassProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwRef) 2141c2c66affSColin Finck { 2142c2c66affSColin Finck TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr ((HWND)dwRef); 2143c2c66affSColin Finck MSG msg; 2144c2c66affSColin Finck 2145edd99e8cSAmine Khaldi switch (message) 2146edd99e8cSAmine Khaldi { 2147c2c66affSColin Finck case WM_MOUSEMOVE: 2148c2c66affSColin Finck case WM_LBUTTONDOWN: 2149c2c66affSColin Finck case WM_LBUTTONUP: 2150c2c66affSColin Finck case WM_MBUTTONDOWN: 2151c2c66affSColin Finck case WM_MBUTTONUP: 2152c2c66affSColin Finck case WM_RBUTTONDOWN: 2153c2c66affSColin Finck case WM_RBUTTONUP: 2154edd99e8cSAmine Khaldi if (infoPtr) 2155edd99e8cSAmine Khaldi { 2156c2c66affSColin Finck msg.hwnd = hwnd; 2157edd99e8cSAmine Khaldi msg.message = message; 2158c2c66affSColin Finck msg.wParam = wParam; 2159c2c66affSColin Finck msg.lParam = lParam; 2160c2c66affSColin Finck TOOLTIPS_RelayEvent(infoPtr, &msg); 2161edd99e8cSAmine Khaldi } 2162c2c66affSColin Finck break; 2163edd99e8cSAmine Khaldi case WM_NCDESTROY: 2164edd99e8cSAmine Khaldi RemoveWindowSubclass(hwnd, TOOLTIPS_SubclassProc, 1); 2165edd99e8cSAmine Khaldi break; 2166c2c66affSColin Finck default: 2167c2c66affSColin Finck break; 2168c2c66affSColin Finck } 2169edd99e8cSAmine Khaldi 2170edd99e8cSAmine Khaldi return DefSubclassProc(hwnd, message, wParam, lParam); 2171c2c66affSColin Finck } 2172c2c66affSColin Finck 2173c2c66affSColin Finck 2174c2c66affSColin Finck static LRESULT CALLBACK 2175c2c66affSColin Finck TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 2176c2c66affSColin Finck { 2177c2c66affSColin Finck TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); 2178c2c66affSColin Finck 2179c2c66affSColin Finck TRACE("hwnd=%p msg=%x wparam=%lx lParam=%lx\n", hwnd, uMsg, wParam, lParam); 2180c2c66affSColin Finck if (!infoPtr && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE)) 2181c2c66affSColin Finck return DefWindowProcW (hwnd, uMsg, wParam, lParam); 2182c2c66affSColin Finck switch (uMsg) 2183c2c66affSColin Finck { 2184c2c66affSColin Finck case TTM_ACTIVATE: 2185c2c66affSColin Finck return TOOLTIPS_Activate (infoPtr, (BOOL)wParam); 2186c2c66affSColin Finck 2187c2c66affSColin Finck case TTM_ADDTOOLA: 2188c2c66affSColin Finck case TTM_ADDTOOLW: 2189c2c66affSColin Finck return TOOLTIPS_AddToolT (infoPtr, (LPTTTOOLINFOW)lParam, uMsg == TTM_ADDTOOLW); 2190c2c66affSColin Finck 2191c2c66affSColin Finck case TTM_DELTOOLA: 2192c2c66affSColin Finck case TTM_DELTOOLW: 2193c2c66affSColin Finck return TOOLTIPS_DelToolT (infoPtr, (LPTOOLINFOW)lParam, 2194c2c66affSColin Finck uMsg == TTM_DELTOOLW); 2195c2c66affSColin Finck case TTM_ENUMTOOLSA: 2196c2c66affSColin Finck case TTM_ENUMTOOLSW: 2197c2c66affSColin Finck return TOOLTIPS_EnumToolsT (infoPtr, (UINT)wParam, (LPTTTOOLINFOW)lParam, 2198c2c66affSColin Finck uMsg == TTM_ENUMTOOLSW); 2199c2c66affSColin Finck case TTM_GETBUBBLESIZE: 2200c2c66affSColin Finck return TOOLTIPS_GetBubbleSize (infoPtr, (LPTTTOOLINFOW)lParam); 2201c2c66affSColin Finck 2202c2c66affSColin Finck case TTM_GETCURRENTTOOLA: 2203c2c66affSColin Finck case TTM_GETCURRENTTOOLW: 2204c2c66affSColin Finck return TOOLTIPS_GetCurrentToolT (infoPtr, (LPTTTOOLINFOW)lParam, 2205c2c66affSColin Finck uMsg == TTM_GETCURRENTTOOLW); 2206c2c66affSColin Finck 2207c2c66affSColin Finck case TTM_GETDELAYTIME: 2208c2c66affSColin Finck return TOOLTIPS_GetDelayTime (infoPtr, (DWORD)wParam); 2209c2c66affSColin Finck 2210c2c66affSColin Finck case TTM_GETMARGIN: 2211c2c66affSColin Finck return TOOLTIPS_GetMargin (infoPtr, (LPRECT)lParam); 2212c2c66affSColin Finck 2213c2c66affSColin Finck case TTM_GETMAXTIPWIDTH: 2214c2c66affSColin Finck return TOOLTIPS_GetMaxTipWidth (infoPtr); 2215c2c66affSColin Finck 2216c2c66affSColin Finck case TTM_GETTEXTA: 2217c2c66affSColin Finck case TTM_GETTEXTW: 2218c2c66affSColin Finck return TOOLTIPS_GetTextT (infoPtr, (LPTTTOOLINFOW)lParam, 2219c2c66affSColin Finck uMsg == TTM_GETTEXTW); 2220c2c66affSColin Finck 2221c2c66affSColin Finck case TTM_GETTIPBKCOLOR: 2222c2c66affSColin Finck return TOOLTIPS_GetTipBkColor (infoPtr); 2223c2c66affSColin Finck 2224c2c66affSColin Finck case TTM_GETTIPTEXTCOLOR: 2225c2c66affSColin Finck return TOOLTIPS_GetTipTextColor (infoPtr); 2226c2c66affSColin Finck 2227c2c66affSColin Finck case TTM_GETTOOLCOUNT: 2228c2c66affSColin Finck return TOOLTIPS_GetToolCount (infoPtr); 2229c2c66affSColin Finck 2230c2c66affSColin Finck case TTM_GETTOOLINFOA: 2231c2c66affSColin Finck case TTM_GETTOOLINFOW: 2232c2c66affSColin Finck return TOOLTIPS_GetToolInfoT (infoPtr, (LPTTTOOLINFOW)lParam, 2233c2c66affSColin Finck uMsg == TTM_GETTOOLINFOW); 2234c2c66affSColin Finck 2235c2c66affSColin Finck case TTM_HITTESTA: 2236c2c66affSColin Finck case TTM_HITTESTW: 2237c2c66affSColin Finck return TOOLTIPS_HitTestT (infoPtr, (LPTTHITTESTINFOW)lParam, 2238c2c66affSColin Finck uMsg == TTM_HITTESTW); 2239c2c66affSColin Finck case TTM_NEWTOOLRECTA: 2240c2c66affSColin Finck case TTM_NEWTOOLRECTW: 2241c2c66affSColin Finck return TOOLTIPS_NewToolRectT (infoPtr, (LPTTTOOLINFOW)lParam); 2242c2c66affSColin Finck 2243c2c66affSColin Finck case TTM_POP: 2244c2c66affSColin Finck return TOOLTIPS_Pop (infoPtr); 2245c2c66affSColin Finck 2246c2c66affSColin Finck case TTM_RELAYEVENT: 2247c2c66affSColin Finck return TOOLTIPS_RelayEvent (infoPtr, (LPMSG)lParam); 2248c2c66affSColin Finck 2249c2c66affSColin Finck case TTM_SETDELAYTIME: 2250c2c66affSColin Finck return TOOLTIPS_SetDelayTime (infoPtr, (DWORD)wParam, (INT)LOWORD(lParam)); 2251c2c66affSColin Finck 2252c2c66affSColin Finck case TTM_SETMARGIN: 2253c2c66affSColin Finck return TOOLTIPS_SetMargin (infoPtr, (LPRECT)lParam); 2254c2c66affSColin Finck 2255c2c66affSColin Finck case TTM_SETMAXTIPWIDTH: 2256c2c66affSColin Finck return TOOLTIPS_SetMaxTipWidth (infoPtr, (INT)lParam); 2257c2c66affSColin Finck 2258c2c66affSColin Finck case TTM_SETTIPBKCOLOR: 2259c2c66affSColin Finck return TOOLTIPS_SetTipBkColor (infoPtr, (COLORREF)wParam); 2260c2c66affSColin Finck 2261c2c66affSColin Finck case TTM_SETTIPTEXTCOLOR: 2262c2c66affSColin Finck return TOOLTIPS_SetTipTextColor (infoPtr, (COLORREF)wParam); 2263c2c66affSColin Finck 2264c2c66affSColin Finck case TTM_SETTITLEA: 2265c2c66affSColin Finck case TTM_SETTITLEW: 2266c2c66affSColin Finck return TOOLTIPS_SetTitleT (infoPtr, (UINT_PTR)wParam, (LPCWSTR)lParam, 2267c2c66affSColin Finck uMsg == TTM_SETTITLEW); 2268c2c66affSColin Finck 2269c2c66affSColin Finck case TTM_SETTOOLINFOA: 2270c2c66affSColin Finck case TTM_SETTOOLINFOW: 2271c2c66affSColin Finck return TOOLTIPS_SetToolInfoT (infoPtr, (LPTTTOOLINFOW)lParam, 2272c2c66affSColin Finck uMsg == TTM_SETTOOLINFOW); 2273c2c66affSColin Finck 2274c2c66affSColin Finck case TTM_TRACKACTIVATE: 2275c2c66affSColin Finck return TOOLTIPS_TrackActivate (infoPtr, (BOOL)wParam, (LPTTTOOLINFOA)lParam); 2276c2c66affSColin Finck 2277c2c66affSColin Finck case TTM_TRACKPOSITION: 2278c2c66affSColin Finck return TOOLTIPS_TrackPosition (infoPtr, lParam); 2279c2c66affSColin Finck 2280c2c66affSColin Finck case TTM_UPDATE: 2281c2c66affSColin Finck return TOOLTIPS_Update (infoPtr); 2282c2c66affSColin Finck 2283c2c66affSColin Finck case TTM_UPDATETIPTEXTA: 2284c2c66affSColin Finck case TTM_UPDATETIPTEXTW: 2285c2c66affSColin Finck return TOOLTIPS_UpdateTipTextT (infoPtr, (LPTTTOOLINFOW)lParam, 2286c2c66affSColin Finck uMsg == TTM_UPDATETIPTEXTW); 2287c2c66affSColin Finck 2288c2c66affSColin Finck case TTM_WINDOWFROMPOINT: 2289c2c66affSColin Finck return (LRESULT)WindowFromPoint (*((LPPOINT)lParam)); 2290c2c66affSColin Finck 2291c2c66affSColin Finck case WM_CREATE: 2292c2c66affSColin Finck return TOOLTIPS_Create (hwnd); 2293c2c66affSColin Finck 2294c2c66affSColin Finck case WM_DESTROY: 2295c2c66affSColin Finck return TOOLTIPS_Destroy (infoPtr); 2296c2c66affSColin Finck 2297c2c66affSColin Finck case WM_ERASEBKGND: 2298c2c66affSColin Finck /* we draw the background in WM_PAINT */ 2299c2c66affSColin Finck return 0; 2300c2c66affSColin Finck 2301c2c66affSColin Finck case WM_GETFONT: 2302c2c66affSColin Finck return TOOLTIPS_GetFont (infoPtr); 2303c2c66affSColin Finck 2304c2c66affSColin Finck case WM_GETTEXT: 2305c2c66affSColin Finck return TOOLTIPS_OnWMGetText (infoPtr, wParam, (LPWSTR)lParam); 2306c2c66affSColin Finck 2307c2c66affSColin Finck case WM_GETTEXTLENGTH: 2308c2c66affSColin Finck return TOOLTIPS_GetTextLength (infoPtr); 2309c2c66affSColin Finck 2310c2c66affSColin Finck case WM_LBUTTONDOWN: 2311c2c66affSColin Finck case WM_LBUTTONUP: 2312c2c66affSColin Finck case WM_MBUTTONDOWN: 2313c2c66affSColin Finck case WM_MBUTTONUP: 2314c2c66affSColin Finck case WM_RBUTTONDOWN: 2315c2c66affSColin Finck case WM_RBUTTONUP: 2316c2c66affSColin Finck case WM_MOUSEMOVE: 2317c2c66affSColin Finck return TOOLTIPS_MouseMessage (infoPtr); 2318c2c66affSColin Finck 2319c2c66affSColin Finck case WM_NCCREATE: 2320c2c66affSColin Finck return TOOLTIPS_NCCreate (hwnd); 2321c2c66affSColin Finck 2322c2c66affSColin Finck case WM_NCHITTEST: 2323c2c66affSColin Finck return TOOLTIPS_NCHitTest (infoPtr, wParam, lParam); 2324c2c66affSColin Finck 2325c2c66affSColin Finck case WM_NOTIFYFORMAT: 2326c2c66affSColin Finck return TOOLTIPS_NotifyFormat (infoPtr, wParam, lParam); 2327c2c66affSColin Finck 2328c2c66affSColin Finck case WM_PRINTCLIENT: 2329c2c66affSColin Finck case WM_PAINT: 2330c2c66affSColin Finck return TOOLTIPS_Paint (infoPtr, (HDC)wParam); 2331c2c66affSColin Finck 2332c2c66affSColin Finck case WM_SETFONT: 2333c2c66affSColin Finck return TOOLTIPS_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam)); 2334c2c66affSColin Finck 2335c2c66affSColin Finck case WM_SYSCOLORCHANGE: 2336c2c66affSColin Finck COMCTL32_RefreshSysColors(); 2337c2c66affSColin Finck return 0; 2338c2c66affSColin Finck 2339c2c66affSColin Finck case WM_TIMER: 2340c2c66affSColin Finck return TOOLTIPS_Timer (infoPtr, (INT)wParam); 2341c2c66affSColin Finck 2342c2c66affSColin Finck case WM_WININICHANGE: 2343c2c66affSColin Finck return TOOLTIPS_WinIniChange (infoPtr); 2344c2c66affSColin Finck 2345c2c66affSColin Finck default: 2346c2c66affSColin Finck if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg)) 2347c2c66affSColin Finck ERR("unknown msg %04x wp=%08lx lp=%08lx\n", 2348c2c66affSColin Finck uMsg, wParam, lParam); 2349c2c66affSColin Finck return DefWindowProcW (hwnd, uMsg, wParam, lParam); 2350c2c66affSColin Finck } 2351c2c66affSColin Finck } 2352c2c66affSColin Finck 2353c2c66affSColin Finck 2354c2c66affSColin Finck VOID 2355c2c66affSColin Finck TOOLTIPS_Register (void) 2356c2c66affSColin Finck { 2357c2c66affSColin Finck WNDCLASSW wndClass; 2358c2c66affSColin Finck 2359c2c66affSColin Finck ZeroMemory (&wndClass, sizeof(WNDCLASSW)); 2360c2c66affSColin Finck wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS; 2361c2c66affSColin Finck wndClass.lpfnWndProc = TOOLTIPS_WindowProc; 2362c2c66affSColin Finck wndClass.cbClsExtra = 0; 2363c2c66affSColin Finck wndClass.cbWndExtra = sizeof(TOOLTIPS_INFO *); 2364c2c66affSColin Finck wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); 2365c2c66affSColin Finck wndClass.hbrBackground = 0; 2366c2c66affSColin Finck wndClass.lpszClassName = TOOLTIPS_CLASSW; 2367c2c66affSColin Finck 2368c2c66affSColin Finck RegisterClassW (&wndClass); 2369c2c66affSColin Finck 2370c2c66affSColin Finck hTooltipIcons[TTI_NONE] = NULL; 2371c2c66affSColin Finck hTooltipIcons[TTI_INFO] = LoadImageW(COMCTL32_hModule, 2372c2c66affSColin Finck (LPCWSTR)MAKEINTRESOURCE(IDI_TT_INFO_SM), IMAGE_ICON, 0, 0, 0); 2373c2c66affSColin Finck hTooltipIcons[TTI_WARNING] = LoadImageW(COMCTL32_hModule, 2374c2c66affSColin Finck (LPCWSTR)MAKEINTRESOURCE(IDI_TT_WARN_SM), IMAGE_ICON, 0, 0, 0); 2375c2c66affSColin Finck hTooltipIcons[TTI_ERROR] = LoadImageW(COMCTL32_hModule, 2376c2c66affSColin Finck (LPCWSTR)MAKEINTRESOURCE(IDI_TT_ERROR_SM), IMAGE_ICON, 0, 0, 0); 2377c2c66affSColin Finck } 2378c2c66affSColin Finck 2379c2c66affSColin Finck 2380c2c66affSColin Finck VOID 2381c2c66affSColin Finck TOOLTIPS_Unregister (void) 2382c2c66affSColin Finck { 2383c2c66affSColin Finck int i; 2384c2c66affSColin Finck for (i = TTI_INFO; i <= TTI_ERROR; i++) 2385c2c66affSColin Finck DestroyIcon(hTooltipIcons[i]); 2386c2c66affSColin Finck UnregisterClassW (TOOLTIPS_CLASSW, NULL); 2387c2c66affSColin Finck } 2388