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

Last change on this file since 461 was 461, checked in by dai, 16 years ago

Form周りを整理。一旦コミット。

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