source: trunk/ab5.0/ablib/src/Classes/ActiveBasic/Windows/UI/Control.ab@ 545

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

ActiveBasic.Windows.UI.FormsをUIへ移動。UI以下にForms以外置くものが思い浮かばないので。

File size: 12.8 KB
RevLine 
[473]1'Classes/ActiveBasic/Windows/UI/Control.ab
2
[545]3#require <Classes/ActiveBasic/Windows/UI/EventArgs.ab>
[473]4
5Namespace ActiveBasic
6Namespace Windows
7Namespace UI
8
[542]9'Namespace Detail
10' TypeDef PTrackMouseEvent = *Function(ByRef tme As TRACKMOUSEEVENT) As BOOL
11'End Namespace
12
[473]13Class Control
14Public
15 Sub Control()
16 End Sub
17
18 Virtual Sub ~Control()
19 End Sub
20
[542]21 Function Handle() As HWND
22 Handle = hwnd
[473]23 End Function
24
25 Static Function FromHWnd(hwnd As HWND) As Control
26 FromHWnd = Nothing
27 If IsWindow(hwnd) Then
28 FromHWnd = FromHWndCore(hwnd)
29 End If
30 End Function
31
32Private
33 Static Function FromHWndCore(hwnd As HWND) As Control
34 If GetClassLongPtr(hwnd, GCW_ATOM) = atom Then
35 Dim gchValue = GetProp(hwnd, PropertyInstance As ULONG_PTR As PCTSTR) As ULONG_PTR
36 If gchValue <> 0 Then
37 Dim gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(gchValue)
38 FromHWndCore = gch.Target As Control
39 Exit Function
40 End If
41 End If
42 End Function
43
44'--------------------------------
[544]45' ウィンドウ作成
[473]46/*
47 Function Create(
48 parent As HWND,
49 rect As RECT,
50 name As String,
51 style As DWord,
52 exStyle = 0 As DWord,
53 menu = 0 As HMENU) As HWND
54*/
[542]55
[473]56Public
57 Function Create() As Boolean
58 Dim cs As CREATESTRUCT
59 cs.hInstance = hInstance
60 cs.lpszClass = (atom As ULONG_PTR) As LPCTSTR
61 GetCreateStruct(cs)
62 Create = createImpl(cs)
63 End Function
64
65Protected
66 Abstract Sub GetCreateStruct(ByRef cs As CREATESTRUCT)
67
68 Function createImpl(ByRef cs As CREATESTRUCT) As Boolean
69 Imports System.Runtime.InteropServices
70
71 Dim gch = GCHandle.Alloc(This)
72 TlsSetValue(tlsIndex, GCHandle.ToIntPtr(gch) As VoidPtr)
73
[542]74 StartWndProc()
75
[473]76 With cs
77 Dim hwnd = CreateWindowEx(.dwExStyle, .lpszClass, .lpszName, .style,
78 .x, .y, .cx, .cy, .hwndParent, .hMenu, .hInstance, .lpCreateParams)
79 createImpl = hwnd <> 0
80 End With
81 End Function
82
83'--------------------------------
84' ウィンドウプロシージャ
85'Protected
86Public
87 Virtual Function WndProc(msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
[542]88 Dim h = Nothing As MessageEventHandler
89 Dim b = messageMap.TryGetValue(Hex$(msg), h)
90 If b Then
91 If Not IsNothing(h) Then
92 Dim a = New MessageEventArgs(hwnd, msg, wp, lp)
93 h(This, a)
94 WndProc = a.LResult
95 Exit Function
96 End If
97 End If
98 WndProc = DefWndProc(msg, wp, lp)
[473]99 End Function
100
101 Virtual Function DefWndProc(msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
[542]102 DefWndProc = DefWindowProc(hwnd, msg, wp, lp)
[473]103 End Function
104
105Private
[544]106 Static Function makeKeysFormMsg(e As MessageEventArgs) As Keys
[473]107 Dim t As DWord
[544]108 t = e.WParam And Keys.KeyCode
[473]109 t Or= (GetKeyState(VK_SHIFT) As Word And &h8000) << 1
110 t Or= (GetKeyState(VK_CONTROL) As Word And &h8000) << 2
111 t Or= (GetKeyState(VK_MENU) As Word And &h8000) << 3
[544]112 makeKeysFormMsg = t As Keys
[473]113 End Function
114
[544]115 Static Function makeMouseEventFromMsg(e As MessageEventArgs) As MouseEventArgs
116 Dim wp = e.WParam
117 Dim lp = e.LParam
118 makeMouseEventFromMsg = New MouseEventArgs(LOWORD(wp) As MouseButtons, 1, GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 0)
[542]119 End Function
[473]120
[542]121 /*!
122 @brief 最初にウィンドウプロシージャが呼ばれるときに実行される関数
123 ここでは、主なメッセージハンドラの登録を行っている。
124 @date 2008/07/11
125 */
126 Sub StartWndProc()
127 Dim t = This '#177対策
128 AddMessageEvent(WM_ERASEBKGND, AddressOf(t.OnEraseBackground))
129 Dim md = New MessageEventHandler(AddressOf(t.OnMouseDownBase))
130 AddMessageEvent(WM_LBUTTONDOWN, md)
131 AddMessageEvent(WM_RBUTTONDOWN, md)
132 AddMessageEvent(WM_MBUTTONDOWN, md)
133 AddMessageEvent(WM_XBUTTONDOWN, md)
134 Dim mu = New MessageEventHandler(AddressOf(t.OnMouseUpBase))
135 AddMessageEvent(WM_LBUTTONUP, mu)
136 AddMessageEvent(WM_RBUTTONUP, mu)
137 AddMessageEvent(WM_MBUTTONUP, mu)
138 AddMessageEvent(WM_XBUTTONUP, mu)
139 Dim mb = New MessageEventHandler(AddressOf(t.OnMouseDblClkBase))
140 AddMessageEvent(WM_LBUTTONDBLCLK, mu)
141 AddMessageEvent(WM_RBUTTONDBLCLK, mu)
142 AddMessageEvent(WM_MBUTTONDBLCLK, mu)
143 AddMessageEvent(WM_XBUTTONDBLCLK, mu)
[544]144
145 AddMessageEvent(WM_MOUSELEAVE, AddressOf(t.OnMouseLeaveBase))
[542]146 AddMessageEvent(WM_PAINT, AddressOf(t.OnPaintBase))
[544]147 AddMessageEvent(WM_KEYDOWN, AddressOf(t.OnKeyDownBase))
148' AddMessageEvent(WM_CHAR, AddressOf(t.OnChar))
149 AddMessageEvent(WM_CREATE, AddressOf(t.OnCreateBase))
[542]150 End Sub
[473]151
[542]152 Sub OnEraseBackground(sender As Object, e As MessageEventArgs)
153 Dim rc As RECT
154 Dim r = GetClientRect(hwnd, rc)
155 FillRect(e.WParam As HDC, rc, (COLOR_3DFACE + 1) As HBRUSH)
156 e.LResult = TRUE
157 End Sub
[473]158
[542]159 Sub OnMouseDownBase(sender As Object, e As MessageEventArgs)
[544]160 OnMouseDown(makeMouseEventFromMsg(e))
[542]161 End Sub
162
163 Sub OnMouseUpBase(sender As Object, e As MessageEventArgs)
[544]164 Dim me = makeMouseEventFromMsg(e)
[542]165 If doubleClickFired = False Then
[544]166' OnClick(System.EventArgs.Empty)
[542]167 OnMouseClick(me)
168 doubleClickFired = False
169 End If
170 OnMouseUp(me)
171 End Sub
172
173 Sub OnMouseDblClkBase(sender As Object, e As MessageEventArgs)
[544]174 Dim me = makeMouseEventFromMsg(e)
[542]175 doubleClickFired = True
176 OnMouseDown(me)
[544]177' OnDoubleClick(System.EventArgs.Empty)
[542]178 OnMouseDoubleClick(me)
179 End Sub
180
181 Sub OnMouseMoveBase(sender As Object, e As MessageEventArgs)
[544]182 Dim me = makeMouseEventFromMsg(e)
[542]183 If mouseEntered Then
184 OnMouseMove(me)
185 Else
186 mouseEntered = True
187 OnMouseEnter(me)
188 End If
189 End Sub
190
[544]191 Sub OnMouseLeaveBase(sender As Object, e As MessageEventArgs)
192 Dim me = makeMouseEventFromMsg(e)
193 OnMouseLeave(me)
194 mouseEntered = False
195 End Sub
196
[542]197 Sub OnPaintBase(sender As Object, e As MessageEventArgs)
198 Dim ps As PAINTSTRUCT
199 BeginPaint(hwnd, ps)
[544]200 Try
201 OnPaintDC(New PaintDCEventArgs(ps.hdc, ps.rcPaint))
202 Finally
[542]203 EndPaint(hwnd, ps)
[544]204 End Try
[542]205 End Sub
206
[544]207 Sub OnKeyDownBase(sender As Object, e As MessageEventArgs)
208 OnKeyDown(New KeyEventArgs(makeKeysFormMsg(e)))
209 End Sub
[542]210
[544]211 Sub OnKeyUpBase(sender As Object, e As MessageEventArgs)
212 OnKeyUp(New KeyEventArgs(makeKeysFormMsg(e)))
213 End Sub
214
215' コメントアウト解除のときはStartWndProcのコメントアウト解除も忘れないこと
216' Sub OnChar(sender As Object, e As MessageEventArgs)
217' OnKeyPress(New KeyPressEventArgs(e.WParam As Char))
218' End Sub
219
220 Sub OnCreateBase(sender As Object, e As MessageEventArgs)
221 OnCreate(New CreateEventArgs(e.LParam As *CREATESTRUCT))
222 End Sub
223
[542]224 messageMap As System.Collections.Generic.Dictionary<Object /*DWord*/, MessageEventHandler>
225
226Public
[473]227 /*!
[542]228 @biref メッセージイベントハンドラを登録する。
[473]229 @date 2007/12/04
230 */
[542]231 Sub AddMessageEvent(message As DWord, h As MessageEventHandler)
232 If Not IsNothing(h) Then
233 If IsNothing(messageMap) Then
234 messageMap = New System.Collections.Generic.Dictionary<Object, MessageEventHandler>
235 End If
236 Dim msg = Hex$(message)
237 Dim m = Nothing As MessageEventHandler
238 If messageMap.TryGetValue(msg, m) Then
239 messageMap.Item[msg] = m + h
240 Else
241 messageMap.Item[msg] = h
242 End If
243 End If
[473]244 End Sub
245
[542]246 /*!
247 @biref メッセージイベントハンドラ登録を解除する。
248 @date 2007/12/04
249 */
250 Sub RemoveMessageEvent(message As DWord, a As MessageEventHandler)
251 If Not IsNothing(a) Then
252 If Not IsNothing(messageMap) Then
[545]253 Dim msg = Hex$(message)
[542]254 Dim m = messageMap.Item[msg]
255 If Not IsNothing(m) Then
256 messageMap.Item[msg] = m - a
257 End If
258 End If
259 End If
260 End Sub
261
262'--------------------------------
263' ウィンドウメッセージ処理
264
265
[473]266'--------
267'イベント
268
269#include "ControlEvent.sbp"
270
271'--------------------------------
[544]272' インスタンスメンバ変数
[473]273Private
[542]274 hwnd As HWND
275 /*!
276 @brief マウスカーソルがクライアント領域に入っているかどうかのフラグ
277 外から中に入ってきたときにMouseEnterイベントを発生させるために用意している。
278 */
279 mouseEntered As Boolean
280 /*!
281 @brief ダブルクリックが起こったかどうかのフラグ
282 Click/MouseClickイベントのために用意している。
283 @date 2008/07/12
284 */
285 doubleClickFired As Boolean
[473]286
287'--------------------------------
[544]288' 初期ウィンドウクラス
[473]289Private
290 Static Function WndProcFirst(hwnd As HWND, msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
291 Imports System.Runtime.InteropServices
292
293 Dim rThis = Control.FromHWndCore(hwnd)
294 If IsNothing(rThis) Then
295 Dim gchValue = TlsGetValue(tlsIndex) As LONG_PTR
296 TlsSetValue(tlsIndex, 0)
297 If gchValue = 0 Then
298 Goto *InstanceIsNotFound
299 End If
300 Dim gch = GCHandle.FromIntPtr(gchValue)
301 rThis = gch.Target As Control
302 ' ウィンドウが作られて最初にWndProcFirstが呼ばれたとき
303
304 If IsNothing(rThis) Then
305 Goto *InstanceIsNotFound
306 End If
[542]307 rThis.hwnd = hwnd
308 SetProp(hwnd, PropertyInstance As ULONG_PTR As PCSTR, gchValue As HANDLE)
[473]309 End If
310 WndProcFirst = rThis.WndProc(msg, wp, lp)
311 If msg = WM_NCDESTROY Then
312 Dim gchValue = GetProp(hwnd, PropertyInstance As ULONG_PTR As PCTSTR) As ULONG_PTR
313 If gchValue <> 0 Then
314 Dim gch = GCHandle.FromIntPtr(gchValue)
315 gch.Free()
316 End If
317 End If
318
319 Exit Function
320
321 *InstanceIsNotFound
322 OutputDebugString("ActiveBasic.Windows.UI.Control.WndProcFirst: The attached instance is not found.")
323 WndProcFirst = DefWindowProc(hwnd, msg, wp, lp)
324 End Function
[542]325
[473]326' Static Const WM_CONTROL_INVOKE = WM_USER + 0 As DWord
327' Static Const WM_CONTROL_BEGININVOKE = WM_USER + 1 As DWord
328
329'--------------------------------
[542]330' その他の補助関数
331Private
332' Sub tracMouseEvent()
333/* If pTrackMouseEvent <> 0 Then
334 Dim tme As TRACKMOUSEEVENT
335 With tme
336 .cbSize = Len(tme)
337 .dwFlags = TME_HOVER Or TME_LEAVE
338 .hwndTrack = wnd
339 .dwHoverTime = HOVER_DEFAULT
340 End With
341 pTrackMouseEvent(tme)
342 End If
343*/ 'End Sub
344
345'--------------------------------
[544]346' 初期化終了関連(特にウィンドウクラス)
[542]347Private
[473]348 'ウィンドウ作成時にウィンドウプロシージャへThisを伝えるためのもの
349 Static tlsIndex As DWord
350
351 Static hInstance As HINSTANCE
352 Static atom As ATOM
[542]353 Static hmodComctl As HMODULE
354' Static pTrackMouseEvent As PTrackMouseEvent
[473]355
356 Static Const WindowClassName = "ActiveBasic.Windows.UI.Control"
357 Static Const PropertyInstance = 0 As ATOM
358Public
359 Static Sub Initialize(hinst As HINSTANCE)
360 tlsIndex = TlsAlloc()
361 hInstance = hinst
[542]362' hmodComctl = LoadLibrary("comctl32.dll")
363' pTrackMouseEvent = GetProcAddress(hmodComctl, ToMBStr("_TrackMouseEvent"))
[473]364
365 Dim PropertyInstanceString = WindowClassName + " " + Hex$(GetCurrentProcessId())
366 PropertyInstance = GlobalAddAtom(ToTCStr(PropertyInstanceString))
367
368 Dim wcx As WNDCLASSEX
369 With wcx
370 .cbSize = Len (wcx)
371 .style = CS_HREDRAW Or CS_VREDRAW Or CS_DBLCLKS
372 .lpfnWndProc = AddressOf (WndProcFirst)
373 .cbClsExtra = 0
374 .cbWndExtra = 0
375 .hInstance = hinst
376 .hIcon = 0
377 .hCursor = LoadImage(0, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE Or LR_SHARED) As HCURSOR
378 .hbrBackground = 0
379 .lpszMenuName = 0
380 .lpszClassName = ToTCStr(WindowClassName)
381 .hIconSm = 0
382 End With
383 atom = RegisterClassEx(wcx)
384 If atom = 0 Then
385 Dim buf[1023] As TCHAR
386 wsprintf(buf, Ex"ActiveBasic.Windows.UI.Control.Control: RegisterClasseEx failed. Error code: &h%08X\r\n", GetLastError())
387 OutputDebugString(buf)
388 Debug
389 ExitThread(0)
390 End If
391 End Sub
392
393 Static Sub Uninitialize()
[542]394 If atom <> 0 Then
395 UnregisterClass(atom As ULONG_PTR As PCSTR, hInstance)
396 End If
397 If tlsIndex <> 0 And tlsIndex <> &hffffffff Then
398 TlsFree(tlsIndex)
399 End If
400' If hmodComctl <> 0 Then
401' FreeLibrary(hmodComctl)
402' End If
403 If PropertyInstance <> 0 Then
404 GlobalDeleteAtom(PropertyInstance)
405 End If
[473]406 End Sub
407
408End Class
409
[542]410Class Form '仮
[473]411 Inherits Control
412Protected
413 Override Sub GetCreateStruct(ByRef cs As CREATESTRUCT)
414 With cs
415 .lpCreateParams = 0
416 '.hInstance
417 .hMenu = 0
418 .hwndParent = 0
419 .cy = CW_USEDEFAULT
420 .cx = CW_USEDEFAULT
421 .y = CW_USEDEFAULT
422 .x = CW_USEDEFAULT
423 .style = WS_OVERLAPPEDWINDOW
424 .lpszName = ""
425 '.lpszClass
426 .dwExStyle = 0
427 End With
428 End Sub
[542]429Public
430
[473]431 Override Function WndProc(msg As DWord, wp As WPARAM, lp As LPARAM) As LRESULT
432 WndProc = 0
433 Select Case msg
434 Case Else
435 WndProc = Super.WndProc(msg, wp, lp)
436 End Select
437 End Function
438End Class
439
440End Namespace 'UI
441End Namespace 'Widnows
442End Namespace 'ActiveBasic
443
444'----------
445'テスト実行用
446
[545]447Imports ActiveBasic.Windows.UI
[473]448
[542]449'OleInitialize()
450Control.Initialize(GetModuleHandle(0))
451
452Class MyForm
453 Inherits Form
[473]454Public
[545]455 Sub MyForm()
[544]456 Dim f = This
457 f.AddMessageEvent(WM_DESTROY, AddressOf (f.Destory))
458 f.AddPaintDC(AddressOf (f.Paint))
459 End Sub
460
461 Sub Destory(sender As Object, e As EventArgs)
462 OutputDebugString(Ex"Destory\r\n")
[542]463 PostQuitMessage(0)
464 End Sub
[544]465
466 Sub Paint(sender As Object, e As PaintDCEventArgs)
467 TextOut(e.Handle, 10, 10, "Hello world!", 12)
468 End Sub
[473]469End Class
470
[542]471Dim f = New MyForm
[473]472f.Create()
[542]473ShowWindow(f.Handle, SW_SHOW)
[473]474
[542]475Dim m As MSG
476Do
477 Dim ret = GetMessage(m, 0, 0, 0)
478 If ret = 0 Then
479 Exit Do
480 ElseIf ret = -1 Then
481 ExitProcess(-1)
482 End If
483
484 TranslateMessage(m)
485 DispatchMessage(m)
486Loop
487
488f = Nothing
489System.GC.Collect()
490
491Control.Uninitialize()
492'OleUninitialize()
493
494End
Note: See TracBrowser for help on using the repository browser.