Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
10 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: Link.h
  6. //
  7. // Owner: a-josem
  8. //
  9. // Description:
  10. //
  11. // Static control subclassing Class used to display links.
  12. //
  13. //
  14. //=======================================================================
  15. #pragma once
  16. #include <stdlib.h>
  17. #include <malloc.h>
  18. #include "windowsx.h"
  19. #include "tchar.h"
  20. #include "htmlhelp.h"
  21. #include <shellapi.h>
  22. #include <safefunc.h>
  23. #include "mistsafe.h"
  24. const TCHAR strObjPtr[] = TEXT("strSysLinkObjPtr");
  25. const struct
  26. {
  27. enum { cxWidth = 32, cyHeight = 32 };
  28. int xHotSpot;
  29. int yHotSpot;
  30. unsigned char arrANDPlane[cxWidth * cyHeight / 8];
  31. unsigned char arrXORPlane[cxWidth * cyHeight / 8];
  32. } _Link_CursorData =
  33. {
  34. 5, 0,
  35. {
  36. 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF,
  37. 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF,
  38. 0xF0, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x7F, 0xFF,
  39. 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF,
  40. 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF,
  41. 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  42. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  43. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  44. },
  45. {
  46. 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
  47. 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xD8, 0x00, 0x00,
  48. 0x06, 0xDA, 0x00, 0x00, 0x06, 0xDB, 0x00, 0x00, 0x67, 0xFB, 0x00, 0x00, 0x77, 0xFF, 0x00, 0x00,
  49. 0x37, 0xFF, 0x00, 0x00, 0x17, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00,
  50. 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00,
  51. 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  54. }
  55. };
  56. class CSysLink
  57. {
  58. public:
  59. CSysLink(BOOL fIsHtmlHelp= TRUE):/*bInit(FALSE),*/m_OrigWndProc(NULL),m_lpstrLabel(NULL), m_lpstrHyperLink(NULL),m_hWnd(NULL),
  60. m_hCursor(NULL), m_hFont(NULL), /* m_bPaintLabel(true),*/ m_clrLink(RGB(0, 0, 255)), m_PaintedFocusRect(false), m_IsHtmlHelp(fIsHtmlHelp)
  61. {
  62. SetRectEmpty(&m_rcLink);
  63. }
  64. ~CSysLink()
  65. {
  66. #if 0
  67. free(m_lpstrLabel);
  68. free(m_lpstrHyperLink);
  69. if(m_hFont != NULL)
  70. ::DeleteObject(m_hFont);
  71. if(m_hCursor != NULL)
  72. ::DestroyCursor(m_hCursor);
  73. #endif
  74. }
  75. void Uninit()
  76. {
  77. SafeFreeNULL(m_lpstrLabel);
  78. SafeFreeNULL(m_lpstrHyperLink);
  79. if(m_hFont != NULL)
  80. {
  81. ::DeleteObject(m_hFont);
  82. m_hFont = NULL;
  83. }
  84. if(m_hCursor != NULL)
  85. {
  86. ::DestroyCursor(m_hCursor);
  87. m_hCursor = NULL;
  88. }
  89. }
  90. void Init()
  91. {
  92. LONG ctrlstyle = GetWindowLong(m_hWnd,GWL_STYLE);
  93. ctrlstyle |= SS_NOTIFY;
  94. SetWindowLongPtr(m_hWnd,GWL_STYLE,ctrlstyle);
  95. HWND wnd = GetParent(m_hWnd);
  96. HFONT hFont = (HFONT)SendMessage(wnd,WM_GETFONT,0,0);
  97. /* if(m_bPaintLabel) */
  98. {
  99. if(hFont != NULL)
  100. {
  101. LOGFONT lf;
  102. GetObject(hFont, sizeof(LOGFONT), &lf);
  103. lf.lfUnderline = TRUE;
  104. m_hFont = CreateFontIndirect(&lf);
  105. }
  106. }
  107. // set label (defaults to window text)
  108. if(m_lpstrLabel == NULL)
  109. {
  110. int nLen = GetWindowTextLength(m_hWnd);
  111. if(nLen > 0)
  112. {
  113. LPTSTR lpszText = (LPTSTR)malloc((nLen+1)*sizeof(TCHAR));
  114. if(NULL != lpszText && GetWindowText(m_hWnd,lpszText, nLen+1))
  115. SetLabel(lpszText);
  116. SafeFree(lpszText);
  117. }
  118. }
  119. // set hyperlink (defaults to label)
  120. if(m_lpstrHyperLink == NULL && m_lpstrLabel != NULL)
  121. SetHyperLink(m_lpstrLabel);
  122. CalcLabelRect();
  123. }
  124. void SubClassWindow(HWND hWnd)
  125. {
  126. if (SetProp(hWnd, strObjPtr, (HANDLE)this))
  127. {
  128. // bInit = TRUE;
  129. m_hWnd = hWnd;
  130. m_OrigWndProc = (WNDPROC) SetWindowLongPtr(hWnd,GWLP_WNDPROC,(LONG_PTR)CSysLink::_SysLinkWndProc);
  131. }
  132. Init();
  133. }
  134. static INT_PTR CALLBACK _SysLinkWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  135. {
  136. CSysLink *pThis = (CSysLink *)GetProp(hwnd, strObjPtr);
  137. // if (NULL != pThis)
  138. // {
  139. switch(uMsg)
  140. {
  141. HANDLE_MSG(hwnd, WM_ERASEBKGND, pThis->_OnEraseBkgnd);
  142. HANDLE_MSG(hwnd, WM_PAINT, pThis->_OnPaint);
  143. HANDLE_MSG(hwnd, WM_SETFOCUS, pThis->_OnFocus);
  144. HANDLE_MSG(hwnd, WM_KILLFOCUS, pThis->_OnFocus);
  145. HANDLE_MSG(hwnd, WM_MOUSEMOVE, pThis->_OnMouseMove);
  146. HANDLE_MSG(hwnd, WM_LBUTTONDOWN, pThis->_OnLButtonDown);
  147. HANDLE_MSG(hwnd, WM_LBUTTONUP, pThis->_OnLButtonUp);
  148. HANDLE_MSG(hwnd, WM_CHAR, pThis->_OnChar);
  149. HANDLE_MSG(hwnd, WM_GETDLGCODE, pThis->_OnGetDlgCode);
  150. HANDLE_MSG(hwnd, WM_SETCURSOR, pThis->_OnSetCursor);
  151. }
  152. // }
  153. return CallWindowProc(pThis->m_OrigWndProc, hwnd,uMsg,wParam,lParam);
  154. }
  155. BOOL Invalidate(BOOL bErase = TRUE)
  156. {
  157. return InvalidateRect(m_hWnd, NULL, bErase);
  158. }
  159. BOOL Navigate()
  160. {
  161. if (m_IsHtmlHelp == TRUE)
  162. HtmlHelp(NULL,m_lpstrHyperLink,HH_DISPLAY_TOPIC,NULL);
  163. else
  164. {
  165. ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL);
  166. }
  167. return TRUE;
  168. }
  169. void SetSysLinkInstanceHandle(HINSTANCE hInstance)
  170. {
  171. m_hInstance = hInstance;
  172. m_hCursor = ::CreateCursor(hInstance, _Link_CursorData.xHotSpot, _Link_CursorData.yHotSpot, _Link_CursorData.cxWidth, _Link_CursorData.cyHeight, _Link_CursorData.arrANDPlane, _Link_CursorData.arrXORPlane);
  173. }
  174. public: //Message Handlers
  175. BOOL _OnSetCursor(HWND hwnd, HWND hwndCursor, UINT codeHitTest, UINT msg)
  176. {
  177. POINT pt;
  178. GetCursorPos(&pt);
  179. ScreenToClient(m_hWnd,&pt);
  180. if(m_lpstrHyperLink != NULL && ::PtInRect(&m_rcLink, pt))
  181. {
  182. return TRUE;
  183. }
  184. return (BOOL)CallWindowProc(m_OrigWndProc, hwnd,WM_SETCURSOR,(WPARAM)hwndCursor,MAKELPARAM(codeHitTest,msg));
  185. }
  186. UINT _OnGetDlgCode(HWND hwnd, LPMSG lpmsg)
  187. {
  188. return DLGC_WANTCHARS;
  189. }
  190. void _OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
  191. {
  192. POINT pt = { x, y};
  193. if(m_lpstrHyperLink != NULL && PtInRect(&m_rcLink, pt))
  194. SetCursor(m_hCursor);
  195. }
  196. void _OnFocus(HWND hwnd, HWND hwndOldFocus)
  197. {
  198. Invalidate();
  199. }
  200. void _OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  201. {
  202. POINT pt = { x, y };
  203. if(PtInRect(&m_rcLink, pt))
  204. {
  205. SetFocus(m_hWnd);
  206. SetCapture(m_hWnd);
  207. }
  208. }
  209. void _OnPaint(HWND hwnd)
  210. {
  211. PAINTSTRUCT ps;
  212. HDC hDC = BeginPaint(hwnd, &ps);
  213. m_hWnd = hwnd;
  214. DoPaint(hDC);
  215. EndPaint(hwnd, &ps);
  216. }
  217. void _OnChar(HWND hwnd, TCHAR ch, int cRepeat)
  218. {
  219. if(ch == VK_RETURN || ch == VK_SPACE)
  220. Navigate();
  221. }
  222. BOOL _OnEraseBkgnd(HWND hwnd, HDC hdc)
  223. {
  224. /* if(m_bPaintLabel)*/
  225. {
  226. HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)m_hWnd);
  227. if(hBrush != NULL)
  228. {
  229. RECT rect;
  230. GetClientRect(m_hWnd, &rect);
  231. FillRect(hdc, &rect, hBrush);
  232. }
  233. }
  234. return 1;
  235. }
  236. void _OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags)
  237. {
  238. if(GetCapture() == m_hWnd)
  239. {
  240. ReleaseCapture();
  241. POINT pt = { x, y };
  242. if(PtInRect(&m_rcLink, pt))
  243. Navigate();
  244. }
  245. }
  246. void DoPaint(HDC hDC)
  247. {
  248. if (m_PaintedFocusRect)
  249. {
  250. m_PaintedFocusRect = false;
  251. DrawFocusRect(hDC, &m_rcLink);
  252. }
  253. SetBkMode(hDC, TRANSPARENT);
  254. SetTextColor(hDC, m_clrLink);
  255. if(m_hFont != NULL)
  256. SelectFont(hDC, m_hFont);
  257. LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
  258. LONG_PTR dwStyle = GetWindowLongPtr(m_hWnd,GWL_STYLE);
  259. int nDrawStyle = DT_LEFT;
  260. if (dwStyle & SS_CENTER)
  261. nDrawStyle = DT_CENTER;
  262. else if (dwStyle & SS_RIGHT)
  263. nDrawStyle = DT_RIGHT;
  264. DrawText(hDC, lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK);
  265. if((GetFocus() == m_hWnd)&&(!m_PaintedFocusRect))
  266. {
  267. m_PaintedFocusRect = true;
  268. DrawFocusRect(hDC, &m_rcLink);
  269. }
  270. }
  271. bool CalcLabelRect()
  272. {
  273. if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
  274. return false;
  275. HDC hDC = GetDC(m_hWnd);
  276. RECT rect;
  277. GetClientRect(m_hWnd, &rect);
  278. m_rcLink = rect;
  279. HFONT hOldFont = NULL;
  280. if(m_hFont != NULL)
  281. hOldFont = SelectFont(hDC, m_hFont);
  282. LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
  283. DWORD dwStyle = (DWORD)GetWindowLongPtr(m_hWnd,GWL_STYLE);
  284. int nDrawStyle = DT_LEFT;
  285. if (dwStyle & SS_CENTER)
  286. nDrawStyle = DT_CENTER;
  287. else if (dwStyle & SS_RIGHT)
  288. nDrawStyle = DT_RIGHT;
  289. DrawText(hDC, lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK | DT_CALCRECT);
  290. if(m_hFont != NULL)
  291. SelectFont(hDC, hOldFont);
  292. return true;
  293. }
  294. bool SetLabel(LPCTSTR lpstrLabel)
  295. {
  296. free(m_lpstrLabel);
  297. m_lpstrLabel = NULL;
  298. int ilen = lstrlen(lpstrLabel) + 1;
  299. m_lpstrLabel = (LPTSTR)malloc(ilen * sizeof(TCHAR));
  300. if(m_lpstrLabel == NULL)
  301. return false;
  302. //lstrcpy(m_lpstrLabel, lpstrLabel);
  303. if (FAILED(StringCchCopyEx(m_lpstrLabel, ilen, lpstrLabel, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  304. {
  305. free(m_lpstrLabel);
  306. m_lpstrLabel = NULL;
  307. return false;
  308. }
  309. CalcLabelRect();
  310. return true;
  311. }
  312. #if 0
  313. bool GetLabel(LPTSTR lpstrBuffer, int nLength)
  314. {
  315. if (NULL != m_lpstrLabel &&
  316. nLength > lstrlen(m_lpstrLabel) &&
  317. SUCCEEDED(StringCchCopyEx(lpstrBuffer, nLength, m_lpstrLabel, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  318. {
  319. return true;
  320. }
  321. return false;
  322. }
  323. #endif
  324. bool SetHyperLink(LPCTSTR lpstrLink)
  325. {
  326. free(m_lpstrHyperLink);
  327. m_lpstrHyperLink = NULL;
  328. int ilen = lstrlen(lpstrLink) + 1;
  329. m_lpstrHyperLink = (LPTSTR)malloc(ilen * sizeof(TCHAR));
  330. if(m_lpstrHyperLink == NULL)
  331. return false;
  332. if (FAILED(StringCchCopyEx(m_lpstrHyperLink, ilen, lpstrLink, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  333. {
  334. free(m_lpstrHyperLink);
  335. m_lpstrHyperLink = NULL;
  336. return false;
  337. }
  338. if(m_lpstrLabel == NULL)
  339. CalcLabelRect();
  340. return true;
  341. }
  342. #if 0
  343. bool GetHyperLink(LPTSTR lpstrBuffer, int nLength)
  344. {
  345. if (NULL != m_lpstrHyperLink &&
  346. nLength > lstrlen(m_lpstrHyperLink) &&
  347. SUCCEEDED(StringCchCopyEx(lpstrBuffer, nLength, m_lpstrHyperLink, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  348. {
  349. return true;
  350. }
  351. return false;
  352. }
  353. #endif
  354. private:
  355. // BOOL bInit;
  356. BOOL m_IsHtmlHelp;
  357. HWND m_hWnd;
  358. WNDPROC m_OrigWndProc;
  359. LPTSTR m_lpstrLabel;
  360. LPTSTR m_lpstrHyperLink;
  361. HCURSOR m_hCursor;
  362. // bool m_bPaintLabel;
  363. HFONT m_hFont;
  364. RECT m_rcLink;
  365. bool m_PaintedFocusRect;
  366. COLORREF m_clrLink; //set once
  367. HINSTANCE m_hInstance;
  368. };