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

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

#121対応、Classes/System/Windows/Forms以下を名前空間に入れた。

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