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

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

フルコンパイルでのミスあぶり出し。註:修正は全て@300や@301以前に行われた。

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