/lib/CChoiceControl.ahk

http://github.com/Skiouros/Macro · AutoHotKey · 433 lines · 278 code · 1 blank · 154 comment · 74 complexity · 1b2ba9e153d7cd0413bb29992a06f6b0 MD5 · raw file

  1. /*
  2. Class: CChoiceControl
  3. This class implements DropDownList, ComboBox and ListBox controls.
  4. This control extends <CControl>. All basic properties and functions are implemented and documented in this class.
  5. */
  6. Class CChoiceControl Extends CControl ;This class is a ComboBox, ListBox and DropDownList
  7. {
  8. __New(Name, Options, Text, GUINum, Type)
  9. {
  10. Base.__New(Name, Options, Text, GUINum)
  11. this.Type := Type
  12. if(Type = "Combobox")
  13. this._.Insert("ControlStyles", {LowerCase : 0x400, Uppercase : 0x2000, Sort : 0x100, Simple : 0x1})
  14. else if(Type = "DropDownList")
  15. this._.Insert("ControlStyles", {LowerCase : 0x400, Uppercase : 0x2000, Sort : 0x100})
  16. else if(Type = "ListBox")
  17. this._.Insert("ControlStyles", {Multi : 0x800, ReadOnly : 0x4000, Sort : 0x2, ToggleSelection : 0x8})
  18. this._.Insert("Events", ["SelectionChanged"])
  19. if(Type = "ListBox")
  20. this._.Insert("Messages", {5 : "KillFocus", 4 : "SetFocus" }) ;Used for automatically registering message callbacks
  21. else if(Type = "ComboBox" || Type = "DropDownList")
  22. this._.Insert("Messages", {4 : "KillFocus", 3 : "SetFocus" }) ;Used for automatically registering message callbacks
  23. }
  24. PostCreate()
  25. {
  26. Base.PostCreate()
  27. this._.Items := new this.CItems(this.GUINum, this.hwnd)
  28. Content := this.Content
  29. Loop, Parse, Content, |
  30. this._.Items.Insert(new this.CItems.CItem(A_Index, this.GUINum, this.hwnd))
  31. this._.PreviouslySelectedItem := this.SelectedItem
  32. }
  33. /*
  34. Variable: SelectedItem
  35. The text of the selected item.
  36. Variable: SelectedIndex
  37. The index of the selected item.
  38. Variable: Items
  39. An array containing all items. See <CChoiceControl.CItems>.
  40. */
  41. __Get(Name, Params*)
  42. {
  43. ;~ global CGUI
  44. if(Name != "GUINum" && !CGUI.GUIList[this.GUINum].IsDestroyed)
  45. {
  46. DetectHidden := A_DetectHiddenWindows
  47. DetectHiddenWindows, On
  48. if(Name = "SelectedItem")
  49. ControlGet, Value, Choice,,, % "ahk_id " . this.hwnd
  50. else if(Name = "Text")
  51. ControlGet, Value, Choice,,,% "ahk_id " this.hwnd
  52. else if(Name = "SelectedIndex")
  53. {
  54. SendMessage, 0x147, 0, 0,,% "ahk_id " this.hwnd
  55. Value := ErrorLevel + 1
  56. }
  57. else if(Name = "Items")
  58. Value := this._.Items
  59. else if(Name = "PreviouslySelectedItem")
  60. Value := this._.PreviouslySelectedItem
  61. ;~ else if(Name = "Items")
  62. ;~ {
  63. ;~ ControlGet, List, List,,, % " ahk_id " this.hwnd
  64. ;~ Value := Array()
  65. ;~ Loop, Parse, List, `n
  66. ;~ Value.Insert(A_LoopField)
  67. ;~ }
  68. Loop % Params.MaxIndex()
  69. if(IsObject(Value)) ;Fix unlucky multi parameter __GET
  70. Value := Value[Params[A_Index]]
  71. if(!DetectHidden)
  72. DetectHiddenWindows, Off
  73. if(Value != "")
  74. return Value
  75. }
  76. }
  77. __Set(Name, Params*)
  78. {
  79. ;~ global CGUI
  80. if(!CGUI.GUIList[this.GUINum].IsDestroyed)
  81. {
  82. Value := Params[Params.MaxIndex()]
  83. Params.Remove(Params.MaxIndex())
  84. DetectHidden := A_DetectHiddenWindows
  85. DetectHiddenWindows, On
  86. Handled := true
  87. if(Name = "SelectedItem")
  88. {
  89. Loop % this.Items.MaxIndex()
  90. if(this.Items[A_Index] = Value)
  91. {
  92. GuiControl, % this.GUINum ":Choose", % this.ClassNN, % A_Index
  93. this.ProcessSubControlState(this._.PreviouslySelectedItem, this.SelectedItem)
  94. this._.PreviouslySelectedItem := this.SelectedItem
  95. }
  96. }
  97. else if(Name = "SelectedIndex" && Value >= 1 && Value <= this.Items.MaxIndex())
  98. {
  99. GuiControl, % this.GUINum ":Choose", % this.ClassNN, % Value
  100. this.ProcessSubControlState(this._.PreviouslySelectedItem, this.SelectedItem)
  101. this._.PreviouslySelectedItem := this.SelectedItem
  102. }
  103. ;~ else if(Name = "Items" && !Params[1])
  104. ;~ {
  105. ;~ if(!IsObject(Value))
  106. ;~ {
  107. ;~ if(InStr(Value, "|") = 1) ;Overwrite current items
  108. ;~ {
  109. ;~ ;Hide overwritten controls for now (until they can be removed properly).
  110. ;~ for index, item in this.Items
  111. ;~ for index2, control in item.Controls
  112. ;~ control.hide()
  113. ;~ this.Items := new this.CItems(this.GUINum, this.Name)
  114. ;~ }
  115. ;~ Loop, Parse, Value,|
  116. ;~ if(A_LoopField)
  117. ;~ this.Items.Insert(this.Items.MaxIndex() + 1, new this.CItems.CItem(this.Items.MaxIndex() + 1, this.GUINum, this.Name))
  118. ;~ }
  119. ;~ else
  120. ;~ {
  121. ;~ ;Hide overwritten controls for now (until they can be removed properly).
  122. ;~ for index, item in this.Items
  123. ;~ for index2, control in item.Controls
  124. ;~ control.hide()
  125. ;~ this.Items := new this.CItems(this.GUINum, this.Name)
  126. ;~ Loop % Value.MaxIndex()
  127. ;~ this.Items.Insert(A_Index, new this.CItems.CItem(A_Index, this.GUINum, this.Name))
  128. ;~ }
  129. ;~ ItemsString := ""
  130. ;~ Loop % this.Items.MaxIndex()
  131. ;~ ItemsString .= "|" Items[A_Index]
  132. ;~ GuiControl, % this.GUINum ":", % this.ClassNN, %ItemsString%
  133. ;~ if(!IsObject(Value) && InStr(Value, "||"))
  134. ;~ {
  135. ;~ if(RegExMatch(Value, "(?:^|\|)(..*?)\|\|", SelectedItem))
  136. ;~ Control, ChooseString, %SelectedItem1%,,% "ahk_id " this.hwnd
  137. ;~ }
  138. ;~ for index, item in Items
  139. ;~ this.Items._.Insert(new this.CItems.CItem(A_Index, this.GUINum, this.Name))
  140. ;~ }
  141. ;~ else if(Name = "Items" && Params[1] > 0)
  142. ;~ {
  143. ;~ this._.Items[Params[1]] := Value
  144. ;~ msgbox should not be here
  145. ;~ Items := this.Items
  146. ;~ Items[Params[1]] := Value
  147. ;~ ItemsString := ""
  148. ;~ Loop % Items.MaxIndex()
  149. ;~ ItemsString .= "|" Items[A_Index]
  150. ;~ SelectedIndex := this.SelectedIndex
  151. ;~ GuiControl, % this.GUINum ":", % this.ClassNN, %ItemsString%
  152. ;~ GuiControl, % this.GUINum ":Choose", % this.ClassNN, %SelectedIndex%
  153. ;~ }
  154. else if(Name = "Text")
  155. {
  156. found := false
  157. Loop % this.Items.MaxIndex()
  158. if(this.Items[A_Index].Text = Value)
  159. {
  160. GuiControl, % this.GUINum ":Choose", % this.ClassNN, % A_Index
  161. this.ProcessSubControlState(this._.PreviouslySelectedItem, this.SelectedItem)
  162. this._.PreviouslySelectedItem := this.SelectedItem
  163. found := true
  164. }
  165. if(!found && this.type = "ComboBox")
  166. ControlSetText, , %Value%, % "ahk_id " this.hwnd
  167. ;~ {
  168. ;~ GuiControl, % this.GUINum ":ChooseString", % this.ClassNN, % Value
  169. ;~ this.ProcessSubControlState(this._.PreviouslySelectedItem, this.SelectedItem)
  170. ;~ this._.PreviouslySelectedItem := this.SelectedItem
  171. ;~ }
  172. }
  173. else
  174. Handled := false
  175. if(!DetectHidden)
  176. DetectHiddenWindows, Off
  177. if(Handled)
  178. return Value
  179. }
  180. }
  181. /*
  182. Event: Introduction
  183. To handle control events you need to create a function with this naming scheme in your window class: ControlName_EventName(params)
  184. The parameters depend on the event and there may not be params at all in some cases.
  185. Additionally it is required to create a label with this naming scheme: GUIName_ControlName
  186. GUIName is the name of the window class that extends CGUI. The label simply needs to call CGUI.HandleEvent().
  187. For better readability labels may be chained since they all execute the same code.
  188. Instead of using ControlName_EventName() you may also call <CControl.RegisterEvent> on a control instance to register a different event function name.
  189. Event: SelectionChanged(SelectedItem)
  190. Invoked when the selection was changed.
  191. */
  192. HandleEvent(Event)
  193. {
  194. this.ProcessSubControlState(this._.PreviouslySelectedItem, this.SelectedItem)
  195. this._.PreviouslySelectedItem := this.SelectedItem
  196. this.CallEvent("SelectionChanged", this.SelectedItem)
  197. }
  198. /*
  199. Class: CChoiceControl.CItems
  200. An array containing all items of the control.
  201. */
  202. Class CItems
  203. {
  204. __New(GUINum, hwnd)
  205. {
  206. this.Insert("_", {})
  207. this._.GUINum := GUINum
  208. this._.hwnd := hwnd
  209. }
  210. /*
  211. Variable: 1,2,3,4,...
  212. Individual items can be accessed by their index.
  213. Variable: Count
  214. The number of items in this control.
  215. */
  216. __Get(Name)
  217. {
  218. ;~ global CGUI
  219. if(this._.HasKey(Name))
  220. return this._[Name]
  221. else if(Name = "Count")
  222. return this.MaxIndex()
  223. }
  224. __Set(Name, Value)
  225. {
  226. ;~ global CGUI
  227. if Name is Integer
  228. return
  229. }
  230. /*
  231. Function: Add
  232. Adds an item to the list of choices.
  233. Parameters:
  234. Text - The text of the new item.
  235. Position - The position at which the item will be inserted. Items with indices >= this value will be appended.
  236. */
  237. Add(Text, Position = -1)
  238. {
  239. ;~ global CGUI
  240. GUI := CGUI.GUIList[this._.GUINum]
  241. Control := GUI.Controls[this._.hwnd]
  242. Selected := Control.SelectedIndex
  243. ItemsString := ""
  244. Pos := 1
  245. Loop % this.MaxIndex()
  246. {
  247. ItemsString .= "|" (Position = A_Index ? Text : this[pos].Text)
  248. if(Position = A_Index)
  249. pos--
  250. pos++
  251. }
  252. if(Position = -1)
  253. ItemsString .= "|" Text
  254. GuiControl, % this._.GUINum ":", % Control.ClassNN, %ItemsString%
  255. this._.Insert(Position = -1 ? this.MaxIndex() + 1 : Position, new this.CItems.CItem(Position, this._.GUINum, this.Name)) ;Insert new item object
  256. for index, item in this ;Move existing indices
  257. item._.Index := index
  258. GuiControl, % this._.GUINum ":Choose", % Control.ClassNN, % (Position != -1 && Selected < Position ? Selected : Selected + 1)
  259. }
  260. /*
  261. Function: Remove
  262. Removes an item to the list of choices.
  263. Parameters:
  264. IndexTextOrItem - The item which should be removed. This can either be an index, the text of the item or the item object stored in the Items array.
  265. */
  266. Remove(IndexTextOrItem)
  267. {
  268. ;~ global CGUI
  269. GUI := CGUI.GUIList[this._.GUINum]
  270. Control := GUI.Controls[this.hwnd]
  271. if(IsObject(IndexTextOrItem))
  272. {
  273. Loop % this.MaxIndex()
  274. if(this[A_Index] = IndexTextOrItem)
  275. IndexTextOrItem := A_Index
  276. }
  277. else if IndexTextOrItem is not Integer
  278. {
  279. Loop % this.MaxIndex()
  280. if(this[A_Index].Text = IndexTextOrItem)
  281. IndexTextOrItem := A_Index
  282. }
  283. if IndexTextOrItem is Number
  284. {
  285. if(IndexTextOrItem > 0 && IndexTextOrItem <= this.MaxIndex())
  286. {
  287. Selected := Control.SelectedIndex
  288. this._.Remove(IndexTextOrItem)
  289. ItemsString := ""
  290. Loop % this.MaxIndex()
  291. if(A_Index != IndexTextOrItem)
  292. ItemsString .= "|" this[A_Index]
  293. GuiControl, % this.GUINum ":Choose", % Control.ClassNN, % (Selected <= IndexTextOrItem ? Selected : Selected - 1)
  294. for index, item in this
  295. item._.Index := index
  296. }
  297. }
  298. }
  299. /*
  300. Function: MaxIndex
  301. Returns the number of items in this control.
  302. */
  303. MaxIndex()
  304. {
  305. ;~ global CGUI
  306. DetectHidden := A_DetectHiddenWindows
  307. DetectHiddenWindows, On
  308. GUI := CGUI.GUIList[this._.GUINum]
  309. ControlGet, List, List,,, % " ahk_id " this._.hwnd
  310. count := 0
  311. Loop, Parse, List, `n
  312. count++
  313. if(!DetectHidden)
  314. DetectHiddenWindows, Off
  315. return count
  316. }
  317. _NewEnum()
  318. {
  319. ;~ global CEnumerator
  320. return new CEnumerator(this)
  321. }
  322. /*
  323. Class: CChoiceControl.CItems.CItem
  324. A single item of this control.
  325. */
  326. Class CItem
  327. {
  328. __New(Index, GUINum, hwnd)
  329. {
  330. this.Insert("_", {})
  331. this._.Insert("GUINum", GUINum)
  332. this._.Insert("hwnd", hwnd)
  333. this._.Insert("Index", Index)
  334. this._.Insert("Controls", {})
  335. }
  336. /*
  337. Function: AddControl
  338. Adds a control to this item that will be visible only when this item is selected. The parameters correspond to the Add() function of CGUI.
  339. Parameters:
  340. Type - The type of the control.
  341. Name - The name of the control.
  342. Options - Options used for creating the control.
  343. Text - The text of the control.
  344. UseEnabledState - If true, the control will be enabled/disabled instead of visible/hidden.
  345. */
  346. AddControl(type, Name, Options, Text, UseEnabledState = 0)
  347. {
  348. ;~ global CGUI
  349. GUI := CGUI.GUIList[this._.GUINum]
  350. if(!this.Selected)
  351. Options .= UseEnabledState ? " Disabled" : " Hidden"
  352. Control := GUI.AddControl(type, Name, Options, Text, this._.Controls)
  353. Control._.UseEnabledState := UseEnabledState
  354. Control.hParentControl := this._.hwnd
  355. return Control
  356. }
  357. /*
  358. Variable: Selected
  359. If true, the item is selected.
  360. Variable: Text
  361. The text of the list item.
  362. */
  363. __Get(Name, Params*)
  364. {
  365. ;~ global CGUI
  366. DetectHidden := A_DetectHiddenWindows
  367. DetectHiddenWindows, On
  368. if(Name = "Text")
  369. {
  370. GUI := CGUI.GUIList[this._.GUINum]
  371. Control := GUI.Controls[this._.hwnd]
  372. ControlGet, List, List,,, % " ahk_id " Control.hwnd
  373. Loop, Parse, List, `n
  374. if(A_Index = this._.Index)
  375. {
  376. Value := A_LoopField
  377. break
  378. }
  379. }
  380. else if(Name = "Selected")
  381. {
  382. GUI := CGUI.GUIList[this._.GUINum]
  383. Control := GUI.Controls[this._.hwnd]
  384. SendMessage, 0x147, 0, 0,,% "ahk_id " Control.hwnd
  385. Value := (this._.Index = ErrorLevel + 1)
  386. }
  387. else if(Name = "Controls")
  388. Value := this._.Controls
  389. Loop % Params.MaxIndex()
  390. if(IsObject(Value)) ;Fix unlucky multi parameter __GET
  391. Value := Value[Params[A_Index]]
  392. if(!DetectHidden)
  393. DetectHiddenWindows, Off
  394. return Value
  395. }
  396. __Set(Name, Value)
  397. {
  398. ;~ global CGUI
  399. if(Name = "Text")
  400. {
  401. GUI := CGUI.GUIList[this._.GUINum]
  402. Control := GUI.Controls[this._.hwnd]
  403. ItemsString := ""
  404. SelectedIndex := Control.SelectedIndex
  405. for index, item in Control.Items
  406. ItemsString .= "|" (index = this._.Index ? Value : item.text)
  407. GuiControl, % this._.GUINum ":", % Control.ClassNN, %ItemsString%
  408. GuiControl, % this._.GUINum ":Choose", % Control.ClassNN, %SelectedIndex%
  409. return Value
  410. }
  411. else if(Name = "Selected" && Value = 1)
  412. {
  413. GUI := CGUI.GUIList[this._.GUINum]
  414. Control := GUI.Controls[this._.hwnd]
  415. GuiControl, % this._.GUINum ":Choose", % Control.ClassNN, % this._.Index
  416. this.ProcessSubControlState(this._.PreviouslySelectedItem, this.SelectedItem)
  417. Control._.PreviouslySelectedItem := Control.SelectedItem
  418. return Value
  419. }
  420. }
  421. }
  422. }
  423. }