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

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

Controlがコンパイルできるように修正

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