ffi-wingui-core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,164 @@
1
+ require 'ffi-wingui-core'
2
+
3
+ exit if defined?(Ocra)
4
+
5
+ include WinGUI
6
+
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
+
9
+ CMD_ITEM1 = WM_APP + 1
10
+
11
+ WndExtra = Struct.new(
12
+ :hcm
13
+ ).send(:include, Util::Id2RefTracking)
14
+
15
+ def onCreate(hwnd,
16
+ cs
17
+ )
18
+ xtra = WndExtra::REFS[GetWindowLong(hwnd, GWL_USERDATA)]
19
+
20
+ xtra[:hcm] = CreatePopupMenu()
21
+ AppendMenu(xtra[:hcm], MF_STRING, CMD_ITEM1, L('Item&1'))
22
+
23
+ 0
24
+ end
25
+
26
+ def onDestroy(hwnd)
27
+ xtra = WndExtra::REFS[GetWindowLong(hwnd, GWL_USERDATA)]
28
+
29
+ DestroyMenu(xtra[:hcm])
30
+
31
+ PostQuitMessage(0); 0
32
+ end
33
+
34
+ def onContextMenu(hwnd,
35
+ x, y
36
+ )
37
+ xtra = WndExtra::REFS[GetWindowLong(hwnd, GWL_USERDATA)]
38
+
39
+ POINT.new { |point|
40
+ GetCursorPos(point)
41
+
42
+ x, y = point.values
43
+ } if x == -1
44
+
45
+ TrackPopupMenu(xtra[:hcm], TPM_RIGHTBUTTON, x, y, 0, hwnd, nil)
46
+
47
+ 0
48
+ end
49
+
50
+ def onItem1(verb,
51
+ hctl, hwnd
52
+ )
53
+ MessageBox(hwnd,
54
+ L(__method__.to_s),
55
+ APPNAME,
56
+ MB_ICONINFORMATION
57
+ )
58
+
59
+ 0
60
+ end
61
+
62
+ WindowProc = FFI::Function.new(:long,
63
+ [:pointer, :uint, :uint, :long],
64
+ convention: :stdcall
65
+ ) { |hwnd, uMsg, wParam, lParam|
66
+ begin
67
+ result = case uMsg
68
+ when WM_NCCREATE
69
+ DefWindowProc(hwnd, uMsg, wParam, lParam)
70
+
71
+ SetWindowLong(hwnd,
72
+ GWL_USERDATA,
73
+ CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams].to_i
74
+ )
75
+
76
+ 1
77
+ when WM_CREATE
78
+ onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
79
+ when WM_DESTROY
80
+ onDestroy(hwnd)
81
+
82
+ when WM_CONTEXTMENU
83
+ onContextMenu(hwnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
84
+ when WM_COMMAND
85
+ id, verb = LOWORD(wParam), HIWORD(wParam)
86
+ hctl = FFI::Pointer.new(lParam)
87
+
88
+ case id
89
+ when CMD_ITEM1
90
+ onItem1(verb, hctl, hwnd)
91
+ end
92
+ end
93
+
94
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
95
+ rescue
96
+ case MessageBox(hwnd,
97
+ L(Util.FormatException($!)),
98
+ APPNAME,
99
+ MB_ABORTRETRYIGNORE | MB_ICONERROR
100
+ )
101
+ when IDABORT
102
+ PostQuitMessage(2)
103
+ when IDRETRY
104
+ retry
105
+ end
106
+ end
107
+ }
108
+
109
+ def main
110
+ xtra = WndExtra.new
111
+
112
+ WNDCLASSEX.new { |wc|
113
+ wc[:cbSize] = wc.size
114
+ wc[:lpfnWndProc] = WindowProc
115
+ wc[:cbWndExtra] = FFI::Type::Builtin::POINTER.size
116
+ wc[:hInstance] = GetModuleHandle(nil)
117
+ wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
118
+ wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
119
+ wc[:hbrBackground] = FFI::Pointer.new(
120
+ ((WINVER == WINXP) ? COLOR_MENUBAR : COLOR_MENU) + 1
121
+ )
122
+
123
+ PWSTR(APPNAME) { |className|
124
+ wc[:lpszClassName] = className
125
+
126
+ DetonateLastError(0, :RegisterClassEx,
127
+ wc
128
+ )
129
+ }
130
+ }
131
+
132
+ hwnd = CreateWindowEx(
133
+ 0, APPNAME, APPNAME, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
134
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
135
+ nil, nil, GetModuleHandle(nil), FFI::Pointer.new(xtra.object_id)
136
+ )
137
+
138
+ raise "CreateWindowEx failed (last error: #{GetLastError()})" if
139
+ hwnd.null? && GetLastError() != 0
140
+
141
+ exit(0) if hwnd.null?
142
+
143
+ ShowWindow(hwnd, SW_SHOWNORMAL)
144
+ UpdateWindow(hwnd)
145
+
146
+ MSG.new { |msg|
147
+ until DetonateLastError(-1, :GetMessage,
148
+ msg, nil, 0, 0
149
+ ) == 0
150
+ TranslateMessage(msg)
151
+ DispatchMessage(msg)
152
+ end
153
+
154
+ exit(msg[:wParam])
155
+ }
156
+ rescue
157
+ MessageBox(hwnd,
158
+ L(Util.FormatException($!)),
159
+ APPNAME,
160
+ MB_ICONERROR
161
+ ); exit(1)
162
+ end
163
+
164
+ main
@@ -0,0 +1,326 @@
1
+ require 'ffi-wingui-core'
2
+
3
+ exit if defined?(Ocra)
4
+
5
+ include WinGUI
6
+
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
+
9
+ unless WINVER >= WINVISTA
10
+ MessageBox(nil,
11
+ L('This example requires Windows Vista or later'),
12
+ APPNAME,
13
+ MB_ICONERROR
14
+ ); exit(0)
15
+ end
16
+
17
+ CMD_ITEM1 = WM_APP + 1
18
+ CMD_ITEM2 = CMD_ITEM1 + 1
19
+ CMD_ITEM3 = CMD_ITEM2 + 1
20
+ CMD_ITEM4 = CMD_ITEM3 + 1
21
+ CMD_ITEM5 = CMD_ITEM4 + 1
22
+ CMD_ITEM6 = CMD_ITEM5 + 1
23
+ CMD_ITEM7 = CMD_ITEM6 + 1
24
+ CMD_ITEM8 = CMD_ITEM7 + 1
25
+ CMD_ITEM9 = CMD_ITEM8 + 1
26
+
27
+ WndExtra = Struct.new(
28
+ :hbmp
29
+ ).send(:include, Util::Id2RefTracking)
30
+
31
+ def onCreate(hwnd,
32
+ cs
33
+ )
34
+ xtra = WndExtra::REFS[GetWindowLong(hwnd, GWL_USERDATA)]
35
+
36
+ xtra[:hbmp] = DetonateLastError(FFI::Pointer::NULL, :LoadImage,
37
+ nil,
38
+ L("#{File.dirname(File.expand_path(__FILE__))}/res/face-devilish.bmp"),
39
+ IMAGE_BITMAP, 0, 0,
40
+ LR_LOADFROMFILE | LR_CREATEDIBSECTION
41
+ )
42
+
43
+ info = MENUITEMINFO.new
44
+
45
+ info[:cbSize] = info.size
46
+ info[:fMask] = MIIM_BITMAP
47
+ info[:hbmpItem] = xtra[:hbmp]
48
+
49
+ hbar = CreateMenu()
50
+ hmenu1 = CreatePopupMenu()
51
+ AppendMenu(hmenu1, MF_STRING, CMD_ITEM1, L('Item&1'))
52
+ SetMenuDefaultItem(hmenu1, CMD_ITEM1, 0)
53
+ SetMenuItemInfo(hmenu1, CMD_ITEM1, 0, info)
54
+
55
+ AppendMenu(hmenu1, MF_STRING | MF_GRAYED, CMD_ITEM2, L('Item&2'))
56
+ SetMenuItemInfo(hmenu1, CMD_ITEM2, 0, info)
57
+
58
+ AppendMenu(hmenu1, MF_STRING | MF_CHECKED, CMD_ITEM3, L('Item&3'))
59
+ SetMenuItemInfo(hmenu1, CMD_ITEM3, 0, info)
60
+
61
+ AppendMenu(hmenu1, MF_SEPARATOR, 0, nil)
62
+
63
+ AppendMenu(hmenu1, MF_STRING | MF_CHECKED | MFT_RADIOCHECK,
64
+ CMD_ITEM4, L('Item&4'))
65
+ SetMenuItemInfo(hmenu1, CMD_ITEM4, 0, info)
66
+
67
+ AppendMenu(hmenu1, MF_STRING, CMD_ITEM5, L('Item&5'))
68
+ SetMenuItemInfo(hmenu1, CMD_ITEM5, 0, info)
69
+
70
+ AppendMenu(hmenu1, MF_SEPARATOR, 0, nil)
71
+
72
+ hmenu2 = CreatePopupMenu()
73
+ AppendMenu(hmenu2, MF_STRING | MF_CHECKED | MFT_RADIOCHECK,
74
+ CMD_ITEM6, L('Item&6'))
75
+ SetMenuItemInfo(hmenu2, CMD_ITEM6, 0, info)
76
+
77
+ AppendMenu(hmenu2, MF_STRING, CMD_ITEM7, L('Item&7'))
78
+ SetMenuItemInfo(hmenu2, CMD_ITEM7, 0, info)
79
+ AppendMenu(hmenu1, MF_POPUP, hmenu2.to_i, L('Menu&2'))
80
+ SetMenuItemInfo(hmenu1, 7, MF_BYPOSITION, info)
81
+ AppendMenu(hbar, MF_POPUP, hmenu1.to_i, L('Menu&1'))
82
+ SetMenuItemInfo(hbar, 0, MF_BYPOSITION, info)
83
+
84
+ AppendMenu(hbar, MF_STRING, CMD_ITEM8, L('Item&8'))
85
+ SetMenuItemInfo(hbar, CMD_ITEM8, 0, info)
86
+
87
+ hmenu3 = CreatePopupMenu()
88
+ AppendMenu(hmenu3, MF_BITMAP, CMD_ITEM9, xtra[:hbmp])
89
+ AppendMenu(hbar, MF_POPUP | MF_BITMAP | MF_RIGHTJUSTIFY, hmenu3.to_i, xtra[:hbmp])
90
+ SetMenu(hwnd, hbar)
91
+
92
+ 0
93
+ ensure
94
+ info.pointer.free if info
95
+ end
96
+
97
+ def onDestroy(hwnd)
98
+ xtra = WndExtra::REFS[GetWindowLong(hwnd, GWL_USERDATA)]
99
+
100
+ DeleteObject(xtra[:hbmp])
101
+
102
+ PostQuitMessage(0); 0
103
+ end
104
+
105
+ def onItem1(verb,
106
+ hctl, hwnd
107
+ )
108
+ hbar = GetMenu(hwnd)
109
+ i2grayed = (GetMenuState(hbar, CMD_ITEM2, 0) & MF_GRAYED) == MF_GRAYED
110
+
111
+ EnableMenuItem(hbar, CMD_ITEM2, (i2grayed) ? MF_ENABLED : MF_GRAYED)
112
+
113
+ 0
114
+ end
115
+
116
+ def onItem2(verb,
117
+ hctl, hwnd
118
+ )
119
+ MessageBox(hwnd,
120
+ L(__method__.to_s),
121
+ APPNAME,
122
+ MB_ICONINFORMATION
123
+ )
124
+
125
+ 0
126
+ end
127
+
128
+ def onItem3(verb,
129
+ hctl, hwnd
130
+ )
131
+ hbar = GetMenu(hwnd)
132
+ i3checked = (GetMenuState(hbar, CMD_ITEM3, 0) & MF_CHECKED) == MF_CHECKED
133
+
134
+ CheckMenuItem(hbar, CMD_ITEM3, (i3checked) ? MF_UNCHECKED : MF_CHECKED)
135
+
136
+ 0
137
+ end
138
+
139
+ def onItem4(verb,
140
+ hctl, hwnd
141
+ )
142
+ CheckMenuRadioItem(GetMenu(hwnd), CMD_ITEM4, CMD_ITEM5, CMD_ITEM4, 0)
143
+
144
+ 0
145
+ end
146
+
147
+ def onItem5(verb,
148
+ hctl, hwnd
149
+ )
150
+ CheckMenuRadioItem(GetMenu(hwnd), CMD_ITEM4, CMD_ITEM5, CMD_ITEM5, 0)
151
+
152
+ 0
153
+ end
154
+
155
+ def onItem6(verb,
156
+ hctl, hwnd
157
+ )
158
+ CheckMenuRadioItem(GetMenu(hwnd), CMD_ITEM6, CMD_ITEM7, CMD_ITEM6, 0)
159
+
160
+ 0
161
+ end
162
+
163
+ def onItem7(verb,
164
+ hctl, hwnd
165
+ )
166
+ CheckMenuRadioItem(GetMenu(hwnd), CMD_ITEM6, CMD_ITEM7, CMD_ITEM7, 0)
167
+
168
+ 0
169
+ end
170
+
171
+ def onItem8(verb,
172
+ hctl, hwnd
173
+ )
174
+ MessageBox(hwnd,
175
+ L(__method__.to_s),
176
+ APPNAME,
177
+ MB_ICONINFORMATION
178
+ )
179
+
180
+ 0
181
+ end
182
+
183
+ def onItem9(verb,
184
+ hctl, hwnd
185
+ )
186
+ hbar = GetMenu(hwnd)
187
+ i2grayed = (GetMenuState(hbar, CMD_ITEM2, 0) & MF_GRAYED) == MF_GRAYED
188
+ i3checked = (GetMenuState(hbar, CMD_ITEM3, 0) & MF_CHECKED) == MF_CHECKED
189
+ i4checked = (GetMenuState(hbar, CMD_ITEM4, 0) & MF_CHECKED) == MF_CHECKED
190
+ i5checked = (GetMenuState(hbar, CMD_ITEM5, 0) & MF_CHECKED) == MF_CHECKED
191
+ i6checked = (GetMenuState(hbar, CMD_ITEM6, 0) & MF_CHECKED) == MF_CHECKED
192
+ i7checked = (GetMenuState(hbar, CMD_ITEM7, 0) & MF_CHECKED) == MF_CHECKED
193
+
194
+ MessageBox(hwnd,
195
+ L("
196
+ Item2 - #{(i2grayed) ? 'grayed' : 'enabled'}
197
+ Item3 - #{(i3checked) ? 'checked' : 'unchecked'}
198
+ Item4 - #{(i4checked) ? 'checked' : 'unchecked'}
199
+ Item5 - #{(i5checked) ? 'checked' : 'unchecked'}
200
+ Item6 - #{(i6checked) ? 'checked' : 'unchecked'}
201
+ Item7 - #{(i7checked) ? 'checked' : 'unchecked'}
202
+ "),
203
+ APPNAME,
204
+ MB_ICONINFORMATION
205
+ )
206
+
207
+ 0
208
+ end
209
+
210
+ WindowProc = FFI::Function.new(:long,
211
+ [:pointer, :uint, :uint, :long],
212
+ convention: :stdcall
213
+ ) { |hwnd, uMsg, wParam, lParam|
214
+ begin
215
+ result = case uMsg
216
+ when WM_NCCREATE
217
+ DefWindowProc(hwnd, uMsg, wParam, lParam)
218
+
219
+ SetWindowLong(hwnd,
220
+ GWL_USERDATA,
221
+ CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams].to_i
222
+ )
223
+
224
+ 1
225
+ when WM_CREATE
226
+ onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
227
+ when WM_DESTROY
228
+ onDestroy(hwnd)
229
+
230
+ when WM_COMMAND
231
+ id, verb = LOWORD(wParam), HIWORD(wParam)
232
+ hctl = FFI::Pointer.new(lParam)
233
+
234
+ case id
235
+ when CMD_ITEM1
236
+ onItem1(verb, hctl, hwnd)
237
+ when CMD_ITEM2
238
+ onItem2(verb, hctl, hwnd)
239
+ when CMD_ITEM3
240
+ onItem3(verb, hctl, hwnd)
241
+ when CMD_ITEM4
242
+ onItem4(verb, hctl, hwnd)
243
+ when CMD_ITEM5
244
+ onItem5(verb, hctl, hwnd)
245
+ when CMD_ITEM6
246
+ onItem6(verb, hctl, hwnd)
247
+ when CMD_ITEM7
248
+ onItem7(verb, hctl, hwnd)
249
+ when CMD_ITEM8
250
+ onItem8(verb, hctl, hwnd)
251
+ when CMD_ITEM9
252
+ onItem9(verb, hctl, hwnd)
253
+ end
254
+ end
255
+
256
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
257
+ rescue
258
+ case MessageBox(hwnd,
259
+ L(Util.FormatException($!)),
260
+ APPNAME,
261
+ MB_ABORTRETRYIGNORE | MB_ICONERROR
262
+ )
263
+ when IDABORT
264
+ PostQuitMessage(2)
265
+ when IDRETRY
266
+ retry
267
+ end
268
+ end
269
+ }
270
+
271
+ def main
272
+ xtra = WndExtra.new
273
+
274
+ WNDCLASSEX.new { |wc|
275
+ wc[:cbSize] = wc.size
276
+ wc[:lpfnWndProc] = WindowProc
277
+ wc[:cbWndExtra] = FFI::Type::Builtin::POINTER.size
278
+ wc[:hInstance] = GetModuleHandle(nil)
279
+ wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
280
+ wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
281
+ wc[:hbrBackground] = FFI::Pointer.new(
282
+ ((WINVER == WINXP) ? COLOR_MENUBAR : COLOR_MENU) + 1
283
+ )
284
+
285
+ PWSTR(APPNAME) { |className|
286
+ wc[:lpszClassName] = className
287
+
288
+ DetonateLastError(0, :RegisterClassEx,
289
+ wc
290
+ )
291
+ }
292
+ }
293
+
294
+ hwnd = CreateWindowEx(
295
+ 0, APPNAME, APPNAME, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
296
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
297
+ nil, nil, GetModuleHandle(nil), FFI::Pointer.new(xtra.object_id)
298
+ )
299
+
300
+ raise "CreateWindowEx failed (last error: #{GetLastError()})" if
301
+ hwnd.null? && GetLastError() != 0
302
+
303
+ exit(0) if hwnd.null?
304
+
305
+ ShowWindow(hwnd, SW_SHOWNORMAL)
306
+ UpdateWindow(hwnd)
307
+
308
+ MSG.new { |msg|
309
+ until DetonateLastError(-1, :GetMessage,
310
+ msg, nil, 0, 0
311
+ ) == 0
312
+ TranslateMessage(msg)
313
+ DispatchMessage(msg)
314
+ end
315
+
316
+ exit(msg[:wParam])
317
+ }
318
+ rescue
319
+ MessageBox(hwnd,
320
+ L(Util.FormatException($!)),
321
+ APPNAME,
322
+ MB_ICONERROR
323
+ ); exit(1)
324
+ end
325
+
326
+ main