123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- #include "main.h"
- #include "./listWidgetInternal.h"
- #include <strsafe.h>
- #define TOOLTIP_MARGIN_LEFT_DLU 3
- #define TOOLTIP_MARGIN_TOP_DLU 1
- #define TOOLTIP_MARGIN_RIGHT_DLU 3
- #define TOOLTIP_MARGIN_BOTTOM_DLU 1
- #define TOOLTIP_DELAY_INITIAL 1000
- #define TOOLTIP_DELAY_RESHOW 400
- static ATOM LISTWIDGETTOOLTIP_PROP = 0;
- static LRESULT WINAPI
- ListWidgetTooltip_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- typedef struct ListWidgetTooltip
- {
- HWND window;
- HWND owner;
- BOOL active;
- POINT position;
- wchar_t *buffer;
- ListWidgetItem *item;
- ListWidgetItemPart part;
- RECT partRect;
- BOOL blockLocationChange;
- WNDPROC originalProc;
- DWORD showTime;
- } ListWidgetTooltip;
- static HWND
- ListWidget_TooltipCreateWindow(HWND owner, WNDPROC *originalProc, HANDLE windowProperty)
- {
- HWND hwnd;
- TOOLINFO ti;
- hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT | WS_EX_LAYERED,
- TOOLTIPS_CLASS, NULL, WS_CLIPSIBLINGS | WS_POPUP | TTS_NOANIMATE | TTS_ALWAYSTIP,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- owner, NULL, NULL, NULL);
- if ( hwnd == NULL )
- return NULL;
- MLSkinWindow2(Plugin_GetLibraryWindow(), hwnd, SKINNEDWND_TYPE_TOOLTIP,
- SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
- if (NULL != originalProc)
- {
- if (0 == LISTWIDGETTOOLTIP_PROP)
- LISTWIDGETTOOLTIP_PROP = GlobalAddAtom(TEXT("ListWidgetTooltipProp"));
- if (0 != LISTWIDGETTOOLTIP_PROP)
- {
- *originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
- (LONGX86)(LONG_PTR)ListWidgetTooltip_WindowProc);
- if (NULL != *originalProc &&
- FALSE == SetProp(hwnd, MAKEINTATOM(LISTWIDGETTOOLTIP_PROP), windowProperty))
- {
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)*originalProc);
- *originalProc = NULL;
- }
- }
- else
- *originalProc = NULL;
- }
- SendMessage(hwnd, CCM_SETVERSION, 6, 0L);
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
- ZeroMemory(&ti, sizeof(ti));
- ti.cbSize = sizeof(ti);
- ti.hwnd = owner;
- ti.lpszText = LPSTR_TEXTCALLBACK;
- ti.uFlags = 0/*TTF_TRACK | TTF_ABSOLUTE*/;
-
- SendMessage(hwnd, TTM_ADDTOOL, 0, (LPARAM)&ti);
- return hwnd;
- }
- ListWidgetTooltip*
- ListWidget_TooltipCreate(HWND hwnd)
- {
- ListWidgetTooltip *tooltip;
- tooltip = (ListWidgetTooltip*)malloc(sizeof(ListWidgetTooltip));
- if (NULL == tooltip)
- return FALSE;
- ZeroMemory(tooltip, sizeof(ListWidgetTooltip));
- tooltip->window = ListWidget_TooltipCreateWindow(hwnd, &tooltip->originalProc, tooltip);
- if (NULL == tooltip->window)
- {
- ListWidget_TooltipDestroy(tooltip);
- return NULL;
- }
- tooltip->owner = hwnd;
- ListWidget_TooltipFontChanged(tooltip);
-
- return tooltip;
- }
- void
- ListWidget_TooltipDestroy(ListWidgetTooltip *tooltip)
- {
- if (NULL != tooltip)
- {
- if (NULL != tooltip->window)
- DestroyWindow(tooltip->window);
- String_Free(tooltip->buffer);
-
- free(tooltip);
- }
- }
- void
- ListWidget_TooltipFontChanged(ListWidgetTooltip *tooltip)
- {
- WidgetStyle *style;
- RECT marginsRect;
- HDC hdc;
- long maxWidth;
- if (NULL == tooltip)
- return;
- if (NULL == tooltip->window)
- {
- // attempt to recover...
- tooltip->window = ListWidget_TooltipCreateWindow(tooltip->owner, &tooltip->originalProc, tooltip);
- if (NULL == tooltip->window)
- return;
- tooltip->active = FALSE;
- tooltip->part = ListWidgetItemPart_None;
- SetRectEmpty(&tooltip->partRect);
- }
- style = WIDGET_GET_STYLE(tooltip->owner);
- if (NULL == style)
- return;
- hdc = GetDCEx(tooltip->window, NULL, DCX_CACHE | DCX_NORESETATTRS);
- if (NULL != hdc)
- {
- HFONT font = (HFONT)SendMessage(tooltip->window, WM_GETFONT, 0, 0L);
- HFONT prevFont = SelectFont(hdc, font);
- maxWidth = Graphics_GetAveStrWidth(hdc, 36);
- SelectFont(hdc, prevFont);
- ReleaseDC(tooltip->window, hdc);
- }
- else
- maxWidth = 100;
- SendMessage(tooltip->window, TTM_SETMAXTIPWIDTH, 0, (LPARAM)maxWidth);
- WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(marginsRect.left, style, TOOLTIP_MARGIN_LEFT_DLU, 3);
- WIDGETSTYLE_DLU_TO_VERT_PX_MIN(marginsRect.top, style, TOOLTIP_MARGIN_TOP_DLU, 2);
- WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(marginsRect.right, style, TOOLTIP_MARGIN_RIGHT_DLU, 3);
- WIDGETSTYLE_DLU_TO_VERT_PX_MIN(marginsRect.bottom, style, TOOLTIP_MARGIN_BOTTOM_DLU, 2);
- SendMessage(tooltip->window, TTM_SETMARGIN, 0, (LPARAM)&marginsRect);
- }
- void
- ListWidget_TooltipRelayMouseMessage(ListWidgetTooltip *tooltip, unsigned int message, unsigned int vKeys, const POINT *cursor)
- {
- if (NULL != tooltip &&
- NULL != tooltip->window &&
- FALSE != tooltip->active)
- {
- MSG msg;
- msg.hwnd = tooltip->owner;
- msg.message = message;
- msg.wParam = (WPARAM)vKeys;
- msg.lParam = MAKELPARAM(cursor->x, cursor->y);
- SendMessage(tooltip->window, TTM_RELAYEVENT, 0, (LPARAM)&msg);
- }
- }
- void
- ListWidget_TooltipHide(ListWidgetTooltip *tooltip)
- {
- if (NULL == tooltip ||
- NULL == tooltip->window ||
- FALSE == tooltip->active)
- {
- return;
- }
- tooltip->active = FALSE;
- tooltip->part = ListWidgetItemPart_None;
- SetRectEmpty(&tooltip->partRect);
- SendMessage(tooltip->window, TTM_ACTIVATE, FALSE, 0);
- }
- BOOL
- ListWidget_TooltipActivate(ListWidgetTooltip *tooltip, const RECT *rect)
- {
- TOOLINFO ti;
- POINT origin;
- if (NULL == tooltip ||
- NULL == tooltip->window)
- {
- return FALSE;
- }
-
- ZeroMemory(&ti, sizeof(ti));
- ti.cbSize = sizeof(ti);
- ti.hwnd = tooltip->owner;
- ti.uId = 0;
-
- if (FALSE == SendMessage(tooltip->window, TTM_GETTOOLINFO, 0, (LPARAM)&ti))
- return FALSE;
-
- if (FALSE != tooltip->active)
- {
- tooltip->active = FALSE;
- SendMessage(tooltip->window, TTM_ACTIVATE, FALSE, 0);
- }
- else
- SendMessage(tooltip->window, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(TOOLTIP_DELAY_INITIAL, 0));
-
-
- CopyRect(&ti.rect, rect);
- if (FALSE != ListWidget_GetViewOrigin(tooltip->owner, &origin))
- OffsetRect(&ti.rect, origin.x, origin.y);
-
- ti.lParam = NULL;
- ti.lpszText = LPSTR_TEXTCALLBACK;
-
- SendMessage(tooltip->window, TTM_SETTOOLINFO, 0, (LPARAM)&ti);
-
- if (FALSE == tooltip->active)
- {
- KillTimer(tooltip->window, 4);
- SendMessage(tooltip->window, TTM_ACTIVATE, TRUE, 0);
- tooltip->active = TRUE;
- }
- return TRUE;
- }
- BOOL
- ListWidget_TooltipUpdate(ListWidgetTooltip *tooltip, ListWidgetItem *item,
- ListWidgetItemPart part, const RECT *partRect)
- {
- BOOL tooltipValid;
- if (NULL == tooltip)
- return FALSE;
- if(FALSE == tooltip->active && NULL == item)
- return FALSE;
- if (0 != (ListWidgetItemPart_Activity & part))
- {
- part &= ~ListWidgetItemPart_Activity;
- part |= ListWidgetItemPart_Frame;
- }
- tooltipValid = (NULL != item && ListWidgetItemPart_None != part);
- if (tooltip->item == item &&
- tooltip->part == part &&
- (FALSE != (FALSE != tooltipValid) ?
- EqualRect(&tooltip->partRect, partRect) :
- IsRectEmpty(&tooltip->partRect)))
- {
-
- return FALSE;
- }
- tooltip->item = item;
- tooltip->part = part;
- if (FALSE != tooltipValid)
- CopyRect(&tooltip->partRect, partRect);
- else
- SetRectEmpty(&tooltip->partRect);
-
- if (FALSE == tooltipValid)
- {
- ListWidget_TooltipHide(tooltip);
- return FALSE;
- }
- return ListWidget_TooltipActivate(tooltip, &tooltip->partRect);
- }
- static BOOL
- ListWidget_TooltipFormatTip(ListWidget *self, HWND hwnd,
- const RECT *rect, wchar_t *buffer, size_t bufferMax)
- {
- WidgetStyle *style;
- ListWidgetItem *item;
- ListWidgetItemPart part;
- ListWidgetItemMetric metrics;
- RECT partRect;
- POINT pt, origin;
- if (NULL == self || NULL == rect)
- return FALSE;
-
- style = WIDGET_GET_STYLE(hwnd);
- if (NULL == style)
- return FALSE;
- if (FALSE == ListWidget_GetItemMetrics(style, &metrics))
- return FALSE;
- if (FALSE == ListWidget_GetViewOrigin(hwnd, &origin))
- {
- origin.x = 0;
- origin.y = 0;
- }
-
- pt.x = (rect->left + (rect->right - rect->left)/2) - origin.x;
- pt.y = (rect->top + (rect->bottom - rect->top)/2) - origin.y;
-
- item = ListWidget_GetItemFromPoint(self, pt);
- if (NULL == item)
- return FALSE;
-
- part = ListWidgetItemPart_Frame |
- ListWidgetItemPart_Command |
- ListWidgetItemPart_Spacebar |
- ListWidgetItemPart_Title;
-
- part = ListWidget_GetItemPartFromPoint(self, item, &metrics, pt, part, &partRect);
- switch(part)
- {
- case ListWidgetItemPart_Command:
- CopyRect(&partRect, rect);
- OffsetRect(&partRect, -origin.x - item->rect.left, -origin.y - item->rect.top);
- return ListWidget_FormatItemCommandTip(self, item, &partRect, buffer, bufferMax);
-
- case ListWidgetItemPart_Activity:
- case ListWidgetItemPart_Frame:
- return ListWidget_FormatItemTip(self, item, buffer, bufferMax);
- case ListWidgetItemPart_Spacebar:
- return ListWidget_FormatItemSpaceTip(self, item, buffer, bufferMax);
- case ListWidgetItemPart_Title:
- return ListWidget_FormatItemTitleTip(self, item, buffer, bufferMax);
- }
- return FALSE;
- }
- static void
- ListWidget_TooltipGetDispInfo(ListWidget *self, ListWidgetTooltip *tooltip, NMTTDISPINFO *dispInfo)
- {
- TOOLINFO ti;
- if (NULL == dispInfo)
- return;
- ZeroMemory(&ti, sizeof(ti));
- ti.cbSize = sizeof(ti);
- ti.hwnd = tooltip->owner;
- ti.uId = dispInfo->hdr.idFrom;
- String_Free(tooltip->buffer);
- tooltip->buffer = NULL;
-
- if (FALSE != SendMessage(dispInfo->hdr.hwndFrom, TTM_GETTOOLINFO, 0, (LPARAM)&ti))
- {
- wchar_t buffer[4096] = {0};
- if (FALSE != ListWidget_TooltipFormatTip(self, tooltip->owner, &ti.rect, buffer, ARRAYSIZE(buffer)))
- tooltip->buffer = String_Duplicate(buffer);
- }
-
- dispInfo->lpszText = tooltip->buffer;
- dispInfo->szText[0] = L'\0';
- dispInfo->hinst = NULL;
- dispInfo->uFlags = TTF_DI_SETITEM;
- }
- BOOL
- ListWidget_TooltipProcessNotification(ListWidget *self, ListWidgetTooltip *tooltip, NMHDR *pnmh, LRESULT *result)
- {
- if (NULL == tooltip ||
- NULL == pnmh ||
- pnmh->hwndFrom != tooltip->window)
- {
- return FALSE;
- }
- switch(pnmh->code)
- {
- case TTN_GETDISPINFO:
- ListWidget_TooltipGetDispInfo(self, tooltip, (NMTTDISPINFO*)pnmh);
- break;
- case TTN_SHOW:
- if (0 == (WS_VISIBLE & GetWindowStyle(tooltip->window)))
- tooltip->showTime = GetTickCount();
- if (FALSE != tooltip->active)
- {
- SendMessage(tooltip->window, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(TOOLTIP_DELAY_RESHOW, 0));
- }
- break;
- }
- return TRUE;
- }
- ListWidgetItem *
- ListWidget_TooltipGetCurrent(ListWidgetTooltip *tooltip, ListWidgetItemPart *part, RECT *partRect)
- {
- if (NULL == tooltip ||
- FALSE == tooltip->active ||
- NULL == tooltip->item)
- {
- return NULL;
- }
-
- if (NULL != part)
- *part = tooltip->part;
- if (NULL != partRect)
- CopyRect(partRect, &tooltip->partRect);
- return tooltip->item;
- }
- BOOL
- ListWidget_TooltipGetChanged(ListWidgetTooltip *tooltip, ListWidgetItem *item,
- ListWidgetItemPart part, const RECT *partRect)
- {
- if (NULL == tooltip)
- return FALSE;
- if (tooltip->item != item)
- return TRUE;
- if (NULL == item)
- return FALSE;
- if (tooltip->part != part)
- return TRUE;
- if (FALSE == EqualRect(&tooltip->partRect, partRect))
- return TRUE;
- return FALSE;
- }
- BOOL
- ListWidget_TooltipUpdateText(ListWidget *self, ListWidgetTooltip *tooltip, ListWidgetItem *item, TooltipUpdateReason reason)
- {
- TOOLINFO ti;
- ListWidgetItemPart mask;
- unsigned int windowStyle;
- unsigned long showTimeout, currentTime;
- if (NULL == self ||
- NULL == tooltip ||
- NULL == tooltip->active ||
- NULL == tooltip->window)
- {
- return FALSE;
- }
- if (NULL != item && tooltip->item != item)
- return FALSE;
- windowStyle = GetWindowStyle(tooltip->window);
- if (0 == (WS_VISIBLE & windowStyle))
- return FALSE;
- showTimeout = (unsigned long)SendMessage(tooltip->window, TTM_GETDELAYTIME, (WPARAM)TTDT_AUTOPOP, 0L);
- currentTime = GetTickCount();
- if (currentTime < tooltip->showTime)
- return FALSE;
-
- currentTime -= tooltip->showTime;
- if (showTimeout > (currentTime + 10))
- showTimeout -= currentTime;
- else
- return FALSE;
-
- KillTimer(tooltip->window, 4);
- switch(reason)
- {
- case Tooltip_DeviceTitleChanged:
- case Tooltip_DeviceModelChanged:
- case Tooltip_DeviceStatusChanged:
- mask = ListWidgetItemPart_Frame |
- ListWidgetItemPart_Activity |
- ListWidgetItemPart_Title;
- if (0 == (mask & tooltip->part))
- return FALSE;
- break;
- case Tooltip_DeviceSpaceChanged:
- mask = ListWidgetItemPart_Frame |
- ListWidgetItemPart_Activity |
- ListWidgetItemPart_Spacebar;
- if (0 == (mask & tooltip->part))
- return FALSE;
- break;
- /*case Tooltip_DeviceActivityChanged:
- mask = ListWidgetItemPart_Frame |
- ListWidgetItemPart_Activity;
- if (0 == (mask & tooltip->part))
- return FALSE;
- break;*/
- }
- ZeroMemory(&ti, sizeof(ti));
- ti.cbSize = sizeof(ti);
- ti.hwnd = tooltip->owner;
- ti.uId = 0;
- ti.lpszText = LPSTR_TEXTCALLBACK;
- tooltip->blockLocationChange = TRUE;
- SendMessage(tooltip->window, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
- tooltip->blockLocationChange = FALSE;
- SetTimer(tooltip->window, 4, showTimeout, 0);
- return TRUE;
- }
- static LRESULT WINAPI
- ListWidgetTooltip_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- ListWidgetTooltip *tooltip;
-
- tooltip = (ListWidgetTooltip*)GetProp(hwnd, MAKEINTATOM(LISTWIDGETTOOLTIP_PROP));
- if (NULL == tooltip ||
- NULL == tooltip->originalProc)
- {
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
- switch(uMsg)
- {
- case WM_DESTROY:
- RemoveProp(hwnd, MAKEINTATOM(LISTWIDGETTOOLTIP_PROP));
- SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)tooltip->originalProc);
- CallWindowProc(tooltip->originalProc, hwnd, uMsg, wParam, lParam);
- tooltip->originalProc = NULL;
- tooltip->window = NULL;
- break;
- case WM_WINDOWPOSCHANGING:
- if (FALSE != tooltip->blockLocationChange)
- {
- WINDOWPOS *pwp;
- pwp = (WINDOWPOS*)lParam;
- if (NULL != pwp)
- {
- pwp->flags |= SWP_NOMOVE;
- }
- }
- break;
- }
-
- return CallWindowProc(tooltip->originalProc, hwnd, uMsg, wParam, lParam);
- }
|