📄 syslink.c
字号:
/***********************************************************************
* SYSLINK_SetFocus
* Handles receiving the input focus.
*/
static LRESULT SYSLINK_SetFocus (SYSLINK_INFO *infoPtr, HWND PrevFocusWindow)
{
PDOC_ITEM Focus;
infoPtr->HasFocus = TRUE;
/* We always select the first link, even if we activated the control using
SHIFT+TAB. This is the default behavior */
Focus = SYSLINK_GetNextLink(infoPtr, NULL);
if(Focus != NULL)
{
SYSLINK_SetFocusLink(infoPtr, Focus);
}
SYSLINK_RepaintLink(infoPtr, Focus);
return 0;
}
/***********************************************************************
* SYSLINK_KillFocus
* Handles losing the input focus.
*/
static LRESULT SYSLINK_KillFocus (SYSLINK_INFO *infoPtr, HWND NewFocusWindow)
{
PDOC_ITEM Focus;
infoPtr->HasFocus = FALSE;
Focus = SYSLINK_GetFocusLink(infoPtr, NULL);
if(Focus != NULL)
{
SYSLINK_RepaintLink(infoPtr, Focus);
}
return 0;
}
/***********************************************************************
* SYSLINK_LinkAtPt
* Returns a link at the specified position
*/
static PDOC_ITEM SYSLINK_LinkAtPt (SYSLINK_INFO *infoPtr, POINT *pt, int *LinkId, BOOL MustBeEnabled)
{
PDOC_ITEM Current;
int id = 0;
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
if((Current->Type == slLink) && SYSLINK_PtInDocItem(Current, *pt) &&
(!MustBeEnabled || (MustBeEnabled && (Current->u.Link.state & LIS_ENABLED))))
{
if(LinkId != NULL)
{
*LinkId = id;
}
return Current;
}
id++;
}
return NULL;
}
/***********************************************************************
* SYSLINK_LButtonDown
* Handles mouse clicks
*/
static LRESULT SYSLINK_LButtonDown (SYSLINK_INFO *infoPtr, DWORD Buttons, POINT *pt)
{
PDOC_ITEM Current, Old;
int id;
Current = SYSLINK_LinkAtPt(infoPtr, pt, &id, TRUE);
if(Current != NULL)
{
SetFocus(infoPtr->Self);
Old = SYSLINK_SetFocusLink(infoPtr, Current);
if(Old != NULL && Old != Current)
{
SYSLINK_RepaintLink(infoPtr, Old);
}
infoPtr->MouseDownID = id;
SYSLINK_RepaintLink(infoPtr, Current);
}
return 0;
}
/***********************************************************************
* SYSLINK_LButtonUp
* Handles mouse clicks
*/
static LRESULT SYSLINK_LButtonUp (SYSLINK_INFO *infoPtr, DWORD Buttons, POINT *pt)
{
if(infoPtr->MouseDownID > -1)
{
PDOC_ITEM Current;
int id;
Current = SYSLINK_LinkAtPt(infoPtr, pt, &id, TRUE);
if((Current != NULL) && (Current->u.Link.state & LIS_FOCUSED) && (infoPtr->MouseDownID == id))
{
SYSLINK_SendParentNotify(infoPtr, NM_CLICK, Current, id);
}
}
infoPtr->MouseDownID = -1;
return 0;
}
/***********************************************************************
* SYSLINK_OnEnter
* Handles ENTER key events
*/
static BOOL SYSLINK_OnEnter (SYSLINK_INFO *infoPtr)
{
if(infoPtr->HasFocus)
{
PDOC_ITEM Focus;
int id;
Focus = SYSLINK_GetFocusLink(infoPtr, &id);
if(Focus != NULL)
{
SYSLINK_SendParentNotify(infoPtr, NM_RETURN, Focus, id);
return TRUE;
}
}
return FALSE;
}
/***********************************************************************
* SYSKEY_SelectNextPrevLink
* Changes the currently focused link
*/
static BOOL SYSKEY_SelectNextPrevLink (SYSLINK_INFO *infoPtr, BOOL Prev)
{
if(infoPtr->HasFocus)
{
PDOC_ITEM Focus;
int id;
Focus = SYSLINK_GetFocusLink(infoPtr, &id);
if(Focus != NULL)
{
PDOC_ITEM NewFocus, OldFocus;
if(Prev)
NewFocus = SYSLINK_GetPrevLink(infoPtr, Focus);
else
NewFocus = SYSLINK_GetNextLink(infoPtr, Focus);
if(NewFocus != NULL)
{
OldFocus = SYSLINK_SetFocusLink(infoPtr, NewFocus);
if(OldFocus != NewFocus)
{
SYSLINK_RepaintLink(infoPtr, OldFocus);
}
SYSLINK_RepaintLink(infoPtr, NewFocus);
return TRUE;
}
}
}
return FALSE;
}
/***********************************************************************
* SYSKEY_SelectNextPrevLink
* Determines if there's a next or previous link to decide whether the control
* should capture the tab key message
*/
static BOOL SYSLINK_NoNextLink (SYSLINK_INFO *infoPtr, BOOL Prev)
{
PDOC_ITEM Focus, NewFocus;
Focus = SYSLINK_GetFocusLink(infoPtr, NULL);
if(Prev)
NewFocus = SYSLINK_GetPrevLink(infoPtr, Focus);
else
NewFocus = SYSLINK_GetNextLink(infoPtr, Focus);
return NewFocus == NULL;
}
/***********************************************************************
* SysLinkWindowProc
*/
static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
SYSLINK_INFO *infoPtr;
TRACE("hwnd=%p msg=%04x wparam=%x lParam=%lx\n", hwnd, message, wParam, lParam);
infoPtr = (SYSLINK_INFO *)GetWindowLongPtrW(hwnd, 0);
if (!infoPtr && message != WM_CREATE)
goto HandleDefaultMessage;
switch(message) {
case WM_PRINTCLIENT:
case WM_PAINT:
return SYSLINK_Paint (infoPtr, (HDC)wParam);
case WM_SETCURSOR:
{
LHITTESTINFO ht;
DWORD mp = GetMessagePos();
ht.pt.x = (short)LOWORD(mp);
ht.pt.y = (short)HIWORD(mp);
ScreenToClient(infoPtr->Self, &ht.pt);
if(SYSLINK_HitTest (infoPtr, &ht))
{
SetCursor(LoadCursorW(0, (LPCWSTR)IDC_HAND));
return TRUE;
}
/* let the default window proc handle this message */
goto HandleDefaultMessage;
}
case WM_SIZE:
{
HDC hdc = GetDC(infoPtr->Self);
if(hdc != NULL)
{
SYSLINK_Render(infoPtr, hdc);
ReleaseDC(infoPtr->Self, hdc);
}
return 0;
}
case WM_GETFONT:
return (LRESULT)infoPtr->Font;
case WM_SETFONT:
return (LRESULT)SYSLINK_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
case WM_SETTEXT:
SYSLINK_SetText(infoPtr, (LPWSTR)lParam);
goto HandleDefaultMessage;
case WM_LBUTTONDOWN:
{
POINT pt;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
return SYSLINK_LButtonDown(infoPtr, wParam, &pt);
}
case WM_LBUTTONUP:
{
POINT pt;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
return SYSLINK_LButtonUp(infoPtr, wParam, &pt);
}
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_RETURN:
SYSLINK_OnEnter(infoPtr);
return 0;
case VK_TAB:
{
BOOL shift = GetKeyState(VK_SHIFT) & 0x8000;
SYSKEY_SelectNextPrevLink(infoPtr, shift);
return 0;
}
}
goto HandleDefaultMessage;
}
case WM_GETDLGCODE:
{
LRESULT Ret = DLGC_HASSETSEL;
int vk = (lParam != 0 ? (int)((LPMSG)lParam)->wParam : 0);
switch(vk)
{
case VK_RETURN:
Ret |= DLGC_WANTMESSAGE;
break;
case VK_TAB:
{
BOOL shift = GetKeyState(VK_SHIFT) & 0x8000;
if(!SYSLINK_NoNextLink(infoPtr, shift))
{
Ret |= DLGC_WANTTAB;
}
else
{
Ret |= DLGC_WANTCHARS;
}
break;
}
}
return Ret;
}
case WM_NCHITTEST:
{
POINT pt;
RECT rc;
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
GetClientRect(infoPtr->Self, &rc);
ScreenToClient(infoPtr->Self, &pt);
if(pt.x < 0 || pt.y < 0 || pt.x > rc.right || pt.y > rc.bottom)
{
return HTNOWHERE;
}
if(SYSLINK_LinkAtPt(infoPtr, &pt, NULL, FALSE))
{
return HTCLIENT;
}
return HTTRANSPARENT;
}
case LM_HITTEST:
return SYSLINK_HitTest(infoPtr, (PLHITTESTINFO)lParam);
case LM_SETITEM:
return SYSLINK_SetItem(infoPtr, (PLITEM)lParam);
case LM_GETITEM:
return SYSLINK_GetItem(infoPtr, (PLITEM)lParam);
case LM_GETIDEALHEIGHT:
return SYSLINK_GetIdealHeight(infoPtr);
case WM_SETFOCUS:
return SYSLINK_SetFocus(infoPtr, (HWND)wParam);
case WM_KILLFOCUS:
return SYSLINK_KillFocus(infoPtr, (HWND)wParam);
case WM_ENABLE:
infoPtr->Style &= ~WS_DISABLED;
infoPtr->Style |= (wParam ? 0 : WS_DISABLED);
InvalidateRect (infoPtr->Self, NULL, FALSE);
return 0;
case WM_STYLECHANGED:
if (wParam == GWL_STYLE)
{
infoPtr->Style = ((LPSTYLESTRUCT)lParam)->styleNew;
InvalidateRect(infoPtr->Self, NULL, TRUE);
}
return 0;
case WM_CREATE:
/* allocate memory for info struct */
infoPtr = Alloc (sizeof(SYSLINK_INFO));
if (!infoPtr) return -1;
SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
/* initialize the info struct */
infoPtr->Self = hwnd;
infoPtr->Notify = ((LPCREATESTRUCTW)lParam)->hwndParent;
infoPtr->Style = ((LPCREATESTRUCTW)lParam)->style;
infoPtr->Font = 0;
infoPtr->LinkFont = 0;
infoPtr->Items = NULL;
infoPtr->HasFocus = FALSE;
infoPtr->MouseDownID = -1;
infoPtr->TextColor = GetSysColor(COLOR_WINDOWTEXT);
infoPtr->LinkColor = GetSysColor(COLOR_HIGHLIGHT);
infoPtr->VisitedColor = GetSysColor(COLOR_HIGHLIGHT);
infoPtr->BreakChar = ' ';
TRACE("SysLink Ctrl creation, hwnd=%p\n", hwnd);
SYSLINK_SetText(infoPtr, ((LPCREATESTRUCTW)lParam)->lpszName);
return 0;
case WM_DESTROY:
TRACE("SysLink Ctrl destruction, hwnd=%p\n", hwnd);
SYSLINK_ClearDoc(infoPtr);
if(infoPtr->Font != 0) DeleteObject(infoPtr->Font);
if(infoPtr->LinkFont != 0) DeleteObject(infoPtr->LinkFont);
SetWindowLongPtrW(hwnd, 0, 0);
Free (infoPtr);
return 0;
default:
HandleDefaultMessage:
if ((message >= WM_USER) && (message < WM_APP))
{
ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam );
}
return DefWindowProcW(hwnd, message, wParam, lParam);
}
}
/***********************************************************************
* SYSLINK_Register [Internal]
*
* Registers the SysLink window class.
*/
VOID SYSLINK_Register (void)
{
WNDCLASSW wndClass;
ZeroMemory (&wndClass, sizeof(wndClass));
wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
wndClass.lpfnWndProc = SysLinkWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof (SYSLINK_INFO *);
wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW);
wndClass.lpszClassName = WC_LINK;
RegisterClassW (&wndClass);
}
/***********************************************************************
* SYSLINK_Unregister [Internal]
*
* Unregisters the SysLink window class.
*/
VOID SYSLINK_Unregister (void)
{
UnregisterClassW (WC_LINK, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -