vruby 2004.08.07

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1326 @@
1
+ ###################################
2
+ #
3
+ # vrcontrol.rb
4
+ # Programmed by nyasu <nyasu@osk.3web.ne.jp>
5
+ # Copyright 1999-2001 Nishikawa,Yasuhiro
6
+ #
7
+ # More information at http://www.threeweb.ad.jp/~nyasu/software/vrproject.html
8
+ # (in Japanese)
9
+ #
10
+ ###################################
11
+
12
+ VR_DIR="vr/" unless defined?(::VR_DIR)
13
+ require VR_DIR+'vruby'
14
+ require VR_DIR+'sysmod'
15
+ =begin
16
+ = VisualuRuby(tmp) Standard Controls
17
+ This file prepares classes of standard controls, panels and menu modules.
18
+
19
+ <<< handlers.rd
20
+
21
+ === Control Container
22
+ * ((<VRStdControlContainer>))
23
+
24
+ === Standard Controls
25
+ * ((<VRButton>))
26
+ * ((<VRGroupbox>))
27
+ * ((<VRCheckbox>))
28
+ * ((<VRRadiobutton>))
29
+ * ((<VRStatic>))
30
+ * ((<VREdit>))
31
+ * ((<VRText>))
32
+ * ((<VRListbox>))
33
+ * ((<VRCombobox>))
34
+
35
+ === Menu
36
+ * ((<VRMenu>))
37
+ * ((<VRMenuItem>))
38
+ * ((<VRMenuUseable>))
39
+
40
+ === Panels
41
+ * ((<VRPanel>))
42
+ * ((<VRBitmapPanel>))
43
+ * ((<VRCanvasPanel>))
44
+ =end
45
+
46
+ ###########################################
47
+ # Messages and Styles
48
+ #
49
+
50
+ module WMsg
51
+ BN_CLICKED = 0
52
+ BN_DBLCLICKED = 5
53
+ BM_GETCHECK = 0xf0
54
+ BM_SETCHECK = 0xf1
55
+
56
+ STN_CLICKED = 0
57
+ STN_DBLCLICKED = 1
58
+
59
+ LB_ADDSTRING = 0x0180
60
+ LB_INSERTSTRING = 0x0181
61
+ LB_DELETESTRING = 0x0182
62
+ LB_SETSEL = 0x0185
63
+ LB_SETCURSEL = 0x0186
64
+ LB_GETSEL = 0x0187
65
+ LB_GETCURSEL = 0x188
66
+ LB_GETTEXT = 0x189
67
+ LB_GETTEXTLEN = 0x18a
68
+ LB_GETCOUNT = 0x18b
69
+ LB_SELECTSTRING = 0x18c
70
+ LB_DIR = 0x18d
71
+ LB_FINDSTRING = 0x18f
72
+ LB_GETSELCOUNT = 0x190
73
+ LB_GETSELITEMS = 0x191
74
+ LB_GETITEMDATA = 0x199
75
+ LB_SETITEMDATA = 0x19a
76
+ LBN_SELCHANGE=1
77
+ LBN_DBLCLK=2
78
+
79
+ CB_ADDSTRING = 0x143
80
+ CB_DELETESTRING = 0x144
81
+ CB_DIR = 0x145
82
+ CB_GETCOUNT = 0x146
83
+ CB_GETCURSEL = 0x147
84
+ CB_GETLBTEXT = 0x148
85
+ CB_GETLBTEXTLEN = 0x149
86
+ CB_INSERTSTRING = 0x14a
87
+ CB_FINDSTRING = 0x14c
88
+ CB_SELECTSTRING = 0x14d
89
+ CB_SETCURSEL = 0x14e
90
+ CB_GETITEMDATA = 0x150
91
+ CB_SETITEMDATA = 0x151
92
+ CB_SETEXTENDEDUI =0x155
93
+ CBN_SELCHANGE = 1
94
+ end
95
+
96
+ module WStyle
97
+ BS_PUSHBUTTON = 0
98
+ BS_CHECKBOX = 2
99
+ BS_AUTOCHECKBOX = 3
100
+ BS_RADIOBUTTON = 4
101
+ BS_3STATE = 5
102
+ BS_GROUPBOX = 7
103
+ BS_USERBUTTON = 8
104
+ BS_AUTORADIOBUTTON= 9
105
+
106
+ ES_MULTILINE = 4
107
+ ES_PASSWORD = 0x20
108
+ ES_AUTOVSCROLL = 0x40
109
+ ES_AUTOHSCROLL = 0x80
110
+ ES_READONLY = 0x800
111
+ ES_WANTRETURN = 0x1000
112
+ LBS_STANDARD = 0x00a00000 | 1
113
+ LBS_MULTIPLESEL = 8
114
+
115
+ CBS_STANDARD = 0x00a00200 | 3
116
+ CBS_AUTOSCROLL = 0x40
117
+ end
118
+
119
+ ###############################################
120
+ # Standard Control
121
+ #
122
+
123
+ class VRStdControl < VRControl
124
+ def _vr_cmdhandlers
125
+ unless defined?(@_vr_cmdhandlers)
126
+ @_vr_cmdhandlers={}
127
+ else
128
+ @_vr_cmdhandlers
129
+ end
130
+ end
131
+
132
+ def addCommandHandler(msg,handlername,handlertype,argparsestr)
133
+ @_vr_cmdhandlers={} unless defined?(@_vr_cmdhandlers)
134
+ @_vr_cmdhandlers[msg]=[] unless _vr_cmdhandlers[msg]
135
+ @_vr_cmdhandlers[msg].push [handlername,handlertype,argparsestr]
136
+ end
137
+
138
+ def deleteCommandHandler(msg,handlername)
139
+ return false unless @_vr_cmdhandlers[msg]
140
+ @_vr_cmdhandlers.delete_if do |shandler|
141
+ shandler[0] != (PREHANDLERSTR+handlername).intern
142
+ end
143
+ end
144
+ end
145
+
146
+
147
+ ################################################
148
+ # Standard Control Container
149
+ #
150
+ module VRStdControlContainer
151
+ =begin
152
+ == VRStdControlContainer
153
+ This module provides a message handler for WM_COMMAND, which calls
154
+ the defined methods in a parent window.
155
+ VRForm includes this module automatically loading "vrcontrol.rb".
156
+ =end
157
+
158
+ include VRMessageHandler
159
+
160
+ def stdcontrolcontainerinit
161
+ addHandler(WMsg::WM_COMMAND,"wmcommand",MSGTYPE::ARGPASS,nil)
162
+ addEvent WMsg::WM_COMMAND
163
+ end
164
+
165
+ def vrinit
166
+ super
167
+ stdcontrolcontainerinit
168
+ addNoRelayMessages [WMsg::WM_COMMAND]
169
+ end
170
+
171
+ def self_wmcommand(msg)
172
+ id=LOWORD(msg.wParam)
173
+ ct=@controls[id] # Activated Control
174
+ if !ct then
175
+ if !@_vr_menu then return end
176
+ ct=@_vr_menus[id]
177
+ if !ct then
178
+ return # no handler
179
+ end
180
+ end
181
+
182
+ messageid=HIWORD(msg.wParam)
183
+ return unless ct._vr_cmdhandlers and ct._vr_cmdhandlers[messageid]
184
+
185
+ ct._vr_cmdhandlers[messageid].each do |shandler|
186
+ args=msgarg2handlerarg(shandler[1],msg,shandler[2])
187
+ ct.__send__(shandler[0],*args) if ct.respond_to?(shandler[0])
188
+ msg.retval = controlmsg_dispatching(ct,shandler[0],*args)
189
+ end
190
+ end
191
+
192
+ end
193
+
194
+ # add
195
+ module VRContainersSet
196
+ include VRStdControlContainer
197
+ INITIALIZERS.push :stdcontrolcontainerinit
198
+ end
199
+
200
+
201
+
202
+ ##########################################
203
+ # Standard Controls
204
+ #
205
+ #
206
+ # Minimum definition for a Standard Control is
207
+ #
208
+ #> class VRSampleControl <VRStdControl
209
+ #> WINCLASSINFO = ["ControlClass",additionalStyle,exStyle]
210
+ #> def vrinit()
211
+ #> super
212
+ #> addCommandHandler(message,eventname,type,argparsestr])
213
+ #> end
214
+ #> end
215
+ #
216
+ # @_vr_cmdhandlers such as {
217
+ ## message -> [eventname, argtype, unpackstr]
218
+ # WMsg::BN_CLICKED=>["clicked",MSGTYPE::ARGNONE,nil],
219
+ # WMsg::LBN_SELCHANGE=>["selchange",MSGTYPE::ARGNONE,nil]
220
+ #}
221
+ # ############################################################
222
+
223
+ class VRButton < VRStdControl
224
+ =begin
225
+ == VRButton
226
+ Button.
227
+ Button's caption can be set/got by caption/caption= method of SWin::Window.
228
+
229
+ === Event handlers
230
+ Buttons invoke the following method of parent window.
231
+ --- ????_clicked
232
+ This parent's method is fired when button is pushed.
233
+ --- ????_dblclicked
234
+ This parent's method is fired when button is double clicked.
235
+ =end
236
+
237
+ WINCLASSINFO = ["BUTTON",WStyle::BS_PUSHBUTTON]
238
+
239
+ def vrinit
240
+ super
241
+ addCommandHandler(WMsg::BN_CLICKED, "clicked", MSGTYPE::ARGNONE,nil)
242
+ addCommandHandler(WMsg::BN_DBLCLICKED, "dblclicked",MSGTYPE::ARGNONE,nil)
243
+ end
244
+ end
245
+
246
+ class VRGroupbox < VRStdControl
247
+ =begin
248
+ == VRGroupbox
249
+ Groupbox.
250
+
251
+ This control can be a container of other window.
252
+ You need to extend this class by Container modules, VRStdControlContainer for Standard Controls and VRCommonControlContainer for Common Controls.
253
+ =end
254
+
255
+ include VRParent
256
+ WINCLASSINFO = ["BUTTON",WStyle::BS_GROUPBOX]
257
+ end
258
+
259
+ class VRCheckbox < VRButton
260
+ =begin
261
+ == VRCheckbox
262
+ Check box.
263
+ Parent class is ((<VRButton>))
264
+
265
+ === Methods
266
+ Checkbox has the following methods.
267
+ --- checked?
268
+ Return boolean value whether checkbox is checked or not.
269
+ --- check(v)
270
+ Check checkbox as v(=true/false).
271
+ =end
272
+ WINCLASSINFO = ["BUTTON",WStyle::BS_AUTOCHECKBOX]
273
+
274
+ def checked?
275
+ c=sendMessage(WMsg::BM_GETCHECK,0,0) #getcheck
276
+ return c!=0
277
+ end
278
+ def check(v)
279
+ sendMessage WMsg::BM_SETCHECK, ( (v)? 1 : 0 ),0
280
+ end
281
+ end
282
+
283
+ class VRRadiobutton < VRCheckbox
284
+ =begin
285
+ == VRRadiobutton
286
+ Radio Button.
287
+
288
+ Parent class is ((<VRCheckbox>))
289
+ =end
290
+ WINCLASSINFO = ["BUTTON",WStyle::BS_AUTORADIOBUTTON]
291
+ end
292
+
293
+
294
+ class VRStatic < VRStdControl
295
+ =begin
296
+ == VRStatic
297
+ Static Control(text).
298
+
299
+ Text can be access as caption.
300
+ =end
301
+ WINCLASSINFO = ["STATIC",0]
302
+ def vrinit
303
+ addCommandHandler(WMsg::STN_CLICKED, "clicked",0,nil)
304
+ end
305
+ end
306
+
307
+ class VREdit < VRStdControl
308
+ =begin
309
+ == VREdit
310
+ Edit Control.
311
+
312
+ === Methods
313
+ --- text
314
+ Gets Text in the control. Line break(\r\n) is translated by this method.
315
+ --- text=(str)
316
+ Sets Text in the control. Line break is translated by this method.
317
+ --- getSel
318
+ Returns [start_pos,end_pos] of the selected area.
319
+ --- setSel(st,en,noscroll=0)
320
+ Sets the selected area specified by ((|st|)) as start point and ((|en|))
321
+ as end point and Scrolls to show the area. When ((|noscroll|)) is 1,
322
+ it doesn't scroll.
323
+ --- setCaret(r)
324
+ Sets cursor point at ((|r|))
325
+ --- replaceSel(newstr)
326
+ Replaces text in the selected area with ((|newstr|)).
327
+ --- readonly=(b)
328
+ Sets readonly flag as boolean ((|b|))
329
+ --- limit
330
+ Gets the length limit of this Editbox.
331
+ --- limit=(lmt)
332
+ Sets the length limit of this Editbox.
333
+ --- modified
334
+ Returns true if the editbox text is modified by user.
335
+ --- modified=(f)
336
+ Sets modified flag of the editbox.
337
+ --- cut
338
+ Cuts the selected area into clipboard.
339
+ --- copy
340
+ Copies the selected area into clipboard.
341
+ --- paste
342
+ Paste the clipboard text into the editbox.
343
+ --- clear
344
+ Clears selected area text.
345
+ Use ((<cut>)) method to set the text into clipboard.
346
+ --- undo
347
+ Undo the previous cut/copy/paste/clear action.
348
+
349
+ === Event handlers
350
+ Editboxes invoke the following method of parent window.
351
+ --- ????_changed
352
+ This parent's method is fired when editbox text is modified.
353
+ =end
354
+
355
+ WINCLASSINFO = ["EDIT",WStyle::ES_AUTOHSCROLL,WExStyle::WS_EX_CLIENTEDGE]
356
+
357
+ def vrinit
358
+ super
359
+ addCommandHandler(0x300,"changed",MSGTYPE::ARGNONE,nil)
360
+ end
361
+
362
+ def getSel
363
+ r=sendMessage(0xb0,0,0)
364
+ return LOWORD(r),HIWORD(r)
365
+ end
366
+
367
+ def setCaret(r)
368
+ setSel(r,r)
369
+ end
370
+
371
+ def setSel(st,en,noscroll=0)
372
+ sendMessage(0xb1,st,en)
373
+ end
374
+
375
+ def replaceSel(newstr)
376
+ sendMessage(0xc2,0,newstr.to_s)
377
+ end
378
+
379
+ def readonly=(b)
380
+ f= (b)? 1 : 0
381
+ sendMessage 0xcf,f,0
382
+ end
383
+
384
+ def limit=(lmt)
385
+ sendMessage 0xc5,lmt.to_i,0
386
+ end
387
+ def limit
388
+ sendMessage 0xd5,0,0
389
+ end
390
+
391
+ def modified
392
+ r=sendMessage 0xb8,0,0 #GETMODIFY
393
+ if r==0 then false else true end
394
+ end
395
+ alias modified? :modified
396
+ def modified=(f)
397
+ r= if f then 1 else 0 end
398
+ sendMessage 0xb9,r,0
399
+ end
400
+
401
+ # change linebreak code
402
+ # caption,caption= methods is raw methods
403
+
404
+ VR_REGEXPNEWLINE="\r\n"
405
+ def text() self.caption.gsub(/#{VR_REGEXPNEWLINE}/,$/); end
406
+ def text=(str)
407
+ self.caption = str.gsub(/([^\r])\n/,'\1'+VR_REGEXPNEWLINE)
408
+ end
409
+
410
+
411
+ # for clipboard and so on..
412
+ def cut
413
+ sendMessage 0x300,0,0 #CUT
414
+ end
415
+ def copy
416
+ sendMessage 0x301,0,0 #COPY
417
+ end
418
+ def paste
419
+ sendMessage 0x302,0,0 #PASTE
420
+ end
421
+ def clear
422
+ sendMessage 0x303,0,0 #CLEAR
423
+ end
424
+ def undo
425
+ sendMessage 0x304,0,0 #UNDO
426
+ end
427
+
428
+ end
429
+
430
+ class VRText < VREdit
431
+ =begin
432
+ == VRText
433
+ Mutiline Editbox.
434
+ Parent class is ((<VREdit>))
435
+
436
+ === Methods
437
+ --- scrollTo(line.col)
438
+ Scrolls ((|line|)) lines vertically and ((|col|)) columns horizontally.
439
+ --- visibleStartLine
440
+ Returns line number of the first visible line in the editbox.
441
+ --- countLines
442
+ Returns max line number.
443
+ --- getLineLengthOf(ln)
444
+ Returns length of the ((|ln|))-th line.
445
+ --- getLineTextOf(ln,maxlen)
446
+ Returns text of ((|ln|))-th line. If maxlen is specified, returned text is
447
+ limited in its length.
448
+ --- scrollup
449
+ Scrolls line up in the editbox.
450
+ --- scrolldown
451
+ Scrolls line down in the editbox.
452
+ --- scrollupPage
453
+ Scrolls page up in the editbox.
454
+ --- scrolldownPage
455
+ Scrolls page down in the editbox.
456
+ --- scrolltocaret
457
+ Scrolls the caret into view in the editbox.
458
+ --- char2line(ptr)
459
+ Returns the index of the line that contains the specified character index.
460
+ --- line2char(ln)
461
+ Returns the character index of a line.
462
+ --- getCurrentLine
463
+ Returns the current line index.
464
+ =end
465
+
466
+ WINCLASSINFO = ["EDIT",
467
+ WStyle::ES_MULTILINE|WStyle::ES_AUTOVSCROLL,WExStyle::WS_EX_CLIENTEDGE
468
+ ]
469
+
470
+ private
471
+ def c_scroll(r)
472
+ sendMessage 0xb5,r.to_i,0
473
+ end
474
+
475
+ public
476
+
477
+ def countLines
478
+ sendMessage 0x00BA,0,0
479
+ end
480
+
481
+ def scrollTo(line,col)
482
+ sendMessage 0x00B6,0,MAKELPARAM(line,col) #LINESCROLL
483
+ end
484
+ def visibleStartLine()
485
+ sendMessage 0x00CE,0,0 #GETFIRSTVISIBLELINE
486
+ end
487
+
488
+ def getLineLengthOf(l)
489
+ sendMessage 0xc1,l.to_i,0 #GETLINELENGTH
490
+ end
491
+ def getLineTextOf(l,textsize=getLineLengthOf(l))
492
+ r=pack("Ia",textsize," "*textsize)
493
+ len=sendMessage 0xc4,l.to_i,r
494
+ r[0,len]
495
+ end
496
+
497
+ def scrollup() c_scroll 0; end
498
+ def scrolldown() c_scroll 1; end
499
+ def scrollupPage() c_scroll 2; end
500
+ def scrolldownPage() c_scroll 3; end
501
+
502
+ def scrolltocaret
503
+ sendMessage 0xb7,0,0 #SCROLLCARET
504
+ end
505
+
506
+ def char2line(ptr)
507
+ sendMessage 0xc9,ptr.to_i,0 #LINEFROMCHAR
508
+ end
509
+ def line2char(l)
510
+ sendMessage 0xbb,l.to_i,0 #LINEINDEX
511
+ end
512
+ def getCurrentLine
513
+ char2line(-1)
514
+ end
515
+ end
516
+
517
+
518
+ class VRListbox < VRStdControl
519
+ =begin
520
+ == VRListbox
521
+ Listbox.
522
+ Listbox has multi strings to select.
523
+
524
+ === Methods
525
+ --- addString(idx,str)
526
+ Adds ((|str|)) String at the ((|idx|)).
527
+ When ((|idx|)) is omitted, ((|str|)) is added at the bottom.
528
+ --- deleteString(idx)
529
+ Deletes string at ((|idx|))
530
+ --- countStrings
531
+ Returns the count of its strings.
532
+ --- clearStrings
533
+ Deletes all strings.
534
+ --- eachString
535
+ Yields each string.
536
+ --- setListStrings(strarray)
537
+ Sets array of string ( ((|strarray|)) ) as the listbox strings.
538
+ --- selectedString
539
+ Returns the selected index.
540
+ --- select(idx)
541
+ Selects ((|idx|))-th string.
542
+ --- getTextOf(idx)
543
+ Retrieves the text of ((|idx|))-th string.
544
+ --- setDir(fname,opt=0)
545
+ Sets the filenames specified by ((|fname|)) to the listbox.
546
+ ((|opt|)) specifies the attributes of the files to be added.
547
+ --- findString(findstr,start=0)
548
+ Finds ((|findstr|)) in the listbox strings and returns the its index.
549
+ ((|start|)) specifies the index to start finding.
550
+ --- getDataOf(idx)
551
+ Retrieves the 32bit value associated with the ((|idx|))-th string.
552
+ --- setDataOf(idx,data)
553
+ Associates the 32bit value with the ((|idx|))-th string.
554
+ === Event handlers
555
+ --- ????_selchanged
556
+ Fired when the selected string is changed.
557
+ =end
558
+
559
+ WINCLASSINFO = ["LISTBOX",WStyle::LBS_STANDARD,WExStyle::WS_EX_CLIENTEDGE]
560
+
561
+ def vrinit
562
+ super
563
+ addCommandHandler(WMsg::LBN_SELCHANGE, "selchange",MSGTYPE::ARGNONE,nil)
564
+ set_liststrings
565
+ end
566
+
567
+ private
568
+ def set_liststrings
569
+ clearStrings
570
+
571
+ return unless defined? @_vr_init_items
572
+ 0.upto(@_vr_init_items.size-1) do |idx|
573
+ addString idx,@_vr_init_items[idx]
574
+ end if @_vr_init_items
575
+ end
576
+
577
+ public
578
+ def addString(*arg)
579
+ if arg[0].is_a?(Integer) then
580
+ sendMessage WMsg::LB_INSERTSTRING,arg[0],arg[1].to_s
581
+ else
582
+ sendMessage WMsg::LB_ADDSTRING,0,arg[0].to_s
583
+ end
584
+ end
585
+
586
+ def deleteString(idx)
587
+ sendMessage WMsg::LB_DELETESTRING,idx.to_i,0
588
+ end
589
+ def countStrings
590
+ sendMessage WMsg::LB_GETCOUNT,0,0
591
+ end
592
+
593
+ def clearStrings
594
+ c=getCount
595
+ (1..c).each do |i|
596
+ deleteString 0 #delete #0 c-times
597
+ end
598
+ end
599
+
600
+ def eachString
601
+ c=getCount
602
+ 0.upto(c-1) do |i|
603
+ yield getString(i)
604
+ end
605
+ end
606
+
607
+ def setListStrings(sarray)
608
+ @_vr_init_items=sarray
609
+ if hWnd>0 then set_liststrings end
610
+ end
611
+
612
+ def selectedString
613
+ sendMessage(WMsg::LB_GETCURSEL,0,0)
614
+ end
615
+
616
+ def getTextOf(idx)
617
+ len = sendMessage(WMsg::LB_GETTEXTLEN,idx.to_i,0) #LB_gettextlen
618
+ raise "No such index(#{idx}) in the Listbox"if len<0
619
+ str=" " * len
620
+ sendMessage(WMsg::LB_GETTEXT,idx.to_i,str) #LB_getText
621
+ str
622
+ end
623
+
624
+ def select(idx)
625
+ sendMessage(WMsg::LB_SETCURSEL,idx.to_i,0)
626
+ end
627
+
628
+ def setDir(fname,opt=0)
629
+ sendMessage(WMsg::LB_DIR,opt.to_i,fname.to_s)
630
+ end
631
+
632
+ def findString(findstr,start=0)
633
+ sendMessage(WMsg::LB_FINDSTRING,start.to_i,findstr.to_s)
634
+ end
635
+
636
+ def getDataOf(idx)
637
+ sendMessage(WMsg::LB_GETITEMDATA,idx.to_i,0)
638
+ end
639
+ def setDataOf(idx,data)
640
+ sendMessage(WMsg::LB_SETITEMDATA,idx.to_i,data.to_i)
641
+ end
642
+
643
+ def eachSelected
644
+ count = sendMessage(WMsg::LB_GETSELCOUNT,0,0)
645
+
646
+ if count<1 then
647
+ yield selectedString
648
+ return
649
+ end
650
+
651
+ buffer = '\0\0\0\0' * count
652
+ sendMessage(WMsg::LB_GETSELITEMS,count,buffer)
653
+
654
+ buffer.unpack("I*")[0,count].each do |i|
655
+ yield i
656
+ end
657
+ end
658
+
659
+ end
660
+
661
+ class VRCombobox < VRStdControl
662
+ =begin
663
+ == VRCombobox
664
+ Combobox is like Listbox, but Only one string is selected.
665
+
666
+ === Methods
667
+ --- addString(idx,str)
668
+ Adds ((|str|)) String at the ((|idx|)).
669
+ When ((|idx|)) is omitted, ((|str|)) is added at the bottom.
670
+ --- deleteString(idx)
671
+ Deletes string at ((|idx|))
672
+ --- countStrings
673
+ Returns the count of its strings.
674
+ --- clearStrings
675
+ Deletes all strings.
676
+ --- eachString
677
+ Yields each string.
678
+ --- setListStrings(strarray)
679
+ Sets array of string ( ((|strarray|)) ) as the combobox strings.
680
+ --- selectedString
681
+ Returns the selected index.
682
+ --- select(idx)
683
+ Selects ((|idx|))-th string.
684
+ --- getTextOf(idx)
685
+ Retrieves the text of ((|idx|))-th string.
686
+ --- setDir(fname,opt=0)
687
+ Sets the filenames specified by ((|fname|)) to the combobox.
688
+ ((|opt|)) specifies the attributes of the files to be added.
689
+ --- findString(findstr,start=0)
690
+ Finds ((|findstr|)) in the combobox strings and returns the its index.
691
+ ((|start|)) specifies the index to start finding.
692
+ --- getDataOf(idx)
693
+ Retrieves the 32bit value associated with the ((|idx|))-th string.
694
+ --- setDataOf(idx,data)
695
+ Associates the 32bit value with the ((|idx|))-th string.
696
+ === Event handlers
697
+ --- ????_selchanged
698
+ Fired when the selected string is changed.
699
+ =end
700
+
701
+ WINCLASSINFO = ["COMBOBOX",WStyle::CBS_STANDARD]
702
+
703
+ def vrinit
704
+ super
705
+ set_liststrings
706
+ addCommandHandler(WMsg::CBN_SELCHANGE, "selchange",MSGTYPE::ARGNONE,nil)
707
+ end
708
+
709
+ private
710
+ def set_liststrings
711
+ clearStrings
712
+ return unless defined? @_vr_init_items
713
+ 0.upto(@_vr_init_items.size-1) do |idx|
714
+ addString idx,@_vr_init_items[idx]
715
+ end if @_vr_init_items
716
+ end
717
+
718
+ public
719
+ def addString(*arg)
720
+ if arg[0].is_a?(Integer) then
721
+ sendMessage WMsg::CB_INSERTSTRING,arg[0],arg[1].to_s
722
+ else
723
+ sendMessage WMsg::CB_ADDSTRING,0,arg[0].to_s
724
+ end
725
+ end
726
+
727
+
728
+ def deleteString(idx)
729
+ sendMessage WMsg::CB_DELETESTRING,idx,0
730
+ end
731
+ def countStrings
732
+ sendMessage WMsg::CB_GETCOUNT,0,0
733
+ end
734
+
735
+ def clearStrings
736
+ c=getCount
737
+ (1..c).each do |i|
738
+ deleteString 0 #delete #0 c-times
739
+ end
740
+ end
741
+
742
+ def eachString
743
+ c=getCount
744
+ 0.upto(c-1) do |i|
745
+ yield getString(i)
746
+ end
747
+ end
748
+
749
+ def setListStrings(sarray)
750
+ @_vr_init_items=sarray
751
+ if hWnd>0 then set_liststrings end
752
+ end
753
+
754
+ def selectedString
755
+ sendMessage(WMsg::CB_GETCURSEL,0,0)
756
+ end
757
+
758
+ def getTextOf(idx)
759
+ len = sendMessage(WMsg::CB_GETLBTEXTLEN,idx,0) #CB_gettextlen
760
+ raise "No such index(#{idx}) in the Combobox"if len<0
761
+ str=" " * len
762
+ sendMessage(WMsg::CB_GETLBTEXT,idx,str) #CB_getText
763
+ str
764
+ end
765
+
766
+ def select(idx)
767
+ sendMessage(WMsg::CB_SETCURSEL,idx,0)
768
+ end
769
+
770
+ def setDir(fname,opt=0)
771
+ sendMessage(WMsg::CB_DIR,opt.to_i,fname.to_s)
772
+ end
773
+
774
+ def findString(findstr,start=0)
775
+ sendMessage(WMsg::CB_FINDSTRING,start.to_i,findstr.to_s)
776
+ end
777
+
778
+ def getDataOf(idx)
779
+ sendMessage(WMsg::CB_GETITEMDATA,idx.to_i,0)
780
+ end
781
+ def setDataOf(idx,data)
782
+ sendMessage(WMsg::CB_SETITEMDATA,idx.to_i,data.to_i)
783
+ end
784
+ end
785
+
786
+ #####################################
787
+ # Editable Combobox
788
+ # programmed by USHIWATARI-san
789
+ module WMsg
790
+ CBN_EDITCHANGE = 5
791
+ end
792
+ module WStyle
793
+ CBS_DROPDOWN = 0x00a00200 | 2
794
+ end
795
+
796
+ class VREditCombobox < VRCombobox
797
+ =begin
798
+ == VREditCombobox
799
+ Editable Combobox.
800
+ This is a kind of Combobox where you can edit the text.
801
+
802
+ === Methods
803
+ This has also VRCombobox's methods.
804
+ --- text
805
+ Returns the current text.
806
+
807
+ === Event handlers
808
+ --- changed
809
+ Fired when the text is changed.
810
+ =end
811
+
812
+
813
+ WINCLASSINFO = ["COMBOBOX",WStyle::CBS_DROPDOWN | WStyle::CBS_AUTOSCROLL ]
814
+ def vrinit
815
+ super
816
+ addCommandHandler(WMsg::CBN_EDITCHANGE, "changed",MSGTYPE::ARGNONE,nil)
817
+ end
818
+
819
+ def text
820
+ self.caption
821
+ end
822
+ def text=(str)
823
+ self.caption = str.gsub(/([^\r])\n/,'\1'+VREdit::VR_REGEXPNEWLINE)
824
+ end
825
+
826
+ end
827
+
828
+
829
+
830
+ #####################################
831
+ # Menu
832
+ #
833
+ class VRMenu
834
+ =begin
835
+ == VRMenu
836
+ Menu.
837
+
838
+ === Methods
839
+ --- append(caption,state)
840
+ Adds a new menu item at the last with the caption of ((|caption|)) and
841
+ the state of ((|state|)). See ((<state=>)) about ((|state|)).
842
+ --- insert(ptr,caption,name,state)
843
+ Inserts new item at ((|ptr|)).
844
+ --- delete(id)
845
+ Deletes menu. ((|id|)) can be a instance of VRMenuItem or a menu-id integer.
846
+ --- count
847
+ Counts the menu items.
848
+ --- set(sarr)
849
+ Sets the menu according to the ((|sarr|)) which is a structured array
850
+ of strings such like
851
+ (({ [ ["&File", [["&Open","open"],["E&xit","exit"]], }))
852
+ (({ ["&Edit",["&Copy","copy]] }))
853
+ (({ ] ] }))
854
+ Caption : TEXT
855
+ Name : TEXT
856
+ Menu : [Caption, Name|Menu]
857
+
858
+ When a menu is clicked, ((|Name|))_clicked method is fired.
859
+
860
+ =end
861
+
862
+ attr :menu
863
+ attr :parent
864
+
865
+ SEPARATOR=["sep","_vrmenusep",0x800]
866
+
867
+ def initialize(menu,parent)
868
+ @menu=menu
869
+ @parent=parent
870
+ end
871
+
872
+ def append (*arg)
873
+ m=VRMenuItem.new(@menu)
874
+ id=@parent.newControlID
875
+ if arg[2] then
876
+ @menu.append arg[0],id,arg[2]
877
+ else
878
+ @menu.append arg[0],id
879
+ end
880
+ @parent.registerMenu(m,arg[1],id,arg[0])
881
+ m
882
+ end
883
+ def insert (ptr,*arg)
884
+ m=VRMenuItem.new(@menu)
885
+ id=@parent.newControlID
886
+ if arg.size>2 then
887
+ @menu.insert arg[0],id,ptr,arg[2]
888
+ else
889
+ @menu.insert arg[0],id,ptr
890
+ end
891
+ @parent.registerMenu(m,arg[1],id,arg[0])
892
+ m
893
+ end
894
+ def delete (id)
895
+ if id.is_a?(VRMenuItem) then
896
+ @menu.delete id.etc
897
+ else
898
+ @menu.delete id
899
+ end
900
+ end
901
+ def count (*arg)
902
+ @menu.count(*arg)
903
+ end
904
+
905
+ def set(sarr)
906
+ sarr.each do |item|
907
+ if item[1].is_a?(Array) then
908
+ m=@parent.newMenu(true)
909
+ m.set(item[1])
910
+ @menu.append item[0],m.menu,item[2]
911
+ elsif item[1].is_a?(VRMenu) then
912
+ @menu.append item[0],item[1].menu,item[2]
913
+ else
914
+ append(*item)
915
+ end
916
+ end
917
+ self
918
+ end
919
+ end
920
+
921
+ VRMenuTemplate = Struct.new("VRMenuTemplate",:caption,:item,:state)
922
+ =begin
923
+ == VRMenuTemplate
924
+ If you don't like using Array for VRMenu#set, this will help you.
925
+
926
+ === Methods
927
+ --- caption
928
+ --- caption=
929
+ Represents the caption of the menu.
930
+ --- item
931
+ --- item=
932
+ When ((|item|)) is String, ((|item|)) means the name of menu item.
933
+ This name is used for the event handler name like ((|item|))_clicked.
934
+ ((|item|)) can be also an instance of VRMenuTemplate. In this case ((|item|))
935
+ represents its submenu.
936
+ === example
937
+ a=VRMenuTemplate.new
938
+ a.caption,a.item = "Test1","test1"
939
+
940
+ b=VRMenuTemplate.new("Test2","test2")
941
+ c=VRMenuTemplate.new("Test3","test3",VRMenuItem::GRAYED)
942
+
943
+ d1=VRMenuTemplate.new("Test4-1","test41")
944
+ d2=VRMenuTemplate.new("Test4-2","test42")
945
+ d3=VRMenuTemplate.new("Test4-3","test43")
946
+
947
+ d = VRMenuTemplate.new
948
+ d.caption , d.item = "Test4" , [d1,d2,d3]
949
+ =end
950
+
951
+ class VRMenuItem
952
+ =begin
953
+ == VRMenuItem
954
+ This is a wrapper of SWin::Menu
955
+ === Methods
956
+ --- new(menu)
957
+ ((|menu|)) must be the instance of SWin::Menu.
958
+ --- state
959
+ Returns the state of the menu item.
960
+ --- state=
961
+ Sets the state of the menu item.
962
+ state means
963
+ * 0 MF_ENABLED
964
+ * 1 MF_GRAYED
965
+ * 2 MF_DISABLED
966
+ * 8 MF_CHECKED
967
+ --- checked?
968
+ Returns true if the menu item is checked.
969
+ --- checked=
970
+ Sets true/false whether the menu item is checked or not.
971
+ --- modify(text)
972
+ Modifies the text of the menu item.
973
+ =end
974
+ attr :name,1
975
+ attr :etc,1
976
+
977
+ GRAYED=1
978
+ DISABLED=2
979
+ CHECKED=8
980
+
981
+ def initialize(menu)
982
+ @menu=menu
983
+ end
984
+ def _vr_cmdhandlers
985
+ {0=>[["clicked",MSGTYPE::ARGNONE,nil]], # for menu
986
+ 1=>[["clicked",MSGTYPE::ARGNONE,nil]]} # for key accelerator
987
+ end
988
+
989
+ def state= (st)
990
+ @menu.setState(@etc,st)
991
+ end
992
+ def state
993
+ @menu.getState(@etc)
994
+ end
995
+ def checked=(f)
996
+ @menu.setChecked(@etc,f)
997
+ end
998
+ def checked?
999
+ (self.state&8)==8
1000
+ end
1001
+ def modify(text)
1002
+ @menu.modify @etc,text
1003
+ end
1004
+ end
1005
+
1006
+ module VRKeyAcceleratorUseable # Thanks to Yukimisake-san.
1007
+ def menuTransTable(hsh)
1008
+ tVirt = {"Ctrl" => 0x08,"Shift" => 0x04,"Alt" => 0x10}
1009
+ tVkey = {"F1"=>0x70,"F2"=>0x71,"F3"=>0x72,"F4"=>0x73,
1010
+ "F5"=>0x74,"F6"=>0x75,"F7"=>0x76,"F8"=>0x77,
1011
+ "F9"=>0x78,"F10"=>0x79,"F11"=>0x7a,"F12"=>0x7b,
1012
+ "Insert"=>0x2d,"Delete"=>0x2e,"PageUp"=>0x21,"PageDown"=>0x22,
1013
+ "End"=>0x23,"Home"=>0x24
1014
+ }
1015
+ r = []
1016
+ hsh.each{|k,v|
1017
+ fVirt = 1
1018
+ key = nil
1019
+ if txt = v[/\t.*/] then
1020
+ a = txt.strip!.split(/\+/)
1021
+ a[0,a.size-1].each{|ii|
1022
+ raise "Iregal Key" unless n = tVirt[ii]
1023
+ fVirt += n } if a.size > 1
1024
+ if (s = a[a.size-1]).size > 1 then
1025
+ unless key = tVkey[s] then raise "Iregal Key" end
1026
+ else
1027
+ key = (s.upcase)[0]
1028
+ end
1029
+ end
1030
+ if key then
1031
+ r << fVirt
1032
+ r << key
1033
+ r << k
1034
+ end
1035
+ }
1036
+ r
1037
+ end
1038
+ end
1039
+
1040
+ module VRMenuUseable
1041
+ =begin
1042
+ == VRMenuUseable
1043
+ Include this module to use menus.
1044
+
1045
+ === Methods
1046
+ --- newMenu(popup=false)
1047
+ Creates a new ((<VRMenu>)). If popup is true, the created menu is popup menu.
1048
+ --- newPopupMenu
1049
+ Same as newMenu(true)
1050
+ --- setMenu(menu)
1051
+ Sets the menu ((<VRMenu>)) to the window.
1052
+ --- showPopup(popupmenu)
1053
+ Shows ((|popupmenu|)) at the cursor position
1054
+ =end
1055
+
1056
+ include VRKeyAcceleratorUseable
1057
+
1058
+ SetForegroundWindow = Win32API.new("user32","SetForegroundWindow","I","I")
1059
+
1060
+ def registerMenu(m,name,id,mcaption="")
1061
+ m.etc= id
1062
+ instance_eval("@"+name+"=m")
1063
+ @_vr_menus= {} unless defined?(@_vr_menus)
1064
+ @_vr_menucaptions= {} unless defined?(@_vr_menucaptions)
1065
+ @_vr_menus[id]= m
1066
+ @_vr_menucaptions[id] = mcaption
1067
+ m.name = name
1068
+ m
1069
+ end
1070
+
1071
+ def newMenu(popup=false)
1072
+ if popup then
1073
+ menu=@screen.factory.newpopup
1074
+ else
1075
+ menu=@screen.factory.newmenu
1076
+ end
1077
+ VRMenu.new(menu,self)
1078
+ end
1079
+
1080
+ def newPopupMenu # contributed by Yuya-san
1081
+ return self.newMenu(true)
1082
+ end
1083
+
1084
+ def setMenu(menu,keyacc=false)
1085
+ SetForegroundWindow.call(self.hWnd)
1086
+ if menu.is_a?(SWin::Menu) then
1087
+ super menu
1088
+ return
1089
+ end
1090
+
1091
+ @_vr_menu=menu
1092
+ @menu=menu
1093
+ super menu.menu
1094
+ if keyacc then
1095
+ tb = menuTransTable(@_vr_menucaptions)
1096
+ SWin::Application.setAccel(self,tb)
1097
+ end
1098
+ end
1099
+
1100
+ def showPopup(menu)
1101
+ SetForegroundWindow.call(self.hWnd)
1102
+ if menu.is_a?(SWin::Menu) then
1103
+ m=menu
1104
+ else # asumes it is VRMenu
1105
+ m=menu.menu
1106
+ @_vr_menu = menu
1107
+ end
1108
+ popupMenu m,*Cursor.get_screenposition
1109
+ end
1110
+
1111
+ def setMenuByArray(arr)
1112
+ self.setMenu newMenu(arr)
1113
+ end
1114
+
1115
+ end
1116
+
1117
+
1118
+ ##############################
1119
+ # Other Controls
1120
+ #
1121
+
1122
+ module WStruct
1123
+ SCROLLINFO="llllll"
1124
+ end
1125
+
1126
+ class VRScrollbar < VRControl
1127
+ WINCLASSINFO = ["SCROLLBAR",0]
1128
+ attr :smallstep,1
1129
+ attr :longstep,1
1130
+
1131
+ def vrinit
1132
+ setRange(0,100)
1133
+ self.pagesize=10
1134
+ self.position=50
1135
+ @smallstep, @longstep = 1,10
1136
+ end
1137
+
1138
+ def setRange(min,max)
1139
+ sendMessage 0xe6,min.to_i,max.to_i
1140
+ end
1141
+
1142
+ def position=(val)
1143
+ sendMessage 0xe0,val.to_i,1
1144
+ end
1145
+ def position
1146
+ sendMessage 0xe1,0,0
1147
+ end
1148
+
1149
+ def pagesize=(p)
1150
+ si=[4*7,2,0,0,p.to_i,0,0].pack WStruct::SCROLLINFO
1151
+ sendMessage 0xe9,1,si # SBM_SETSCROLLINFO
1152
+ end
1153
+ def pagesize
1154
+ si=[4*7,2,0,0,0,0,0].pack WStruct::SCROLLINFO
1155
+ sendMessage 0xea,1,si # SBM_GETSCROLLINFO
1156
+ si.unpack(WStruct::SCROLLINFO)[4]
1157
+ end
1158
+ end
1159
+
1160
+ class VRHScrollbar < VRScrollbar
1161
+ WINCLASSINFO = ["SCROLLBAR",0]
1162
+ end
1163
+ class VRVScrollbar < VRScrollbar
1164
+ WINCLASSINFO = ["SCROLLBAR",1]
1165
+ end
1166
+
1167
+ module WMsg
1168
+ WM_HSCROLL=276
1169
+ WM_VSCROLL=277
1170
+ end
1171
+
1172
+ module VRScrollbarContainer
1173
+ def scrollbarcontainerinit
1174
+ addHandler WMsg::WM_HSCROLL,"vrscroll",MSGTYPE::ARGINTINT,nil
1175
+ addHandler WMsg::WM_VSCROLL,"vrscroll",MSGTYPE::ARGINTINT,nil
1176
+ acceptEvents [ WMsg::WM_HSCROLL,WMsg::WM_VSCROLL]
1177
+ @_vr_scrollbars={}
1178
+ end
1179
+ def vrinit
1180
+ super
1181
+ scrollbarcontainerinit
1182
+ end
1183
+
1184
+ def searchscrollbar(hwnd)
1185
+ @_vr_scrollbars=Hash.new unless defined? @_vr_scrollbars
1186
+ srl = @_vr_scrollbars[hwnd] # false : to be ignored window, 0: form
1187
+ if srl==nil then
1188
+ @controls.each_value do |v|
1189
+ if v.is_a?(SWin::Window) and v.hWnd==hwnd then
1190
+ if v.is_a?(VRScrollbar) then
1191
+ @_vr_scrollbars[hwnd] = srl = v
1192
+ elsif defined?(VRTrackbar) and v.is_a?(VRTrackbar) then
1193
+ @_vr_scrollbars[hwnd] = srl = false
1194
+ elsif defined?(VRUpdown) and v.is_a?(VRUpdown) then
1195
+ @_vr_scrollbars[hwnd] = srl = false
1196
+ else
1197
+ @_vr_scrollbars[hwnd] = srl = 0
1198
+ end
1199
+ break
1200
+ end
1201
+ end # @controls.each_value
1202
+ end
1203
+
1204
+ case srl
1205
+ when 0
1206
+ self
1207
+ when false
1208
+ nil
1209
+ when nil
1210
+ nil
1211
+ else
1212
+ srl
1213
+ end
1214
+ end
1215
+
1216
+ def self_vrscroll(wparam,hwnd)
1217
+ srl = searchscrollbar(hwnd)
1218
+ return unless srl
1219
+
1220
+ code=LOWORD(wparam)
1221
+ if code==4 then
1222
+ pos=HIWORD(wparam)
1223
+ else
1224
+ pos = srl.position
1225
+ end
1226
+ case code
1227
+ when 0
1228
+ srl.sendMessage 224,pos-srl.smallstep,1
1229
+ when 1
1230
+ srl.sendMessage 224,pos+srl.smallstep,1
1231
+ when 2
1232
+ srl.sendMessage 224,pos-srl.longstep,1
1233
+ when 3
1234
+ srl.sendMessage 224,pos+srl.longstep,1
1235
+ when 4
1236
+ srl.sendMessage 224,pos,1
1237
+ end
1238
+ controlmsg_dispatching(srl,"changed")
1239
+ end
1240
+ end
1241
+
1242
+ # add
1243
+ module VRContainersSet
1244
+ include VRScrollbarContainer
1245
+ INITIALIZERS.push :scrollbarcontainerinit
1246
+ end
1247
+
1248
+
1249
+ ########################
1250
+ #
1251
+ # Control using VRPanel
1252
+ #
1253
+ class VRBitmapPanel < VRPanel
1254
+ =begin
1255
+ == VRBitmapPanel
1256
+ Bitmap panel that can display static bitmap.
1257
+
1258
+ === Methods
1259
+ --- loadFile(filename)
1260
+ Loads ((|filename|)) as bitmap file.
1261
+ --- createBitmap(info,bmp)
1262
+ Creates an bitmap from ((|info|)) and ((|bmp|)).
1263
+ --- bmp
1264
+ The instance of displaying SWin::Bitmap.
1265
+ =end
1266
+ attr :bmp,1
1267
+
1268
+ include VRDrawable
1269
+ def vrinit
1270
+ super
1271
+ @bmp=nil
1272
+ end
1273
+
1274
+ def loadFile(fname)
1275
+ @bmp=SWin::Bitmap.loadFile fname
1276
+ self.refresh
1277
+ end
1278
+
1279
+ def createBitmap(info,bmp)
1280
+ @bmp=SWin::Bitmap.createBitmap info,bmp
1281
+ self.refresh
1282
+ end
1283
+
1284
+ def self_paint
1285
+ drawBitmap @bmp if @bmp.is_a?(SWin::Bitmap)
1286
+ end
1287
+ end
1288
+
1289
+
1290
+ class VRCanvasPanel < VRPanel
1291
+ =begin
1292
+ == VRCanvasPanel
1293
+ Bitmap Canvas panel that can display drawable bitmap.
1294
+ === Methods
1295
+ --- createCanvas(w,h,color=0xffffff)
1296
+ Creates a new canvas dimensioned ( ((|w|)),((|h||)) ) and
1297
+ colored ((|color|)) on the background.
1298
+ --- canvas
1299
+ Returns the instance of SWin::Canvas to draw it.
1300
+ =end
1301
+
1302
+ attr :canvas
1303
+
1304
+ include VRDrawable
1305
+
1306
+ def createCanvas(w,h,color=0xffffff)
1307
+ @canvas=@screen.factory.newcanvas(w,h)
1308
+ @canvas.setBrush(color)
1309
+ @canvas.setPen(color)
1310
+ @canvas.fillRect(0,0,w,h)
1311
+ @canvas.setPen(0x0)
1312
+ end
1313
+
1314
+ def vrinit
1315
+ super
1316
+ @canvas=nil
1317
+ end
1318
+
1319
+ def self_paint
1320
+ bitblt @canvas if @canvas
1321
+ end
1322
+ end
1323
+
1324
+ if VR_COMPATIBILITY_LEVEL then
1325
+ require VR_DIR + 'compat/vrcontrol.rb'
1326
+ end