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

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

wtypes.abを追加

File size: 16.6 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 Dim asyncInvokeData = New System.Windows.Forms.Detail.AsyncInvokeData
312 With asyncInvokeData
313 .FuncPtr = pfn
314 .Data = p
315 .AsyncResult = asyncResult
316 End With
317 Dim gch = System.Runtime.InteropServices.GCHandle.Alloc(asyncInvokeData)
318 wnd.PostMessage(WM_CONTROL_BEGININVOKE, 0, System.Runtime.InteropServices.GCHandle.ToIntPtr(gch))
319 Return pAsyncResult
320 End Function
321
322 ' BeginInvokeで呼び出した関数の戻り値を受け取る。
323 ' その関数がまだ終了していない場合、終了するまで待機する。
324 Function EndInvoke(ar As System.IAsyncResult) As VoidPtr
325 ar.WaitHandle.WaitOne()
326 Dim arInvoke = ar As System.Windows.Forms.Detail.AsyncResultForInvoke
327 Return arInvoke.Result
328 End Function
329
330 ' 与えられたウィンドウハンドルがControl(若しくはその派生クラス)の
331 ' インスタンスに対応するものであった場合、
332 ' 元のインスタンスを返す。
333 ' そうでなければNothingを返す。
334 Static Function FromHandle(hwnd As HWND) As Control
335 If IsWindow(hwnd) Then
336 If GetClassLongPtr(hwnd, GCW_ATOM) = atom Then
337 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(GetWindowLongPtr(hwnd, GWLP_THIS))
338 Return gch.Target As Control
339 End If
340 End If
341 Return Nothing As Control
342 End Function
343
344 Virtual Sub ResetText()
345 text = ""
346 End Sub
347
348 Override Function ToString() As String
349 Return text
350 End Function
351
352 ' Wrapper Methods
353 Sub BringToFront()
354 wnd.BringToTop()
355 End Sub
356
357 Sub Hide()
358 wnd.Show(SW_HIDE)
359 End Sub
360
361 Sub Show()
362 wnd.Show(SW_SHOW)
363 End Sub
364
365 Sub Update()
366 wnd.Update()
367 End Sub
368
369 Sub CreateControl()
370 CreateHandle() '暫定
371 End Sub
372
373Protected
374
375 '---------------------------------------------------------------------------
376 ' Protected Properties
377' Const Virtual Function CanRaiseEvents() As Boolean
378 Virtual Function CreateParams() As CreateParams
379 Return createParams
380 End Function
381' Virtual Function DefaultCursor() As Cursor
382
383 Virtual Function DefaultSize() As Size
384 Dim s As Size(300, 300)
385 Return s
386 End Function
387
388' Function FontHeight() As Long
389' Sub FontHeight(h As Long)
390
391' Const Virtual Function Cursor() As Cursor
392' Virtual Sub Cursor(c As Cursor)
393
394 '---------------------------------------------------------------------------
395 ' Protected Methods
396 Virtual Sub CreateHandle()
397 Dim createParams = CreateParams()
398 Dim gch = GCHandle.Alloc(This)
399 TlsSetValue(tlsIndex, GCHandle.ToIntPtr(gch) As VoidPtr)
400 With createParams
401 Dim hwndParent = 0 As HWND
402 If Not Object.ReferenceEquals(parent, Nothing) Then
403 hwndParent = parent.Handle
404 End If
405 Dim pText As PCTSTR
406 If String.IsNullOrEmpty(text) Then
407 pText = "" As PCTSTR
408 Else
409 pText = ToTCStr(text)
410 End If
411
412 If CreateWindowEx(.ExStyle, atom As ULONG_PTR As PCSTR, pText, .Style, _
413 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, _
414 hwndParent, 0, hInstance, 0) = 0 Then
415 ' Error
416 Dim buf[1023] As TCHAR
417 wsprintf(buf, ToTCStr(Ex"Control: CreateWindowEx failed. Error code: &h%08X\r\n"), GetLastError())
418 OutputDebugString(buf)
419' Debug
420 ExitThread(0)
421 End If
422 End With
423 gch.Free()
424 End Sub
425
426 Virtual Sub DefWndProc(m As Message)
427 m.Result = DefWindowProc(m.HWnd, m.Msg, m.WParam, m.LParam)
428 End Sub
429
430 Virtual Sub WndProc(m As Message)
431 With m
432 Select Case .Msg
433 Case WM_GETTEXTLENGTH
434 .Result = text.Length 'ToDo: Unicode対応
435 Case WM_GETTEXT
436 Dim size = System.Math.Min(.WParam As SIZE_T, (text.Length + 1) As SIZE_T)
437 ActiveBasic.Strings.ChrCopy(.LParam As PCTSTR, ToTCStr(text), size)
438 .Result = size
439 Case WM_SETTEXT
440 text = New String(.LParam As PCTSTR)
441 Case WM_ENABLE
442 OnEnabledChanged(System.EventArgs.Empty)
443 Case WM_ERASEBKGND
444 ' OnPaintBackgroundに移すべき
445 Dim hdc = .WParam As HDC
446 Dim hbr = CreateSolidBrush(bkColor.ToCOLORREF())
447 Dim hbrOld = SelectObject(hdc, hbr)
448 Dim rc = wnd.ClientRect
449 Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom)
450 SelectObject(hdc, hbrOld)
451 DeleteObject(hbr)
452 Case WM_CONTROL_INVOKE
453 Dim pfn = .LParam As System.Windows.Forms.Detail.InvokeProc
454 .Result = pfn(m.WParam As VoidPtr) As LRESULT
455 Case WM_CONTROL_BEGININVOKE
456 OnControlBeginInvoke(m)
457 Case WM_CREATE
458 OnHandleCreated(System.EventArgs.Empty)
459 Case WM_DESTROY
460 OnHandleDestroyed(System.EventArgs.Empty)
461 Case Else
462 DefWndProc(m)
463 End Select
464 End With
465 End Sub
466
467 Virtual Sub SetClientSizeCore(x As Long, y As Long)
468 Dim rc As RECT
469 With rc
470 .left = 0
471 .top = 0
472 .right = x
473 .bottom = y
474 End With
475 Dim hasMenu = FALSE As BOOL
476 If wnd.Parent As HWND = 0 Then
477 If wnd.Menu <> 0 Then
478 hasMenu = TRUE
479 End If
480 End If
481 AdjustWindowRectEx(rc, wnd.Style, hasMenu, wnd.ExStyle)
482 wnd.Move(rc)
483 End Sub
484
485 Virtual Sub SetBoundsCore(x As Long, y As Long, width As Long, height As Long, bs As BoundsSpecified)
486' If Not (bs As DWord And BoundsSpecified.X As DWord) Then
487 x = Left
488' End If
489' If Not (bs As DWord And BoundsSpecified.Y As DWord) Then
490 y = Right
491' End If
492' If Not (bs As DWord And BoundsSpecified.Width As DWord) Then
493 width = Width
494' End If
495' If Not (bs As DWord And BoundsSpecified.Height As DWord) Then
496 height = Height
497' End If
498 wnd.Move(x, y, width, height)
499 End Sub
500
501 Virtual Sub NotifyInvalidate(r As Rectangle)
502 Dim rc As RECT
503 rc = r.ToRECT()
504 wnd.InvalidateRect(rc)
505 End Sub
506
507 Virtual Sub OnPaintBackground(e As PaintEventArgs) : End Sub
508 Virtual Sub OnEnabledChanged(e As System.EventArgs) : End Sub
509 Virtual Sub OnBackColorChanged(e As System.EventArgs) : End Sub
510 Virtual Sub OnHandleCreated(e As System.EventArgs) : End Sub
511 Virtual Sub OnHandleDestroyed(e As System.EventArgs) : End Sub
512 Virtual Sub OnTextChanged(e As System.EventArgs)
513 wnd.SetText(ToTCStr(text))
514 End Sub
515
516Private
517 ' Member variables
518 wnd As WindowHandle
519 text As String
520 parent As Control
521 bkColor As Color
522
523 Static createParams As CreateParams
524
525 'ウィンドウ作成時にウィンドウプロシージャへThisを伝えるためのもの
526 Static tlsIndex As DWord
527
528 Static hInstance As HINSTANCE
529 Static atom As ATOM
530
531 Static Const WM_CONTROL_INVOKE = WM_USER + 0 As DWord
532 Static Const WM_CONTROL_BEGININVOKE = WM_USER + 1 As DWord
533
534 Static Const WindowClassName = "ActiveBasic Control"
535Public
536 Static Sub Initialize(hinst As HINSTANCE)
537 tlsIndex = TlsAlloc()
538 hInstance = hinst
539
540 Dim wcx As WNDCLASSEX
541 With wcx
542 .cbSize = Len (wcx)
543 .style = CS_HREDRAW Or CS_VREDRAW Or CS_DBLCLKS
544 .lpfnWndProc = AddressOf (WndProcFirst)
545 .cbClsExtra = 0
546 .cbWndExtra = SizeOf (LONG_PTR) * 2
547 .hInstance = hinst
548 .hIcon = 0
549 .hCursor = LoadImage(0, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE Or LR_SHARED) As HCURSOR
550 .hbrBackground = 0
551 .lpszMenuName = 0
552 .lpszClassName = ToTCStr(WindowClassName)
553 .hIconSm = 0
554 End With
555 atom = RegisterClassEx(wcx)
556 If atom = 0 Then
557 Dim buf[1023] As TCHAR
558 wsprintf(buf, ToTCStr(Ex"Control: RegisterClasseEx failed. Error code: &h%08X\r\n"), GetLastError())
559 OutputDebugString(buf)
560 Debug
561 ExitThread(0)
562 End If
563
564 With createParams
565 ' 値は暫定的なもの
566 .Style = WS_OVERLAPPEDWINDOW
567 .ExStyle = WS_EX_APPWINDOW
568 End With
569 End Sub
570
571 Static Sub Uninitialize()
572 UnregisterClass(atom As ULONG_PTR As PCSTR, hInstance)
573 TlsFree(tlsIndex)
574 End Sub
575Private
576 Static Const GWLP_THIS = SizeOf (LONG_PTR) * 0 As Long
577 Static Const GWLP_TAG = SizeOf (LONG_PTR) * 1 As Long
578
579 ' Windowsから呼ばれるウィンドウプロシージャ。WndProc
580 Static Function WndProcFirst(hwnd As HWND, msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
581 Dim rThis = Control.FromHandle(hwnd) As Control
582 If Object.ReferenceEquals(rThis As Object, Nothing) Then
583 Dim gchValue = TlsGetValue(tlsIndex) As LONG_PTR
584 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(gchValue)
585 rThis = gch.Target As Control
586 ' ウィンドウが作られて最初にWndProcFirstが呼ばれたとき
587 If Object.ReferenceEquals(rThis, Nothing) Then
588 ' あってはならない事態
589 Debug
590 ExitThread(-1)
591 End If
592 rThis.wnd = New WindowHandle(hwnd)
593 SetWindowLongPtr(hwnd, GWLP_THIS, gchValue)
594 End If
595
596 Dim m = Message.Create(hwnd, msg, wp, lp)
597 rThis.WndProc(m)
598 Return m.Result
599 End Function
600
601 ' BeginInvokeが呼ばれたときの処理
602 Sub OnControlBeginInvoke(m As Message)
603 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(m.LParam)
604 Dim data = gch.Target As System.Windows.Forms.Detail.AsyncInvokeData
605 With data
606 Dim pfn = .FuncPtr
607 .AsyncResult.Result = pfn(.Data)
608 SetEvent(.AsyncResult.AsyncWaitHandle.Handle)
609 End With
610 End Sub
611End Class
612
613Namespace Detail
614Class _System_ControlIinitializer
615Public
616 Sub _System_ControlIinitializer(hinst As HINSTANCE)
617 System.Windows.Forms.Control.Initialize(hinst)
618 End Sub
619
620 Sub ~_System_ControlIinitializer()
621 System.Windows.Forms.Control.Uninitialize()
622 End Sub
623End Class
624
625#ifndef _SYSTEM_NO_INITIALIZE_CONTROL_
626Dim _System_ControlInitializer As _System_ControlIinitializer(GetModuleHandle(0))
627#endif '_SYSTEM_NO_INITIALIZE_CONTROL_
628
629End Namespace
630
631End Namespace 'Forms
632End Namespace 'Widnows
633End Namespace 'System
634
635#endif '__SYSTEM_WINDOWS_FORMS_CONTROL_AB__
636
Note: See TracBrowser for help on using the repository browser.