source: trunk/Include/Classes/System/Windows/Forms/Control.ab@ 388

Last change on this file since 388 was 388, checked in by イグトランス (egtra), 16 years ago

Stringなどで例外を投げるようにした。
#147の解決。
CType ASCII文字判定関数群の追加。

File size: 17.5 KB
Line 
1' Classes/System/Windows/Forms/Control.ab
2
3#ifndef __SYSTEM_WINDOWS_FORMS_CONTROL_AB__
4#define __SYSTEM_WINDOWS_FORMS_CONTROL_AB__
5
6/*
7#require <Classes/System/Windows/Forms/misc.ab>
8#require <Classes/System/Windows/Forms/CreateParams.ab>
9#require <Classes/System/Windows/Forms/Message.ab>
10#require <Classes/System/Windows/Forms/PaintEventArgs.ab>
11#require <Classes/System/misc.ab>
12#require <Classes/System/Math.ab>
13#require <Classes/System/Threading/WaitHandle.ab>
14*/
15#require <Classes/System/Drawing/Color.ab>
16#require <Classes/System/Drawing/Point.ab>
17#require <Classes/System/Drawing/Size.ab>
18#require <Classes/System/Drawing/Rectangle.ab>
19/*
20#require <Classes/System/Runtime/InteropServices/GCHandle.ab>
21#require <Classes/ActiveBasic/Windows/WindowHandle.sbp>
22#require <Classes/ActiveBasic/Strings/Strings.ab>
23*/
24Namespace System
25Namespace Windows
26Namespace Forms
27
28Namespace Detail
29
30TypeDef InvokeProc = *Function(p As VoidPtr) As VoidPtr
31
32Class AsyncResultForInvoke
33 Implements System.IAsyncResult
34Public
35 ' Properties
36 Sub AsyncResultForInvoke(h As HANDLE)
37 waitHandle.Handle = h
38 End Sub
39
40 Function AsyncState() As Object
41 Return Nothing
42 End Function
43
44 Function AsyncWaitHandle() As System.Threading.WaitHandle
45 Return waitHandle
46 End Function
47
48 Function CompletedSynchronously() As Boolean
49 Return False
50 End Function
51
52 Function IsCompleted() As Boolean
53 Return waitHandle.WaitOne(0, False)
54 End Function
55
56 Const Function Result() As VoidPtr
57 Return result
58 End Function
59
60 Sub Result(r As VoidPtr)
61 result = r
62 End Sub
63
64Private
65 waitHandle As System.Threading.WaitHandle
66 result As VoidPtr
67End Class
68
69Class AsyncInvokeData
70Public
71 FuncPtr As InvokeProc
72 Data As *VoidPtr
73 AsyncResult As AsyncResultForInvoke
74End Class
75
76End Namespace 'Detail
77
78Class Control
79
80' Inherits IWin32Window
81Public
82 '---------------------------------------------------------------------------
83 ' Public Properties
84 Function AllowDrop() As Boolean
85 End Function
86
87 'Anchor
88 'AutoScrollOffset
89 'AutoSize
90 'BackColor下
91 'BackgroundImage
92 'BackgroundImageLayout
93 '-BindingContext
94 'Bottom 下
95 'Bounds 下
96 'CanFocus
97 'CanSelect
98 'Capture
99 '-CausesValidation
100 'CheckForIllegalCrossThreadCalls
101
102 /*Override*/ Function Handle() As HWND
103 Return wnd.HWnd
104 End Function
105
106 ' IDropTargetを実装するのでDragAcceptFiles関数は呼ばない。
107 Sub AllowDrop(a As Boolean)
108 End Sub
109
110 Const Function Visible() As Boolean
111 Return wnd.Visible
112 End Function
113
114 Sub Visible(v As Boolean)
115 wnd.Visible(v)
116 End Sub
117
118 Const Function Text() As String
119 Return text
120 End Function
121
122 Sub Text(t As String)
123 text = t
124 Dim e As EventArgs
125 OnTextChanged(e)
126 End Sub
127
128 Const Function Enabled() As Boolean
129 Return wnd.Enabled
130 End Function
131
132 Sub Enabled(e As Boolean)
133 ' OnEnabledChangedはWM_ENABLE経由で呼ばれる
134 wnd.Enabled(e)
135 End Sub
136
137 Const Function Bounds() As Rectangle
138 Dim wr As RECT
139 wr = wnd.WindowRect
140 Dim r = New Rectangle(wr)
141 Dim parent = Parent
142 If Object.ReferenceEquals(parent, Nothing) Then
143 Return parent->RectangleToClient(r)
144 Else
145 Return r
146 End If
147 End Function
148/* BoundsSpecifiedが使用不能なのでコメントアウト
149 Sub Bounds(r As Rectangle)
150 SetBoundsCore(r.X, r.Y, r.Width, r.Height, BoundsSpecified.All)
151 End Sub
152*/
153 Const Function Location() As Point
154 Return Bounds.Location
155 End Function
156/*
157 Sub Location(p As Point)
158 SetBoundsCore(p.X, p.Y, 0, 0, BoundsSpecified.Location)
159 End Sub
160*/
161 Const Function Size() As Size
162 Return Bounds.Size
163 End Function
164/*
165 Sub Size(s As Size)
166 SetBoundsCore(0, 0, s.Width, s.Height, BoundsSpecified.Size)
167 End Sub
168
169 Const Function ClientRectangle() As Rectangle
170 Return New Rectangle(wnd.ClientRect)
171 End Function
172
173 Const Function ClientSize() As Size
174 Return ClientRectangle.Size
175 End Function
176*/
177 Const Function Left() As Long
178 Dim b = Bounds
179 Return b.Left
180 End Function
181/*
182 Sub Left(l As Long)
183 SetBoundsCore(l, 0, 0, 0, BoundsSpecified.X)
184 End Sub
185*/
186 Const Function Top() As Long
187 Dim b = Bounds
188 Return b.Top
189 End Function
190/*
191 Sub Top(t As Long)
192 SetBoundsCore(0, t, 0, 0, BoundsSpecified.Y)
193 End Sub
194*/
195 Const Function Width() As Long
196 Dim b = Bounds
197 Return b.Width
198 End Function
199/*
200 Sub Width(w As Long)
201 SetBoundsCore(0, 0, w, 0, BoundsSpecified.Width)
202 End Sub
203*/
204 Const Function Height() As Long
205 Dim b = Bounds
206 Return b.Height
207 End Function
208/*
209 Sub Height(h As Long)
210 SetBoundsCore(0, 0, 0, h, BoundsSpecified.Height)
211 End Sub
212*/
213 Const Function Right() As Long
214 Dim b = Bounds
215 Return b.Left + b.Width
216 End Function
217
218 Const Function Bottom() As Long
219 Dim b = Bounds
220 Return b.Top + b.Height
221 End Function
222/*
223 Const Function PointToScreen(p As Point) As Point
224 PointToScreen = New Point
225 PointToScreen.X = p.X
226 PointToScreen.Y = p.Y
227 wnd.ClientToScreen(ByVal ObjPtr(PointToScreen) As *POINTAPI)
228 End Function
229
230 Const Function PointToClient(p As Point) As Point
231 PointToScreen = New Point
232 PointToClient.X = p.X
233 PointToClient.Y = p.Y
234 wnd.ScreenToClient(ByVal ObjPtr(PointToClient) As *POINTAPI)
235 End Function
236*/
237 Const Function RectangleToScreen(r As Rectangle) As Rectangle
238 Dim rc = r.ToRECT
239 wnd.ClientToScreen(rc)
240 Return New Rectangle(rc)
241 End Function
242
243 Const Function RectangleToClient(r As Rectangle) As Rectangle
244 Dim rc = r.ToRECT()
245 wnd.ScreenToClient(rc)
246 Return New Rectangle(rc)
247 End Function
248
249 Const Function InvokeRequired() As Boolean
250 Return wnd.ThreadId <> GetCurrentThreadId()
251 End Function
252
253 Const Virtual Function BackColor() As Color
254 Return bkColor
255 End Function
256
257 Virtual Sub BackColor(c As Color)
258 c = bkColor
259 OnBackColorChanged(New EventArgs)
260 End Sub
261
262 Function Parent() As Control
263 Return parent
264 End Function
265
266 Const Function IsHandleCreated() As Boolean
267 Return wnd.HWnd <> 0 Or IsWindow(wnd.HWnd) <> FALSE
268 End Function
269
270 Static Function DefaultBackColor() As Color
271 Return Color.FromArgb(255, 255, 255)
272 End Function
273
274 '---------------------------------------------------------------------------
275 ' Constractors
276
277 Sub Control()
278 Dim sz = DefaultSize()
279 init(Nothing, "", 100, 100, sz.Width, sz.Height)
280 End Sub
281
282 Sub Control(text As String)
283 Dim sz = DefaultSize()
284 init(Nothing, text, 100, 100, sz.Width, sz.Height)
285 End Sub
286
287 Sub Control(parent As Control, text As String)
288 Dim sz = DefaultSize()
289 init(parent, text, 100, 100, sz.Width, sz.Height)
290 End Sub
291
292 Sub Control(text As String, left As Long, top As Long, width As Long, height As Long)
293 init(Nothing, text, left, top, width, height)
294 End Sub
295
296 Sub Control(parent As Control, text As String, left As Long, top As Long, width As Long, height As Long)
297 init(parent, text, left, top, width, height)
298 End Sub
299
300Private
301
302 Sub init(parent As Control, text As String, left As Long, top As Long, width As Long, height As Long)
303 This.parent = parent
304' CreateControl()
305 End Sub
306
307
308 '---------------------------------------------------------------------------
309 ' Destractor
310Public
311 Virtual Sub ~Control()
312 If Not Object.ReferenceEquals(wnd, Nothing) Then
313 If wnd.IsWindow Then
314 wnd.Destroy() ' 暫定
315 End If
316 End If
317 End Sub
318
319 '---------------------------------------------------------------------------
320 ' Public Methods
321/*
322 ' 同期関数呼出、Controlが作成されたスレッドで関数を実行する。
323 ' 関数は同期的に呼び出されるので、関数が終わるまでInvokeは制御を戻さない。
324 Function Invoke(pfn As System.Windows.Forms.Detail.InvokeProc, p As VoidPtr) As VoidPtr
325 Return wnd.SendMessage(WM_CONTROL_INVOKE, p As WPARAM, pfn As LPARAM) As VoidPtr
326 End Function
327
328 ' 非同期関数呼出、Controlが作成されたスレッドで関数を実行する。
329 ' 関数は非同期的に呼び出されるので、BeginInvokeはすぐに制御を戻す。
330 ' 後にEndInvokeを呼び出すことにより、関数の戻り値を受け取れる。
331 Function BeginInvoke(pfn As System.Windows.Forms.Detail.InvokeProc, p As VoidPtr) As System.IAsyncResult
332 ' EndInvokeがDeleteする
333 Dim asyncResult = New System.Windows.Forms.Detail.AsyncResultForInvoke(CreateEvent(0, FALSE, FALSE, 0))
334 Dim asyncInvokeData = New System.Windows.Forms.Detail.AsyncInvokeData
335 With asyncInvokeData
336 .FuncPtr = pfn
337 .Data = p
338 .AsyncResult = asyncResult
339 End With
340 Dim gch = System.Runtime.InteropServices.GCHandle.Alloc(asyncInvokeData)
341 wnd.PostMessage(WM_CONTROL_BEGININVOKE, 0, System.Runtime.InteropServices.GCHandle.ToIntPtr(gch))
342 Return asyncResult
343 End Function
344
345 ' BeginInvokeで呼び出した関数の戻り値を受け取る。
346 ' その関数がまだ終了していない場合、終了するまで待機する。
347 Function EndInvoke(ar As System.IAsyncResult) As VoidPtr
348 ar.WaitHandle.WaitOne()
349 Dim arInvoke = ar As System.Windows.Forms.Detail.AsyncResultForInvoke
350 Return arInvoke.Result
351 End Function
352*/
353 ' 与えられたウィンドウハンドルがControl(若しくはその派生クラス)の
354 ' インスタンスに対応するものであった場合、
355 ' 元のインスタンスを返す。
356 ' そうでなければNothingを返す。
357 Static Function FromHandle(hwnd As HWND) As Control
358 If IsWindow(hwnd) Then
359 If GetClassLongPtr(hwnd, GCW_ATOM) = atom Then
360 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(GetWindowLongPtr(hwnd, GWLP_THIS))
361 Return gch.Target As Control
362 End If
363 End If
364 Return Nothing As Control
365 End Function
366
367 Virtual Sub ResetText()
368 text = ""
369 End Sub
370
371 Override Function ToString() As String
372 Return text
373 End Function
374
375 ' Wrapper Methods
376 Sub BringToFront()
377 wnd.BringToTop()
378 End Sub
379
380 Sub Hide()
381 wnd.Show(SW_HIDE)
382 End Sub
383
384 Sub Show()
385 Debug
386 wnd.Show(SW_SHOW)
387 End Sub
388
389 Sub Update()
390 wnd.Update()
391 End Sub
392
393 Sub CreateControl()
394 CreateHandle() '暫定
395 End Sub
396
397Protected
398
399 '---------------------------------------------------------------------------
400 ' Protected Properties
401' Const Virtual Function CanRaiseEvents() As Boolean
402 Virtual Function CreateParams() As CreateParams
403 Return createParams
404 End Function
405' Virtual Function DefaultCursor() As Cursor
406
407 Virtual Function DefaultSize() As Size
408 Return New Size(300, 300)
409 End Function
410
411' Function FontHeight() As Long
412' Sub FontHeight(h As Long)
413
414' Const Virtual Function Cursor() As Cursor
415' Virtual Sub Cursor(c As Cursor)
416
417 '---------------------------------------------------------------------------
418 ' Protected Methods
419 Virtual Sub CreateHandle()
420 Debug
421 If Not Object.ReferenceEquals(wnd, Nothing) Then
422 If wnd.HWnd <> 0 Then
423 Exit Sub
424 End If
425 End If
426
427 Dim createParams = CreateParams()
428 Dim gch = System.Runtime.InteropServices.GCHandle.Alloc(This)
429 TlsSetValue(tlsIndex, System.Runtime.InteropServices.GCHandle.ToIntPtr(gch) As VoidPtr)
430 With createParams
431 Dim pText As PCTSTR
432 If String.IsNullOrEmpty(text) Then
433 pText = "" As PCTSTR
434 Else
435 pText = ToTCStr(text)
436 End If
437
438 If CreateWindowEx(.ExStyle, atom As ULONG_PTR As PCSTR, pText, .Style, _
439 .X, .Y, .Width, .Height, _
440 .Parent, 0, hInstance, 0) = 0 Then
441 ' Error
442 Dim buf[1023] As TCHAR
443 wsprintf(buf, ToTCStr(Ex"Control: CreateWindowEx failed. Error code: &h%08X\r\n"), GetLastError())
444 OutputDebugString(buf)
445
446 gch.Free()
447' Debug
448 ExitThread(0)
449 End If
450 End With
451
452 End Sub
453
454 Virtual Sub DefWndProc(m As Message)
455 m.Result = DefWindowProc(m.HWnd, m.Msg, m.WParam, m.LParam)
456 End Sub
457
458 Virtual Sub WndProc(m As Message)
459 With m
460 Select Case .Msg
461 Case WM_GETTEXTLENGTH
462 .Result = text.Length 'ToDo: Unicode対応
463 Case WM_GETTEXT
464 Dim size = System.Math.Min(.WParam As SIZE_T, (text.Length + 1) As SIZE_T)
465 ActiveBasic.Strings.ChrCopy(.LParam As PCTSTR, ToTCStr(text), size)
466 .Result = size
467 Case WM_SETTEXT
468 text = New String(.LParam As PCTSTR)
469 Case WM_ENABLE
470 OnEnabledChanged(System.EventArgs.Empty)
471 Case WM_ERASEBKGND
472 ' OnPaintBackgroundに移すべき
473 Dim hdc = .WParam As HDC
474 Dim hbr = CreateSolidBrush(bkColor.ToCOLORREF())
475 Dim hbrOld = SelectObject(hdc, hbr)
476 Dim rc = wnd.ClientRect
477 Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom)
478 SelectObject(hdc, hbrOld)
479 DeleteObject(hbr)
480 Case WM_CONTROL_INVOKE
481 Dim pfn = .LParam As System.Windows.Forms.Detail.InvokeProc
482 .Result = pfn(m.WParam As VoidPtr) As LRESULT
483 Case WM_CONTROL_BEGININVOKE
484 OnControlBeginInvoke(m)
485 Case WM_CREATE
486 OnHandleCreated(System.EventArgs.Empty)
487 Case WM_DESTROY
488 OnHandleDestroyed(System.EventArgs.Empty)
489
490 Case WM_LBUTTONDOWN
491 Goto *ButtonDown
492*ButtonDown
493 Case Else
494 DefWndProc(m)
495 End Select
496 End With
497 End Sub
498
499 Virtual Sub SetClientSizeCore(x As Long, y As Long)
500 Dim rc As RECT
501 With rc
502 .left = 0
503 .top = 0
504 .right = x
505 .bottom = y
506 End With
507 Dim hasMenu = FALSE As BOOL
508 If wnd.Parent As HWND = 0 Then
509 If wnd.Menu <> 0 Then
510 hasMenu = TRUE
511 End If
512 End If
513 AdjustWindowRectEx(rc, wnd.Style, hasMenu, wnd.ExStyle)
514 wnd.Move(rc)
515 End Sub
516
517 Virtual Sub SetBoundsCore(x As Long, y As Long, width As Long, height As Long, bs As BoundsSpecified)
518' If Not (bs As DWord And BoundsSpecified.X As DWord) Then
519 x = Left
520' End If
521' If Not (bs As DWord And BoundsSpecified.Y As DWord) Then
522 y = Right
523' End If
524' If Not (bs As DWord And BoundsSpecified.Width As DWord) Then
525 width = Width
526' End If
527' If Not (bs As DWord And BoundsSpecified.Height As DWord) Then
528 height = Height
529' End If
530 wnd.Move(x, y, width, height)
531 End Sub
532
533 Virtual Sub NotifyInvalidate(r As Rectangle)
534 Dim rc As RECT
535 rc = r.ToRECT()
536 wnd.InvalidateRect(rc)
537 End Sub
538
539' Virtual Sub OnPaintBackground(e As PaintEventArgs) : End Sub
540 Virtual Sub OnEnabledChanged(e As System.EventArgs) : End Sub
541 Virtual Sub OnBackColorChanged(e As System.EventArgs) : End Sub
542 Virtual Sub OnHandleCreated(e As System.EventArgs) : End Sub
543 Virtual Sub OnHandleDestroyed(e As System.EventArgs) : End Sub
544 Virtual Sub OnTextChanged(e As System.EventArgs)
545 wnd.SetText(ToTCStr(text))
546 End Sub
547
548Private
549 ' Member variables
550 wnd As ActiveBasic.Windows.WindowHandle
551 text As String
552 parent As Control
553 bkColor As Color
554
555 Static createParams As CreateParams
556
557 'ウィンドウ作成時にウィンドウプロシージャへThisを伝えるためのもの
558 Static tlsIndex As DWord
559
560 Static hInstance As HINSTANCE
561 Static atom As ATOM
562
563 Static Const WM_CONTROL_INVOKE = WM_USER + 0 As DWord
564 Static Const WM_CONTROL_BEGININVOKE = WM_USER + 1 As DWord
565
566 Static Const WindowClassName = "ActiveBasic Control"
567Public
568 Static Sub Initialize(hinst As HINSTANCE)
569 tlsIndex = TlsAlloc()
570 hInstance = hinst
571
572 Dim wcx As WNDCLASSEX
573 With wcx
574 .cbSize = Len (wcx)
575 .style = CS_HREDRAW Or CS_VREDRAW Or CS_DBLCLKS
576 .lpfnWndProc = AddressOf (WndProcFirst)
577 .cbClsExtra = 0
578 .cbWndExtra = SizeOf (LONG_PTR) * 2
579 .hInstance = hinst
580 .hIcon = 0
581 .hCursor = LoadImage(0, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE Or LR_SHARED) As HCURSOR
582 .hbrBackground = 0
583 .lpszMenuName = 0
584 .lpszClassName = ToTCStr(WindowClassName)
585 .hIconSm = 0
586 End With
587 atom = RegisterClassEx(wcx)
588 If atom = 0 Then
589 Dim buf[1023] As TCHAR
590 wsprintf(buf, ToTCStr(Ex"Control: RegisterClasseEx failed. Error code: &h%08X\r\n"), GetLastError())
591 OutputDebugString(buf)
592 Debug
593 ExitThread(0)
594 End If
595
596 With createParams
597 ' 値は暫定的なもの
598 .Style = WS_OVERLAPPEDWINDOW
599 .ExStyle = WS_EX_APPWINDOW
600 .Caption = String.Empty
601 .X = 0
602 .Y = 0
603 .Width = 0
604 .Height = 0
605 End With
606 End Sub
607
608 Static Sub Uninitialize()
609 UnregisterClass(atom As ULONG_PTR As PCSTR, hInstance)
610 TlsFree(tlsIndex)
611 End Sub
612Private
613 Static Const GWLP_THIS = SizeOf (LONG_PTR) * 0 As Long
614 Static Const GWLP_TAG = SizeOf (LONG_PTR) * 1 As Long
615
616 ' Windowsから呼ばれるウィンドウプロシージャ。WndProc
617 Static Function WndProcFirst(hwnd As HWND, msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
618 Dim rThis = Control.FromHandle(hwnd) As Control
619 If Object.ReferenceEquals(rThis As Object, Nothing) Then
620 Dim gchValue = TlsGetValue(tlsIndex) As LONG_PTR
621 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(gchValue)
622 rThis = gch.Target As Control
623 ' ウィンドウが作られて最初にWndProcFirstが呼ばれたとき
624 If Object.ReferenceEquals(rThis, Nothing) Then
625 ' あってはならない事態
626 Debug
627 ExitThread(-1)
628 End If
629 rThis.wnd = New ActiveBasic.Windows.WindowHandle(hwnd)
630 SetWindowLongPtr(hwnd, GWLP_THIS, gchValue)
631 ElseIf msg = WM_NCDESTROY Then
632 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(GetWindowLongPtr(hwnd, GWLP_THIS))
633 gch.Free()
634 End If
635
636 Dim m = Message.Create(hwnd, msg, wp, lp)
637 rThis.WndProc(m)
638 Return m.Result
639 End Function
640
641 ' BeginInvokeが呼ばれたときの処理
642 Sub OnControlBeginInvoke(m As Message)
643 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(m.LParam)
644 Dim data = gch.Target As System.Windows.Forms.Detail.AsyncInvokeData
645 With data
646 Dim pfn = .FuncPtr
647 .AsyncResult.Result = pfn(.Data)
648 SetEvent(.AsyncResult.AsyncWaitHandle.Handle)
649 End With
650 End Sub
651End Class
652
653Namespace Detail
654Class _System_ControlIinitializer
655Public
656 Sub _System_ControlIinitializer(hinst As HINSTANCE)
657 System.Windows.Forms.Control.Initialize(hinst)
658 End Sub
659
660 Sub ~_System_ControlIinitializer()
661 System.Windows.Forms.Control.Uninitialize()
662 End Sub
663End Class
664
665#ifndef _SYSTEM_NO_INITIALIZE_CONTROL_
666Dim _System_ControlInitializer As _System_ControlIinitializer(GetModuleHandle(0))
667#endif '_SYSTEM_NO_INITIALIZE_CONTROL_
668
669End Namespace
670
671End Namespace 'Forms
672End Namespace 'Widnows
673End Namespace 'System
674
675#endif '__SYSTEM_WINDOWS_FORMS_CONTROL_AB__
676
Note: See TracBrowser for help on using the repository browser.