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

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

wtypes.abを追加

File size: 16.6 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))
311 Dim asyncInvokeData = New System.Windows.Forms.Detail.AsyncInvokeData
[223]312 With asyncInvokeData
[77]313 .FuncPtr = pfn
314 .Data = p
[223]315 .AsyncResult = asyncResult
[77]316 End With
[282]317 Dim gch = System.Runtime.InteropServices.GCHandle.Alloc(asyncInvokeData)
318 wnd.PostMessage(WM_CONTROL_BEGININVOKE, 0, System.Runtime.InteropServices.GCHandle.ToIntPtr(gch))
[77]319 Return pAsyncResult
320 End Function
321
322 ' BeginInvokeで呼び出した関数の戻り値を受け取る。
323 ' その関数がまだ終了していない場合、終了するまで待機する。
[282]324 Function EndInvoke(ar As System.IAsyncResult) As VoidPtr
[223]325 ar.WaitHandle.WaitOne()
[282]326 Dim arInvoke = ar As System.Windows.Forms.Detail.AsyncResultForInvoke
[223]327 Return arInvoke.Result
[77]328 End Function
329
330 ' 与えられたウィンドウハンドルがControl(若しくはその派生クラス)の
331 ' インスタンスに対応するものであった場合、
[223]332 ' 元のインスタンスを返す。
333 ' そうでなければNothingを返す。
334 Static Function FromHandle(hwnd As HWND) As Control
[77]335 If IsWindow(hwnd) Then
[223]336 If GetClassLongPtr(hwnd, GCW_ATOM) = atom Then
[282]337 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(GetWindowLongPtr(hwnd, GWLP_THIS))
[223]338 Return gch.Target As Control
[77]339 End If
340 End If
[223]341 Return Nothing As Control
[77]342 End Function
343
344 Virtual Sub ResetText()
345 text = ""
346 End Sub
347
[223]348 Override Function ToString() As String
[77]349 Return text
350 End Function
351
352 ' Wrapper Methods
353 Sub BringToFront()
354 wnd.BringToTop()
355 End Sub
356
357 Sub Hide()
358 wnd.Show(SW_HIDE)
359 End Sub
360
361 Sub Show()
362 wnd.Show(SW_SHOW)
363 End Sub
364
365 Sub Update()
366 wnd.Update()
367 End Sub
368
[240]369 Sub CreateControl()
370 CreateHandle() '暫定
371 End Sub
372
[77]373Protected
[240]374
[132]375 '---------------------------------------------------------------------------
376 ' Protected Properties
[223]377' Const Virtual Function CanRaiseEvents() As Boolean
378 Virtual Function CreateParams() As CreateParams
379 Return createParams
[77]380 End Function
381' Virtual Function DefaultCursor() As Cursor
382
383 Virtual Function DefaultSize() As Size
384 Dim s As Size(300, 300)
385 Return s
386 End Function
387
388' Function FontHeight() As Long
389' Sub FontHeight(h As Long)
390
391' Const Virtual Function Cursor() As Cursor
[240]392' Virtual Sub Cursor(c As Cursor)
[77]393
[132]394 '---------------------------------------------------------------------------
395 ' Protected Methods
[77]396 Virtual Sub CreateHandle()
397 Dim createParams = CreateParams()
[223]398 Dim gch = GCHandle.Alloc(This)
399 TlsSetValue(tlsIndex, GCHandle.ToIntPtr(gch) As VoidPtr)
[240]400 With createParams
[77]401 Dim hwndParent = 0 As HWND
[223]402 If Not Object.ReferenceEquals(parent, Nothing) Then
403 hwndParent = parent.Handle
[77]404 End If
[240]405 Dim pText As PCTSTR
406 If String.IsNullOrEmpty(text) Then
407 pText = "" As PCTSTR
408 Else
409 pText = ToTCStr(text)
410 End If
411
412 If CreateWindowEx(.ExStyle, atom As ULONG_PTR As PCSTR, pText, .Style, _
[77]413 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, _
414 hwndParent, 0, hInstance, 0) = 0 Then
415 ' Error
[223]416 Dim buf[1023] As TCHAR
417 wsprintf(buf, ToTCStr(Ex"Control: CreateWindowEx failed. Error code: &h%08X\r\n"), GetLastError())
[77]418 OutputDebugString(buf)
419' Debug
420 ExitThread(0)
421 End If
422 End With
[223]423 gch.Free()
[77]424 End Sub
425
[223]426 Virtual Sub DefWndProc(m As Message)
[77]427 m.Result = DefWindowProc(m.HWnd, m.Msg, m.WParam, m.LParam)
428 End Sub
429
[223]430 Virtual Sub WndProc(m As Message)
[77]431 With m
432 Select Case .Msg
433 Case WM_GETTEXTLENGTH
[282]434 .Result = text.Length 'ToDo: Unicode対応
[77]435 Case WM_GETTEXT
[282]436 Dim size = System.Math.Min(.WParam As SIZE_T, (text.Length + 1) As SIZE_T)
437 ActiveBasic.Strings.ChrCopy(.LParam As PCTSTR, ToTCStr(text), size)
[77]438 .Result = size
439 Case WM_SETTEXT
[223]440 text = New String(.LParam As PCTSTR)
[77]441 Case WM_ENABLE
[282]442 OnEnabledChanged(System.EventArgs.Empty)
[77]443 Case WM_ERASEBKGND
444 ' OnPaintBackgroundに移すべき
[132]445 Dim hdc = .WParam As HDC
[77]446 Dim hbr = CreateSolidBrush(bkColor.ToCOLORREF())
447 Dim hbrOld = SelectObject(hdc, hbr)
[132]448 Dim rc = wnd.ClientRect
[77]449 Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom)
450 SelectObject(hdc, hbrOld)
451 DeleteObject(hbr)
452 Case WM_CONTROL_INVOKE
[282]453 Dim pfn = .LParam As System.Windows.Forms.Detail.InvokeProc
[77]454 .Result = pfn(m.WParam As VoidPtr) As LRESULT
455 Case WM_CONTROL_BEGININVOKE
456 OnControlBeginInvoke(m)
[223]457 Case WM_CREATE
[282]458 OnHandleCreated(System.EventArgs.Empty)
[240]459 Case WM_DESTROY
[282]460 OnHandleDestroyed(System.EventArgs.Empty)
[77]461 Case Else
462 DefWndProc(m)
463 End Select
464 End With
465 End Sub
466
467 Virtual Sub SetClientSizeCore(x As Long, y As Long)
468 Dim rc As RECT
469 With rc
470 .left = 0
471 .top = 0
472 .right = x
473 .bottom = y
474 End With
475 Dim hasMenu = FALSE As BOOL
476 If wnd.Parent As HWND = 0 Then
477 If wnd.Menu <> 0 Then
478 hasMenu = TRUE
479 End If
480 End If
481 AdjustWindowRectEx(rc, wnd.Style, hasMenu, wnd.ExStyle)
482 wnd.Move(rc)
483 End Sub
484
485 Virtual Sub SetBoundsCore(x As Long, y As Long, width As Long, height As Long, bs As BoundsSpecified)
[223]486' If Not (bs As DWord And BoundsSpecified.X As DWord) Then
[77]487 x = Left
[223]488' End If
489' If Not (bs As DWord And BoundsSpecified.Y As DWord) Then
[77]490 y = Right
[223]491' End If
492' If Not (bs As DWord And BoundsSpecified.Width As DWord) Then
[77]493 width = Width
[223]494' End If
495' If Not (bs As DWord And BoundsSpecified.Height As DWord) Then
[77]496 height = Height
[223]497' End If
[77]498 wnd.Move(x, y, width, height)
499 End Sub
500
501 Virtual Sub NotifyInvalidate(r As Rectangle)
502 Dim rc As RECT
503 rc = r.ToRECT()
504 wnd.InvalidateRect(rc)
505 End Sub
506
[223]507 Virtual Sub OnPaintBackground(e As PaintEventArgs) : End Sub
[282]508 Virtual Sub OnEnabledChanged(e As System.EventArgs) : End Sub
509 Virtual Sub OnBackColorChanged(e As System.EventArgs) : End Sub
510 Virtual Sub OnHandleCreated(e As System.EventArgs) : End Sub
511 Virtual Sub OnHandleDestroyed(e As System.EventArgs) : End Sub
512 Virtual Sub OnTextChanged(e As System.EventArgs)
[223]513 wnd.SetText(ToTCStr(text))
[77]514 End Sub
515
516Private
517 ' Member variables
518 wnd As WindowHandle
519 text As String
[223]520 parent As Control
[77]521 bkColor As Color
522
523 Static createParams As CreateParams
524
525 'ウィンドウ作成時にウィンドウプロシージャへThisを伝えるためのもの
526 Static tlsIndex As DWord
527
528 Static hInstance As HINSTANCE
529 Static atom As ATOM
530
531 Static Const WM_CONTROL_INVOKE = WM_USER + 0 As DWord
532 Static Const WM_CONTROL_BEGININVOKE = WM_USER + 1 As DWord
533
[223]534 Static Const WindowClassName = "ActiveBasic Control"
[77]535Public
536 Static Sub Initialize(hinst As HINSTANCE)
537 tlsIndex = TlsAlloc()
538 hInstance = hinst
539
540 Dim wcx As WNDCLASSEX
541 With wcx
542 .cbSize = Len (wcx)
543 .style = CS_HREDRAW Or CS_VREDRAW Or CS_DBLCLKS
544 .lpfnWndProc = AddressOf (WndProcFirst)
545 .cbClsExtra = 0
546 .cbWndExtra = SizeOf (LONG_PTR) * 2
547 .hInstance = hinst
548 .hIcon = 0
549 .hCursor = LoadImage(0, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE Or LR_SHARED) As HCURSOR
550 .hbrBackground = 0
551 .lpszMenuName = 0
[240]552 .lpszClassName = ToTCStr(WindowClassName)
[77]553 .hIconSm = 0
554 End With
555 atom = RegisterClassEx(wcx)
556 If atom = 0 Then
[223]557 Dim buf[1023] As TCHAR
558 wsprintf(buf, ToTCStr(Ex"Control: RegisterClasseEx failed. Error code: &h%08X\r\n"), GetLastError())
[77]559 OutputDebugString(buf)
560 Debug
561 ExitThread(0)
562 End If
563
564 With createParams
565 ' 値は暫定的なもの
566 .Style = WS_OVERLAPPEDWINDOW
567 .ExStyle = WS_EX_APPWINDOW
568 End With
569 End Sub
570
571 Static Sub Uninitialize()
572 UnregisterClass(atom As ULONG_PTR As PCSTR, hInstance)
573 TlsFree(tlsIndex)
574 End Sub
575Private
576 Static Const GWLP_THIS = SizeOf (LONG_PTR) * 0 As Long
577 Static Const GWLP_TAG = SizeOf (LONG_PTR) * 1 As Long
578
579 ' Windowsから呼ばれるウィンドウプロシージャ。WndProc
580 Static Function WndProcFirst(hwnd As HWND, msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
[223]581 Dim rThis = Control.FromHandle(hwnd) As Control
582 If Object.ReferenceEquals(rThis As Object, Nothing) Then
583 Dim gchValue = TlsGetValue(tlsIndex) As LONG_PTR
[282]584 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(gchValue)
[223]585 rThis = gch.Target As Control
[77]586 ' ウィンドウが作られて最初にWndProcFirstが呼ばれたとき
[223]587 If Object.ReferenceEquals(rThis, Nothing) Then
[77]588 ' あってはならない事態
589 Debug
[240]590 ExitThread(-1)
[77]591 End If
[223]592 rThis.wnd = New WindowHandle(hwnd)
593 SetWindowLongPtr(hwnd, GWLP_THIS, gchValue)
[77]594 End If
[240]595
596 Dim m = Message.Create(hwnd, msg, wp, lp)
[223]597 rThis.WndProc(m)
[77]598 Return m.Result
599 End Function
600
601 ' BeginInvokeが呼ばれたときの処理
[223]602 Sub OnControlBeginInvoke(m As Message)
[282]603 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(m.LParam)
604 Dim data = gch.Target As System.Windows.Forms.Detail.AsyncInvokeData
[223]605 With data
606 Dim pfn = .FuncPtr
607 .AsyncResult.Result = pfn(.Data)
608 SetEvent(.AsyncResult.AsyncWaitHandle.Handle)
609 End With
[77]610 End Sub
611End Class
612
[282]613Namespace Detail
[77]614Class _System_ControlIinitializer
615Public
616 Sub _System_ControlIinitializer(hinst As HINSTANCE)
[282]617 System.Windows.Forms.Control.Initialize(hinst)
[77]618 End Sub
619
620 Sub ~_System_ControlIinitializer()
[282]621 System.Windows.Forms.Control.Uninitialize()
[77]622 End Sub
623End Class
624
625#ifndef _SYSTEM_NO_INITIALIZE_CONTROL_
626Dim _System_ControlInitializer As _System_ControlIinitializer(GetModuleHandle(0))
627#endif '_SYSTEM_NO_INITIALIZE_CONTROL_
628
[282]629End Namespace
630
631End Namespace 'Forms
632End Namespace 'Widnows
633End Namespace 'System
634
[77]635#endif '__SYSTEM_WINDOWS_FORMS_CONTROL_AB__
[240]636
Note: See TracBrowser for help on using the repository browser.