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

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

Control周りの修正

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