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