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

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

#121対応、Classes/System/Windows/Forms以下を名前空間に入れた。

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