aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/commandLink.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/commandLink.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/commandLink.cpp')
-rw-r--r--Src/Winamp/commandLink.cpp698
1 files changed, 698 insertions, 0 deletions
diff --git a/Src/Winamp/commandLink.cpp b/Src/Winamp/commandLink.cpp
new file mode 100644
index 00000000..69f18189
--- /dev/null
+++ b/Src/Winamp/commandLink.cpp
@@ -0,0 +1,698 @@
+#include "main.h"
+#include "./commandLink.h"
+#include "./api.h"
+//#include "./guiObjects.h"
+
+#include <windows.h>
+#include <shlwapi.h>
+#include <commctrl.h>
+#include <strsafe.h>
+
+#ifndef LONGX86
+#ifdef _WIN64
+ #define LONGX86 LONG_PTR
+#else /*_WIN64*/
+ #define LONGX86 LONG
+#endif /*_WIN64*/
+#endif // LONGX86
+
+
+#define MARGIN_LEFT 2
+#define MARGIN_TOP 0
+#define MARGIN_RIGHT 2
+#define MARGIN_BOTTOM 1
+
+typedef struct __COMMANDLINK
+{
+ COLORREF rgbBk;
+ COLORREF rgbText;
+ COLORREF rgbTextVisited;
+ COLORREF rgbTextHighlight;
+ HCURSOR cursorHot;
+ HFONT textFont;
+ UINT state;
+ RECT margins;
+} COMMANDLINK;
+
+#define GetCommandLink(__hwnd) ((COMMANDLINK*)(LONG_PTR)(LONGX86)GetWindowLongPtrW((__hwnd), 0))
+
+static LRESULT CALLBACK CommandLink_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+
+EXTERN_C BOOL CommandLink_RegisterClass(HINSTANCE hInstance)
+{
+ WNDCLASSEXW wc;
+ ATOM klassAtom;
+
+ if (GetClassInfoExW(hInstance, NWC_COMMANDLINKW, &wc))
+ return TRUE;
+
+ ZeroMemory(&wc, sizeof(WNDCLASSEXW));
+
+ wc.cbSize = sizeof(WNDCLASSEXW);
+ wc.hInstance = hInstance;
+ wc.lpszClassName = NWC_COMMANDLINKW;
+ wc.lpfnWndProc = CommandLink_WindowProc;
+ wc.style = CS_GLOBALCLASS;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.cbWndExtra = sizeof(COMMANDLINK*);
+
+ klassAtom = RegisterClassExW(&wc);
+ if (0 == klassAtom)
+ return FALSE;
+
+ if (NULL != WASABI_API_APP)
+ WASABI_API_APP->DirectMouseWheel_RegisterSkipClass(klassAtom);
+
+ return TRUE;
+}
+
+
+static COLORREF CommandLink_BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha)
+{
+ if (alpha > 254) return rgbTop;
+ if (alpha < 0) return rgbBottom;
+
+ INT k = (((255 - alpha)*255 + 127)/255);
+
+ return RGB( (GetRValue(rgbTop)*alpha + k*GetRValue(rgbBottom) + 127)/255,
+ (GetGValue(rgbTop)*alpha + k*GetGValue(rgbBottom) + 127)/255,
+ (GetBValue(rgbTop)*alpha + k*GetBValue(rgbBottom) + 127)/255);
+}
+
+static HBRUSH CommandLink_GetPaintColors(HWND hwnd, HDC hdc, COLORREF *rgbBkOut, COLORREF *rgbFgOut)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return NULL;
+
+ COLORREF rgbBk, rgbFg;
+ UINT windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
+ BOOL defaultColors = (0 != (CLS_DEFAULTCOLORS & windowStyle));
+
+ rgbBk = (defaultColors) ? GetSysColor(COLOR_3DFACE) : link->rgbBk;
+ if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
+
+ if (0 != (WS_DISABLED & windowStyle))
+ rgbFg = GetSysColor(COLOR_GRAYTEXT);
+ else
+ {
+ if (0 != (CLIS_VISITED & link->state))
+ rgbFg = (defaultColors) ? RGB(85, 26, 139) : link->rgbTextVisited;
+ else
+ rgbFg = (defaultColors) ? GetSysColor(COLOR_HOTLIGHT) : link->rgbText;
+
+ if (0 != ((CLIS_HOT | CLIS_PRESSED) & link->state))
+ {
+ if (0 == (CLS_HIGHLIGHTCOLOR & windowStyle))
+ rgbFg = CommandLink_BlendColors(rgbFg, rgbBk, 160);
+ else
+ rgbFg = link->rgbTextHighlight;
+ }
+ }
+
+ if (NULL != rgbFgOut)
+ *rgbFgOut = rgbFg;
+
+
+ HBRUSH backBrush = NULL;
+ if (FALSE != defaultColors)
+ {
+ HWND hParent = GetParent(hwnd);
+ if (NULL != hParent)
+ {
+ COLORREF backBk = SetBkColor(hdc, rgbBk);
+ COLORREF backFg = SetBkColor(hdc, rgbFg);
+ backBrush = (HBRUSH)SendMessageW(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd);
+ rgbBk = SetBkColor(hdc, backBk);
+ SetBkColor(hdc, backFg);
+ }
+ }
+ return backBrush;
+}
+
+static BOOL CommandLink_GetTextRect(HDC hdc, LPCWSTR pszText, INT cchText, const RECT *prcClient, RECT *prcTextOut, const RECT *margins)
+{
+ if (NULL == prcClient || NULL == prcTextOut)
+ return FALSE;
+
+ SIZE textSize;
+ if (0 == cchText || !GetTextExtentPoint32W(hdc, pszText, cchText, &textSize))
+ return SetRectEmpty(prcTextOut);
+
+ prcTextOut->left = ((prcClient->right - prcClient->left) - textSize.cx) / 2;
+ if (prcTextOut->left < (prcClient->left + margins->left))
+ prcTextOut->left = prcClient->left + margins->left;
+
+ prcTextOut->top = ((prcClient->bottom - prcClient->top) - textSize.cy) / 2;
+ if (prcTextOut->top < (prcClient->top + margins->top))
+ prcTextOut->top = prcClient->top + margins->top;
+
+ prcTextOut->right = prcTextOut->left + textSize.cx;
+ if (prcTextOut->right > (prcClient->right - margins->right))
+ prcTextOut->right = prcClient->right - margins->right;
+
+ prcTextOut->bottom = prcTextOut->top + textSize.cy;
+ if (prcTextOut->bottom > (prcClient->bottom - margins->bottom))
+ prcTextOut->bottom = prcClient->bottom - margins->bottom;
+
+ return TRUE;
+}
+
+static BOOL CommandLink_GetIdealSizeReal(HWND hwnd, SIZE *sizeOut)
+{
+ if (NULL == sizeOut)
+ return FALSE;
+
+ ZeroMemory(sizeOut, sizeof(SIZE));
+
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return FALSE;
+
+ WCHAR szText[256] = {0};
+ INT cchText = GetWindowTextW(hwnd, szText, ARRAYSIZE(szText));
+
+ HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
+ if (NULL == hdc) return FALSE;
+
+ HFONT originalFont = (HFONT)SelectObject(hdc, link->textFont);
+ BOOL resultOk;
+
+ if (0 == cchText)
+ {
+ TEXTMETRICW tm;
+ resultOk = GetTextMetricsW(hdc, &tm);
+ if (resultOk) sizeOut->cy = tm.tmHeight;
+ }
+ else
+ resultOk = GetTextExtentPoint32W(hdc, szText, cchText, sizeOut);
+
+ if (originalFont != link->textFont) SelectObject(hdc, originalFont);
+ ReleaseDC(hwnd, hdc);
+
+ if (resultOk)
+ {
+ sizeOut->cx += (link->margins.left + link->margins.right);
+ sizeOut->cy += (link->margins.top + link->margins.bottom);
+ }
+ return resultOk;
+}
+
+static BOOL CommandLink_SetStateEx(HWND hwnd, UINT newState, UINT stateMask, BOOL fRedraw)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return FALSE;
+
+ UINT oldState = link->state;
+ link->state = (link->state & ~stateMask) | (newState & stateMask);
+
+ if (oldState != link->state && fRedraw)
+ InvalidateRect(hwnd, NULL, TRUE);
+
+ return TRUE;
+}
+
+static void CommandLink_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return;
+
+ RECT clientRect, partRect;
+ if (!GetClientRect(hwnd, &clientRect)) return;
+
+ DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
+
+ COLORREF rgbBk, rgbFg;
+ HBRUSH backBrush = CommandLink_GetPaintColors(hwnd, hdc, &rgbBk, &rgbFg);
+
+ COLORREF originalBk = SetBkColor(hdc, rgbBk);
+ COLORREF originalFg = SetTextColor(hdc, rgbFg);
+
+ HFONT originalFont = (HFONT)SelectObject(hdc, link->textFont);
+
+ WCHAR szText[256] = {0};
+ INT cchText = GetWindowTextW(hwnd, szText, ARRAYSIZE(szText));
+
+ RECT textRect;
+ CommandLink_GetTextRect(hdc, szText, cchText, &clientRect, &textRect, &link->margins);
+
+ if (fErase)
+ {
+ if(NULL != backBrush)
+ {
+ FillRect(hdc, prcPaint, backBrush);
+ }
+ else
+ {
+ ExtTextOut(hdc, 0, 0, ETO_OPAQUE, prcPaint, NULL, 0, NULL);
+ }
+ }
+
+ if (0 != ((CLIS_HOT | CLIS_PRESSED) & link->state) ||
+ 0 != (CLS_ALWAYSUNDERLINE & windowStyle))
+ {
+ TEXTMETRIC tm;
+ if (GetTextMetrics(hdc, &tm))
+ {
+ CopyRect(&partRect, &textRect);
+ partRect.top = partRect.top + tm.tmAscent + 1;
+ partRect.bottom = partRect.top + 1;
+
+ COLORREF originalColor = SetBkColor(hdc, rgbFg);
+ ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &partRect, NULL, 0, NULL);
+ if (originalColor != rgbFg) SetBkColor(hdc, originalColor);
+ }
+ }
+
+ if (0 != cchText)
+ {
+ INT originalMode = SetBkMode(hdc, TRANSPARENT);
+ UINT originalAlign = SetTextAlign(hdc, TA_LEFT | TA_TOP);
+ ExtTextOutW(hdc, textRect.left, textRect.top, ETO_CLIPPED, &textRect, szText, cchText, NULL);
+ if (TRANSPARENT != originalMode) SetBkMode(hdc, originalMode);
+ if ((TA_LEFT | TA_TOP) != originalAlign) SetTextAlign(hdc, originalAlign);
+ }
+
+ if (CLIS_FOCUSED == ((CLIS_FOCUSED | CLIS_HIDEFOCUS) & link->state))
+ {
+ SetBkColor(hdc, 0x00FFFFFF);
+ SetTextColor(hdc, 0x000000000);
+ DrawFocusRect(hdc, &clientRect);
+ }
+
+ SelectObject(hdc, originalFont);
+ if (originalBk != rgbBk) SetBkColor(hdc, originalBk);
+ if (originalFg != rgbFg) SetTextColor(hdc, originalFg);
+
+}
+
+static void CommandLink_NotifyParent(HWND hwnd, UINT notificationId)
+{
+ NMHDR nmhdr;
+ nmhdr.code = notificationId;
+ nmhdr.hwndFrom = hwnd;
+ nmhdr.idFrom = GetDlgCtrlID(hwnd);
+
+ HWND hParent = GetParent(hwnd);
+ if (NULL != hParent)
+ {
+ SendMessageW(hParent, WM_NOTIFY, (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+ }
+}
+
+static void CommandLink_Click(HWND hwnd)
+{
+ CommandLink_NotifyParent(hwnd, NM_CLICK);
+
+ DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
+ if (0 != (CLS_TRACKVISITED & windowStyle))
+ CommandLink_SetStateEx(hwnd, CLIS_VISITED, CLIS_VISITED, TRUE);
+
+}
+
+static void CommandLink_QueryUiState(HWND hwnd)
+{
+ UINT uiState = (UINT)DefWindowProcW(hwnd, WM_QUERYUISTATE, 0, 0L);
+ CommandLink_SetStateEx(hwnd, (0 != (UISF_HIDEFOCUS & uiState)) ? CLIS_HIDEFOCUS : 0, CLIS_HIDEFOCUS, TRUE);
+}
+static LRESULT CommandLink_OnCreateWindow(HWND hwnd, CREATESTRUCT *pcs)
+{
+ UNREFERENCED_PARAMETER(pcs);
+
+ COMMANDLINK *link;
+
+ link = (COMMANDLINK*)calloc(1, sizeof(COMMANDLINK));
+ if (NULL == link)
+ {
+ DestroyWindow(hwnd);
+ return -1;
+ }
+
+ SetLastError(ERROR_SUCCESS);
+ if (!SetWindowLongPtrW(hwnd, 0, (LONGX86)(LONG_PTR)link) && ERROR_SUCCESS != GetLastError())
+ {
+ free(link);
+ DestroyWindow(hwnd);
+ return -1;
+ }
+
+ link->rgbBk = GetSysColor(COLOR_3DFACE);
+ link->rgbText = GetSysColor(COLOR_HOTLIGHT);
+ link->rgbTextVisited = (0x00FFFFFF & (~link->rgbText));
+ link->rgbTextHighlight = GetSysColor(COLOR_HOTLIGHT);
+ link->cursorHot = LoadCursor(NULL, IDC_HAND);
+ SetRect(&link->margins, MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM);
+
+ CommandLink_QueryUiState(hwnd);
+ return FALSE;
+}
+
+static void CommandLink_OnDestroy(HWND hwnd)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ SetWindowLongPtrW(hwnd, 0, 0L);
+ if (!link) return;
+
+ free(link);
+}
+
+static void CommandLink_OnPaint(HWND hwnd)
+{
+ PAINTSTRUCT ps;
+ if (BeginPaint(hwnd, &ps))
+ {
+ if (ps.rcPaint.left != ps.rcPaint.right)
+ CommandLink_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
+ EndPaint(hwnd, &ps);
+ }
+}
+
+static void CommandLink_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
+{
+ RECT clientRect;
+ if (GetClientRect(hwnd, &clientRect))
+ CommandLink_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options));
+}
+
+static void CommandLink_OnSetFocus(HWND hwnd, HWND lostFocus)
+{
+ UNREFERENCED_PARAMETER(lostFocus);
+ CommandLink_SetStateEx(hwnd, CLIS_FOCUSED, CLIS_FOCUSED, TRUE);
+ CommandLink_NotifyParent(hwnd, NM_SETFOCUS);
+}
+
+static void CommandLink_OnKillFocus(HWND hwnd, HWND receiveFocus)
+{
+ UNREFERENCED_PARAMETER(receiveFocus);
+ CommandLink_SetStateEx(hwnd, 0, CLIS_FOCUSED, TRUE);
+ CommandLink_NotifyParent(hwnd, NM_KILLFOCUS);
+}
+
+static void CommandLink_OnMouseMove(HWND hwnd, UINT mouseFlags, POINTS pts)
+{
+ UNREFERENCED_PARAMETER(mouseFlags);
+ UNREFERENCED_PARAMETER(pts);
+
+ UINT windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
+
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL != link)
+ {
+ if (0 == (CLIS_HOT & link->state) && 0 != (CLS_HOTTRACK & windowStyle))
+ {
+ link->state |= CLIS_HOT;
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ TRACKMOUSEEVENT tm;
+ tm.cbSize = sizeof(TRACKMOUSEEVENT);
+ tm.dwFlags = TME_LEAVE;
+ tm.hwndTrack = hwnd;
+ TrackMouseEvent(&tm);
+ }
+ }
+}
+
+static void CommandLink_OnMouseLeave(HWND hwnd)
+{
+ CommandLink_SetStateEx(hwnd, 0, CLIS_HOT, TRUE);
+}
+
+static void CommandLink_OnLButtonDown(HWND hwnd, UINT mouseFlags, POINTS pts)
+{
+ UNREFERENCED_PARAMETER(mouseFlags);
+ UNREFERENCED_PARAMETER(pts);
+
+ if (IsWindowEnabled(hwnd) && hwnd != GetFocus())
+ SetFocus(hwnd);
+
+ CommandLink_SetStateEx(hwnd, CLIS_PRESSED, CLIS_PRESSED, TRUE);
+ if (hwnd != GetCapture())
+ SetCapture(hwnd);
+
+}
+
+static void CommandLink_OnLButtonUp(HWND hwnd, UINT mouseFlags, POINTS pts)
+{
+ UNREFERENCED_PARAMETER(mouseFlags);
+
+ RECT clientRect;
+ POINT pt;
+ POINTSTOPOINT(pt, pts);
+
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL != link && 0 != (CLIS_PRESSED & link->state))
+ {
+ if (GetClientRect(hwnd, &clientRect) && PtInRect(&clientRect, pt))
+ CommandLink_Click(hwnd);
+ CommandLink_SetStateEx(hwnd, 0, CLIS_PRESSED, TRUE);
+ }
+
+ if (hwnd == GetCapture())
+ SetCapture(NULL);
+}
+
+static void CommandLink_OnKeyDown(HWND hwnd, UINT virtualKey, UINT keyFlags)
+{
+ UNREFERENCED_PARAMETER(hwnd);
+ UNREFERENCED_PARAMETER(virtualKey);
+ UNREFERENCED_PARAMETER(keyFlags);
+
+}
+
+static void CommandLink_OnKeyUp(HWND hwnd, UINT virtualKey, UINT keyFlags)
+{
+ UNREFERENCED_PARAMETER(keyFlags);
+
+ switch(virtualKey)
+ {
+ case VK_SPACE:
+ CommandLink_Click(hwnd);
+ break;
+ }
+
+}
+
+static void CommandLink_OnEnable(HWND hwnd, BOOL fEnabled)
+{
+ UNREFERENCED_PARAMETER(fEnabled);
+ InvalidateRect(hwnd, NULL, TRUE);
+}
+
+
+static void CommandLink_OnUpdateUiState(HWND hwnd, UINT actionId, UINT stateId)
+{
+ DefWindowProcW(hwnd, WM_UPDATEUISTATE, MAKEWPARAM(actionId, stateId), 0L);
+ CommandLink_QueryUiState(hwnd);
+}
+
+static void CommandLink_OnSetFont(HWND hwnd, HFONT newFont, BOOL fRedraw)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL != link) link->textFont = newFont;
+
+ if (FALSE != fRedraw)
+ InvalidateRect(hwnd, NULL, TRUE);
+}
+
+static LRESULT CommandLink_OnGetFont(HWND hwnd)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ return (LRESULT)((NULL != link) ? link->textFont : NULL);
+}
+
+static LRESULT CommandLink_OnSetCursor(HWND hwnd, HWND cursorWindow, UINT hitTest, UINT uMsg)
+{
+ UNREFERENCED_PARAMETER(cursorWindow);
+ UNREFERENCED_PARAMETER(hitTest);
+ UNREFERENCED_PARAMETER(uMsg);
+
+ if (IsWindowEnabled(hwnd))
+ {
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL != link && NULL != link->cursorHot)
+ {
+ SetCursor(link->cursorHot);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static LRESULT CommandLink_OnGetIdealHeight(HWND hwnd)
+{
+ SIZE windowSize;
+ return (CommandLink_GetIdealSizeReal(hwnd, &windowSize)) ? windowSize.cy : 0;
+}
+
+static LRESULT CommandLink_OnGetIdealSize(HWND hwnd, SIZE *sizeOut)
+{
+ return CommandLink_GetIdealSizeReal(hwnd, sizeOut);
+}
+
+static void CommandLink_OnResetVisited(HWND hwnd)
+{
+ CommandLink_SetStateEx(hwnd, 0, CLIS_VISITED, TRUE);
+}
+
+
+static BOOL CommandLink_OnGetMargins(HWND hwnd, RECT *prc)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == prc || NULL == link) return FALSE;
+ return CopyRect(prc, &link->margins);
+}
+
+static BOOL CommandLink_OnSetMargins(HWND hwnd, const RECT *prc)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == prc || NULL == link) return FALSE;
+ return CopyRect(&link->margins, prc);
+}
+
+static BOOL CommandLink_OnSetBackColor(HWND hwnd, COLORREF rgb)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return FALSE;
+
+ link->rgbBk = rgb;
+ return TRUE;
+}
+
+static BOOL CommandLink_OnGetBackColor(HWND hwnd)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ return (NULL != link) ? link->rgbBk : RGB(255, 0, 255);
+}
+
+static BOOL CommandLink_OnSetTextColor(HWND hwnd, COLORREF rgb)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return FALSE;
+
+ link->rgbText = rgb;
+ return TRUE;
+}
+
+static BOOL CommandLink_OnGetTextColor(HWND hwnd)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ return (NULL != link) ? link->rgbText : RGB(255, 0, 255);
+}
+
+static BOOL CommandLink_OnSetVisitedColor(HWND hwnd, COLORREF rgb)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return FALSE;
+
+ link->rgbTextVisited = rgb;
+ return TRUE;
+}
+
+static BOOL CommandLink_OnGetVisitedColor(HWND hwnd)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ return (NULL != link) ? link->rgbTextVisited : RGB(255, 0, 255);
+}
+
+static BOOL CommandLink_OnSetHighlightColor(HWND hwnd, COLORREF rgb)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ if (NULL == link) return FALSE;
+
+ link->rgbTextHighlight = rgb;
+ return TRUE;
+}
+
+static BOOL CommandLink_OnGetHighlightColor(HWND hwnd)
+{
+ COMMANDLINK *link = GetCommandLink(hwnd);
+ return (NULL != link) ? link->rgbTextHighlight : RGB(255, 0, 255);
+}
+
+static LRESULT CALLBACK CommandLink_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ switch ( uMsg )
+ {
+ case WM_CREATE:
+ return CommandLink_OnCreateWindow( hwnd, (CREATESTRUCT *) lParam );
+ case WM_DESTROY:
+ CommandLink_OnDestroy( hwnd );
+ return 0;
+ case WM_PAINT:
+ CommandLink_OnPaint( hwnd );
+ return 0;
+ case WM_PRINTCLIENT:
+ CommandLink_OnPrintClient( hwnd, (HDC) wParam, (UINT) lParam );
+ return 0;
+ case WM_ERASEBKGND:
+ return 0;
+ case WM_SETFONT:
+ CommandLink_OnSetFont( hwnd, (HFONT) wParam, (BOOL) LOWORD( lParam ) );
+ return 0;
+ case WM_GETFONT:
+ return CommandLink_OnGetFont( hwnd );
+ case WM_SETFOCUS:
+ CommandLink_OnSetFocus( hwnd, (HWND) wParam );
+ return 0;
+ case WM_KILLFOCUS:
+ CommandLink_OnKillFocus( hwnd, (HWND) wParam );
+ return 0;
+ case WM_MOUSEMOVE:
+ CommandLink_OnMouseMove( hwnd, (UINT) wParam, MAKEPOINTS( lParam ) );
+ return 0;
+ case WM_MOUSELEAVE:
+ CommandLink_OnMouseLeave( hwnd );
+ return 0;
+ case WM_LBUTTONDOWN:
+ CommandLink_OnLButtonDown( hwnd, (UINT) wParam, MAKEPOINTS( lParam ) );
+ return 0;
+ case WM_LBUTTONUP:
+ CommandLink_OnLButtonUp( hwnd, (UINT) wParam, MAKEPOINTS( lParam ) );
+ return 0;
+ case WM_KEYDOWN:
+ CommandLink_OnKeyDown( hwnd, (UINT) wParam, (UINT) lParam );
+ return 0;
+ case WM_KEYUP:
+ CommandLink_OnKeyUp( hwnd, (UINT) wParam, (UINT) lParam );
+ return 0;
+ case WM_ENABLE:
+ CommandLink_OnEnable( hwnd, (BOOL) wParam );
+ return 0;
+ case WM_UPDATEUISTATE:
+ CommandLink_OnUpdateUiState( hwnd, LOWORD( wParam ), HIWORD( wParam ) );
+ return 0;
+ case WM_SETCURSOR:
+ return CommandLink_OnSetCursor( hwnd, (HWND) wParam, LOWORD( lParam ), HIWORD( lParam ) );
+
+ case CLM_GETIDEALHEIGHT:
+ return CommandLink_OnGetIdealHeight( hwnd );
+ case CLM_GETIDEALSIZE:
+ return CommandLink_OnGetIdealSize( hwnd, (SIZE *) lParam );
+ case CLM_RESETVISITED:
+ CommandLink_OnResetVisited( hwnd );
+ return 0;
+ case CLM_GETMARGINS:
+ return CommandLink_OnGetMargins( hwnd, (RECT *) lParam );
+ case CLM_SETMARGINS:
+ return CommandLink_OnSetMargins( hwnd, (const RECT *) lParam );
+ case CLM_SETBACKCOLOR:
+ return CommandLink_OnSetBackColor( hwnd, (COLORREF) lParam );
+ case CLM_GETBACKCOLOR:
+ return CommandLink_OnGetBackColor( hwnd );
+ case CLM_SETTEXTCOLOR:
+ return CommandLink_OnSetTextColor( hwnd, (COLORREF) lParam );
+ case CLM_GETTEXTCOLOR:
+ return CommandLink_OnGetTextColor( hwnd );
+ case CLM_SETVISITEDCOLOR:
+ return CommandLink_OnSetVisitedColor( hwnd, (COLORREF) lParam );
+ case CLM_GETVISITEDCOLOR:
+ return CommandLink_OnGetVisitedColor( hwnd );
+ case CLM_SETHIGHLIGHTCOLOR:
+ return CommandLink_OnSetHighlightColor( hwnd, (COLORREF) lParam );
+ case CLM_GETHIGHLIGHTCOLOR:
+ return CommandLink_OnGetHighlightColor( hwnd );
+ }
+
+ return DefWindowProcW( hwnd, uMsg, wParam, lParam );
+}