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

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

Controlの追加とそれに伴う修正

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