PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/CSysLinkControl.ahk

http://github.com/Uberi/CGUI
AutoHotKey | 211 lines | 130 code | 1 blank | 80 comment | 5 complexity | d1157ab34636ef89aff016be615d1d51 MD5 | raw file
  1. ; ======================================================================================================================
  2. ; AHK 1.1.04 +
  3. ; ======================================================================================================================
  4. ; Function: Support for SysLink controls - http://msdn.microsoft.com/en-us/library/bb760704%28VS.85%29.aspx
  5. ; They may be useful in some cases, but they offer very few options for customizing.
  6. ; AHK version: 1.1.04.00 (U32)
  7. ; Language: English
  8. ; Tested on: Win XPSP3, Win VistaSP2 (32 Bit)
  9. ; Version: 0.0.02.012/2011-09-16/just me
  10. ; How to use: To create a new Syslink control use MySysLink := New SysLink_Control()
  11. ; passing up to four parameters:
  12. ; Name - Name of the control
  13. ; Text - Text to show in the control (String)
  14. ; ----------- Optional ---------------------------------------------------------
  15. ; Options - Options for positioning and sizing (X, Y, W, H) (String)
  16. ; as used in "Gui, Add" command.
  17. ; Defaults: X - automatically positioned by GUI
  18. ; Y - automatically positioned by GUI
  19. ; W - 200
  20. ; H - 0 (the height will be adjusted to fit the text)
  21. ; The options "BackgroundTrans" and "Border" are supported also.
  22. ; Function - Function to be called on WM_NOTIFY messages (String)
  23. ; Default: "_SysLink_Notifications"
  24. ; On success - New returns an object with six public keys:
  25. ; HWND - HWND of the control (Pointer)
  26. ; X - X-position (Integer)
  27. ; Y - Y-position (Integer)
  28. ; W - Width of the control (Integer)
  29. ; H - Height of the control (Integer)
  30. ; ID - Id of the control (>= 0x4000) (Integer)
  31. ; On failure - New returns False, ErrorLevel contains additional informations.
  32. ;
  33. ; To destroy the control afterwards simply assign an empty string or zero (e.g. MySysLink := "").
  34. ;
  35. ; Remarks: MSDN: "The SysLink control supports the anchor tag(<a>) along with the attributes HREF and ID.
  36. ; An HREF can be any protocol, such as http, ftp, and mailto. An ID is an optional name,
  37. ; unique within a SysLink control, and it is associated with an individual link.
  38. ; Links are also assigned a zero-based index according to their position within the string."
  39. ;
  40. ; The scripts provides the function _SysLink_Notifications() as default handler for
  41. ; NM_CLICK and NM_RETURN notifications (the only notifications associated with the control).
  42. ; This function only will run clicked URLs. If you want to do another action or to respond also
  43. ; to clicks on IDs, you have to pass the name of a function accepting exactly four parameters
  44. ; (Hwnd, Msg, wParam, lParam) to be called instead.
  45. ;
  46. ; This class is using Class_Notification.ahk from http://www.autohotkey.com/forum/topic75591.html
  47. ; because I think it makes things easier. If you want to handle other notifications in your script,
  48. ; you should use it too.
  49. ; ======================================================================================================================
  50. ; This software is provided 'as-is', without any express or implied warranty.
  51. ; In no event will the authors be held liable for any damages arising from the use of this software.
  52. ; ======================================================================================================================
  53. /*
  54. Class: CSysLinkControl
  55. A class for displaying hyperlinks in text.
  56. Property: Text
  57. Simply use <A HREF="URL">URL Text</A> notation inside the text to show a link. This control supports multiple links and regular text as well.
  58. Event: Click(URL)
  59. Called when a link is clicked. If this is not handled the control will try to open the URL.
  60. */
  61. Class CSysLinkControl extends CControl {
  62. ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  63. ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  64. ; PRIVATE Properties and Methods ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  65. ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  66. ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  67. ; ===================================================================================================================
  68. ; CONSTRUCTOR __New()
  69. ; ===================================================================================================================
  70. __New(Name, Options, Text, GUINum)
  71. {
  72. Static INIT := False
  73. Static HDEFFONT := 0
  74. Static DEFAULT_GUI_FONT := 17
  75. Static ICC_LINK_CLASS := 0x00008000
  76. Static IDC_SYSLINK := 0x4000
  77. Static WC_LINK := "SysLink"
  78. Static LWS_TRANSPARENT := 0x0001
  79. Static WM_USER := 0x400
  80. Static LM_GETIDEALHEIGHT := (WM_USER + 0x301)
  81. Static WM_SETFONT := 0x0030
  82. Static WM_GETFONT := 0x0031
  83. Static NM_FIRST := 0
  84. Static NM_CLICK := (NM_FIRST-2)
  85. Static NM_RETURN := (NM_FIRST-4)
  86. Static WS_TABSTOP := 0x00010000
  87. Static WS_BORDER := 0x00800000
  88. Static WS_VISIBLE := 0x10000000
  89. Static WS_CHILD := 0x40000000
  90. Static DefaultW := 200
  91. Static DefaultH := 0
  92. base.__New(Name, Options, Text, GUINum)
  93. this.Type := "SysLink"
  94. HGUI := CGUI.GUIList[GUINum].hwnd
  95. If !(INIT) {
  96. VarSetCapacity(ICCX, 8, 0)
  97. NumPut(8, ICCX, 0, "UInt")
  98. NumPut(ICC_LINK_CLASS, ICCX, 4, "UInt")
  99. If !DllCall("Comctl32.dll\InitCommonControlsEx", "Ptr", &ICCX)
  100. Return False
  101. HDEFFONT := DllCall("Gdi32.dll\GetStockObject", "Int", DEFAULT_GUI_FONT)
  102. INIT := True
  103. }
  104. If !DllCall("User32.dll\IsWindow", "UPtr", HGUI) {
  105. ErrorLevel := "Invalid parameter HGUI: " . HGUI
  106. Return False
  107. }
  108. W := DefaultW
  109. H := DefaultH
  110. Opts := {X: "", Y: "", W: "", H: ""}
  111. Options := Trim(RegExReplace(Options, "\s+", " "))
  112. SL_STYLES := WS_TABSTOP | WS_VISIBLE | WS_CHILD
  113. Loop, Parse, Options, %A_Space%
  114. {
  115. If (A_LoopField = "BackgroundTrans") {
  116. SL_STYLES |= LWS_TRANSPARENT
  117. Continue
  118. }
  119. If (A_LoopField = "Border") {
  120. SL_STYLES |= WS_BORDER
  121. Continue
  122. }
  123. O := SubStr(A_LoopField, 1, 1)
  124. If InStr("XYWH", O)
  125. Opts[O] := A_LoopField
  126. }
  127. If (Opts.W <> "")
  128. W := Opts.W
  129. If (Opts.H <> "")
  130. H := Opts.H
  131. Options := Opts.X . " " . Opts.Y . " " . Opts.W . " " . Opts.H
  132. Gui, %HGUI%:Add, Text, %Options% hwndHDUMMY, X
  133. GuiControlGet, CP, Pos, %HDUMMY%
  134. HFONT := DllCall("SendMessage", "Ptr", HDUMMY, "Int", WM_GETFONT, "Ptr", 0, "Ptr", 0, "UPtr")
  135. If !(HFONT)
  136. HFONT := HDEFFONT
  137. X := CPX
  138. Y := CPY
  139. If (W = Opts.W)
  140. W := CPW
  141. If (H = Opts.H)
  142. H := CPH
  143. HSL := DllCall("CreateWindowExW", "UInt", 0, "WStr", WC_LINK, "WStr", Text, "UInt", SL_STYLES
  144. , "Int", X, "Int", Y, "Int", W, "Int", H
  145. , "Ptr", HGUI, "Ptr", IDC_SYSLINK, "Ptr", 0, "Ptr", 0, "Ptr")
  146. If ((ErrorLevel) || !(HSL)) {
  147. ErrorMsg := "Couldn't create SysLink control!`nErrorLevel: " . ErrorLevel . " - HWND: " . HSL
  148. ErrorLevel := ErrorMsg
  149. Return False
  150. }
  151. DllCall("SendMessage", "Ptr", HSL, "Int", WM_SETFONT, "Ptr", HFONT, "Ptr", False)
  152. If (H = DefaultH) {
  153. H := DllCall("SendMessage", "Ptr", HSL, "Int", LM_GETIDEALHEIGHT, "Ptr", W, "Ptr", 0)
  154. DllCall("MoveWindow", "Ptr", HSL, "Int", X, "Int", Y, "Int", W, "Int", H, "Int", False)
  155. If (H <> CPH)
  156. Gui, %HGUI%:Add, Text, x%X% y%Y% w%W% h%H% +BackgroundTrans
  157. }
  158. This.HWND := HSL
  159. ;~ This.X := X
  160. ;~ This.Y := Y
  161. ;~ This.W := W
  162. ;~ This.H := H
  163. This.ID := IDC_SYSLINK
  164. IDC_SYSLINK += 1
  165. return HSL
  166. }
  167. ; ===================================================================================================================
  168. ; DESTRUCTOR __Delete()
  169. ; ===================================================================================================================
  170. __Delete() {
  171. Global Notification
  172. Static NM_FIRST := 0
  173. Static NM_CLICK := (NM_FIRST-2)
  174. Static NM_RETURN := (NM_FIRST-4)
  175. If (This.HWND) {
  176. DllCall("DestroyWindow", "Ptr", This.HWND)
  177. }
  178. }
  179. OnWM_NOTIFY(wParam, lParam) {
  180. ; lParam is a pointer to a NMLINK structure containing NMHDR and LITEM structures
  181. ; -> http://msdn.microsoft.com/en-us/library/bb760714%28VS.85%29.aspx
  182. Static NM_FIRST := 0
  183. Static NM_CLICK := (NM_FIRST-2)
  184. Static NM_RETURN := (NM_FIRST-4)
  185. Static MAX_LINKID_TEXT := 48
  186. Static L_MAX_URL_LENGTH := (2048 + 32 + 3) ; 3 : sizeof("://"))
  187. Static OffHwnd := 0
  188. Static OffIDFrom := OffHwnd + A_PtrSize
  189. Static OffCode := OffIDFrom + A_PtrSize
  190. Static OffLITEM := OffCode + 4
  191. Static OffMask := OffLITEM
  192. Static OffItem := OffMask + 4
  193. Static OffState := OffItem + 4
  194. Static OffStmask := OffState + 4
  195. Static OffID := OffStmask + 4
  196. Static OffUrl := OffID + (MAX_LINKID_TEXT * 2)
  197. Code := NumGet(lParam + 0, OffCode, "INT")
  198. if(Code = NM_CLICK || Code = NM_RETURN)
  199. {
  200. Url := StrGet(lParam + OffUrl, L_MAX_URL_LENGTH, "UTF-16")
  201. Url := Trim(Url)
  202. if(!this.CallEvent("Click", Url).Handled)
  203. if(Url)
  204. Run, *Open %Url%
  205. }
  206. }
  207. }