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

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

String型の自身を変更するメソッドを、戻り値で返すように変更。
併せて文字列比較を自前の関数で行うように変更。
プロンプトのキャレットの位置計算が正しくなかったバグを修正。

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