📄 tooltips.c
字号:
DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT);
SelectObject (hdc, hOldFont);
title.cy = max(title.cy, rcTitle.bottom - rcTitle.top) + BALLOON_TITLE_TEXT_SPACING;
title.cx += (rcTitle.right - rcTitle.left);
}
hOldFont = SelectObject (hdc, infoPtr->hFont);
DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
SelectObject (hdc, hOldFont);
ReleaseDC (hwnd, hdc);
if ((style & TTS_BALLOON) || infoPtr->pszTitle)
{
lpSize->cx = max(rc.right - rc.left, title.cx) + 2*BALLOON_TEXT_MARGIN +
infoPtr->rcMargin.left + infoPtr->rcMargin.right;
lpSize->cy = title.cy + rc.bottom - rc.top + 2*BALLOON_TEXT_MARGIN +
infoPtr->rcMargin.bottom + infoPtr->rcMargin.top +
BALLOON_STEMHEIGHT;
}
else
{
lpSize->cx = rc.right - rc.left + 2*NORMAL_TEXT_MARGIN +
infoPtr->rcMargin.left + infoPtr->rcMargin.right;
lpSize->cy = rc.bottom - rc.top + 2*NORMAL_TEXT_MARGIN +
infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
}
}
static void
TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr)
{
TTTOOL_INFO *toolPtr;
HMONITOR monitor;
MONITORINFO mon_info;
RECT rect;
SIZE size;
NMHDR hdr;
int ptfx = 0;
DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
if (infoPtr->nTool == -1) {
TRACE("invalid tool (-1)!\n");
return;
}
infoPtr->nCurrentTool = infoPtr->nTool;
TRACE("Show tooltip pre %d! (%p)\n", infoPtr->nTool, hwnd);
TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);
if (infoPtr->szTipText[0] == L'\0') {
infoPtr->nCurrentTool = -1;
return;
}
TRACE("Show tooltip %d!\n", infoPtr->nCurrentTool);
toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
hdr.hwndFrom = hwnd;
hdr.idFrom = toolPtr->uId;
hdr.code = TTN_SHOW;
SendMessageW (toolPtr->hwnd, WM_NOTIFY,
(WPARAM)toolPtr->uId, (LPARAM)&hdr);
TRACE("%s\n", debugstr_w(infoPtr->szTipText));
TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
TRACE("size %d x %d\n", size.cx, size.cy);
if (toolPtr->uFlags & TTF_CENTERTIP) {
RECT rc;
if (toolPtr->uFlags & TTF_IDISHWND)
GetWindowRect ((HWND)toolPtr->uId, &rc);
else {
rc = toolPtr->rect;
MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2);
}
rect.left = (rc.left + rc.right - size.cx) / 2;
if (style & TTS_BALLOON)
{
ptfx = rc.left + ((rc.right - rc.left) / 2);
if(rect.top - size.cy >= 0)
{
rect.top -= size.cy;
infoPtr->bToolBelow = FALSE;
}
else
{
infoPtr->bToolBelow = TRUE;
rect.top += 20;
}
rect.left = max(0, rect.left - BALLOON_STEMINDENT);
}
else
{
rect.top = rc.bottom + 2;
infoPtr->bToolBelow = TRUE;
}
}
else {
GetCursorPos ((LPPOINT)&rect);
if (style & TTS_BALLOON)
{
ptfx = rect.left;
if(rect.top - size.cy >= 0)
{
rect.top -= size.cy;
infoPtr->bToolBelow = FALSE;
}
else
{
infoPtr->bToolBelow = TRUE;
rect.top += 20;
}
rect.left = max(0, rect.left - BALLOON_STEMINDENT);
}
else
{
rect.top += 20;
infoPtr->bToolBelow = TRUE;
}
}
TRACE("pos %d - %d\n", rect.left, rect.top);
rect.right = rect.left + size.cx;
rect.bottom = rect.top + size.cy;
/* check position */
monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
mon_info.cbSize = sizeof(mon_info);
GetMonitorInfoW( monitor, &mon_info );
if( rect.right > mon_info.rcWork.right ) {
rect.left -= rect.right - mon_info.rcWork.right + 2;
rect.right = mon_info.rcWork.right - 2;
}
if (rect.left < mon_info.rcWork.left) rect.left = mon_info.rcWork.left;
if( rect.bottom > mon_info.rcWork.bottom ) {
RECT rc;
if (toolPtr->uFlags & TTF_IDISHWND)
GetWindowRect ((HWND)toolPtr->uId, &rc);
else {
rc = toolPtr->rect;
MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2);
}
rect.bottom = rc.top - 2;
rect.top = rect.bottom - size.cy;
}
AdjustWindowRectEx (&rect, GetWindowLongW (hwnd, GWL_STYLE),
FALSE, GetWindowLongW (hwnd, GWL_EXSTYLE));
if (style & TTS_BALLOON)
{
HRGN hRgn;
HRGN hrStem;
POINT pts[3];
ptfx -= rect.left;
if(infoPtr->bToolBelow)
{
pts[0].x = ptfx;
pts[0].y = 0;
pts[1].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2));
pts[1].y = BALLOON_STEMHEIGHT;
pts[2].x = pts[1].x + BALLOON_STEMWIDTH;
pts[2].y = pts[1].y;
if(pts[2].x > (rect.right - rect.left) - BALLOON_STEMINDENT)
{
pts[2].x = (rect.right - rect.left) - BALLOON_STEMINDENT;
pts[1].x = pts[2].x - BALLOON_STEMWIDTH;
}
}
else
{
pts[0].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2));
pts[0].y = (rect.bottom - rect.top) - BALLOON_STEMHEIGHT;
pts[1].x = pts[0].x + BALLOON_STEMWIDTH;
pts[1].y = pts[0].y;
pts[2].x = ptfx;
pts[2].y = (rect.bottom - rect.top);
if(pts[1].x > (rect.right - rect.left) - BALLOON_STEMINDENT)
{
pts[1].x = (rect.right - rect.left) - BALLOON_STEMINDENT;
pts[0].x = pts[1].x - BALLOON_STEMWIDTH;
}
}
hrStem = CreatePolygonRgn(pts, sizeof(pts) / sizeof(pts[0]), ALTERNATE);
hRgn = CreateRoundRectRgn(0,
(infoPtr->bToolBelow ? BALLOON_STEMHEIGHT : 0),
rect.right - rect.left,
(infoPtr->bToolBelow ? rect.bottom - rect.top : rect.bottom - rect.top - BALLOON_STEMHEIGHT),
BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS);
CombineRgn(hRgn, hRgn, hrStem, RGN_OR);
DeleteObject(hrStem);
SetWindowRgn(hwnd, hRgn, FALSE);
/* we don't free the region handle as the system deletes it when
* it is no longer needed */
}
SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW | SWP_NOACTIVATE);
/* repaint the tooltip */
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
TRACE("timer 2 started!\n");
SetTimer (hwnd, ID_TIMERLEAVE, infoPtr->nReshowTime, 0);
TRACE("timer 3 started!\n");
}
static void
TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
{
TTTOOL_INFO *toolPtr;
NMHDR hdr;
TRACE("Hide tooltip %d! (%p)\n", infoPtr->nCurrentTool, hwnd);
if (infoPtr->nCurrentTool == -1)
return;
toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
KillTimer (hwnd, ID_TIMERPOP);
hdr.hwndFrom = hwnd;
hdr.idFrom = toolPtr->uId;
hdr.code = TTN_POP;
SendMessageW (toolPtr->hwnd, WM_NOTIFY,
(WPARAM)toolPtr->uId, (LPARAM)&hdr);
infoPtr->nCurrentTool = -1;
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
}
static void
TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr)
{
TTTOOL_INFO *toolPtr;
RECT rect;
SIZE size;
NMHDR hdr;
if (infoPtr->nTrackTool == -1) {
TRACE("invalid tracking tool (-1)!\n");
return;
}
TRACE("show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool);
if (infoPtr->szTipText[0] == L'\0') {
infoPtr->nTrackTool = -1;
return;
}
TRACE("show tracking tooltip %d!\n", infoPtr->nTrackTool);
toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
hdr.hwndFrom = hwnd;
hdr.idFrom = toolPtr->uId;
hdr.code = TTN_SHOW;
SendMessageW (toolPtr->hwnd, WM_NOTIFY,
(WPARAM)toolPtr->uId, (LPARAM)&hdr);
TRACE("%s\n", debugstr_w(infoPtr->szTipText));
TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
TRACE("size %d x %d\n", size.cx, size.cy);
if (toolPtr->uFlags & TTF_ABSOLUTE) {
rect.left = infoPtr->xTrackPos;
rect.top = infoPtr->yTrackPos;
if (toolPtr->uFlags & TTF_CENTERTIP) {
rect.left -= (size.cx / 2);
rect.top -= (size.cy / 2);
}
}
else {
RECT rcTool;
if (toolPtr->uFlags & TTF_IDISHWND)
GetWindowRect ((HWND)toolPtr->uId, &rcTool);
else {
rcTool = toolPtr->rect;
MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rcTool, 2);
}
GetCursorPos ((LPPOINT)&rect);
rect.top += 20;
if (toolPtr->uFlags & TTF_CENTERTIP) {
rect.left -= (size.cx / 2);
rect.top -= (size.cy / 2);
}
/* smart placement */
if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
(rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
rect.left = rcTool.right;
}
TRACE("pos %d - %d\n", rect.left, rect.top);
rect.right = rect.left + size.cx;
rect.bottom = rect.top + size.cy;
AdjustWindowRectEx (&rect, GetWindowLongW (hwnd, GWL_STYLE),
FALSE, GetWindowLongW (hwnd, GWL_EXSTYLE));
if (GetWindowLongW(hwnd, GWL_STYLE) & TTS_BALLOON)
{
HRGN hRgn;
/* FIXME: need to add pointy bit using CreatePolyRgn & CombinRgn */
hRgn = CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS);
SetWindowRgn(hwnd, hRgn, FALSE);
/* we don't free the region handle as the system deletes it when
* it is no longer needed */
}
SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW | SWP_NOACTIVATE );
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
static void
TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
{
TTTOOL_INFO *toolPtr;
NMHDR hdr;
TRACE("hide tracking tooltip %d\n", infoPtr->nTrackTool);
if (infoPtr->nTrackTool == -1)
return;
toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
hdr.hwndFrom = hwnd;
hdr.idFrom = toolPtr->uId;
hdr.code = TTN_POP;
SendMessageW (toolPtr->hwnd, WM_NOTIFY,
(WPARAM)toolPtr->uId, (LPARAM)&hdr);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
}
static INT
TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
{
TTTOOL_INFO *toolPtr;
INT nTool;
for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
toolPtr = &infoPtr->tools[nTool];
if (!(toolPtr->uFlags & TTF_IDISHWND) &&
(lpToolInfo->hwnd == toolPtr->hwnd) &&
(lpToolInfo->uId == toolPtr->uId))
return nTool;
}
for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
toolPtr = &infoPtr->tools[nTool];
if ((toolPtr->uFlags & TTF_IDISHWND) &&
(lpToolInfo->uId == toolPtr->uId))
return nTool;
}
return -1;
}
static INT
TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
{
TTTOOL_INFO *toolPtr;
INT nTool;
for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
toolPtr = &infoPtr->tools[nTool];
if (!(toolPtr->uFlags & TTF_IDISHWND) &&
(lpToolInfo->hwnd == toolPtr->hwnd) &&
(lpToolInfo->uId == toolPtr->uId))
return nTool;
}
for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
toolPtr = &infoPtr->tools[nTool];
if ((toolPtr->uFlags & TTF_IDISHWND) &&
(lpToolInfo->uId == toolPtr->uId))
return nTool;
}
return -1;
}
static INT
TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt)
{
TTTOOL_INFO *toolPtr;
INT nTool;
for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
toolPtr = &infoPtr->tools[nTool];
if (!(toolPtr->uFlags & TTF_IDISHWND)) {
if (hwnd != toolPtr->hwnd)
continue;
if (!PtInRect (&toolPtr->rect, *lpPt))
continue;
return nTool;
}
}
for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
toolPtr = &infoPtr->tools[nTool];
if (toolPtr->uFlags & TTF_IDISHWND) {
if ((HWND)toolPtr->uId == hwnd)
return nTool;
}
}
return -1;
}
static BOOL
TOOLTIPS_IsWindowActive (HWND hwnd)
{
HWND hwndActive = GetActiveWindow ();
if (!hwndActive)
return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -