ffi-wingui-core 0.1.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,1019 @@
1
+ require 'ffi'
2
+
3
+ module WinGUI
4
+ extend FFI::Library
5
+
6
+ INVALID_HANDLE_VALUE = FFI::Pointer.new(-1)
7
+
8
+ def MAKEWORD(low, high)
9
+ (low & 0xff) | ((high & 0xff) << 8)
10
+ end
11
+
12
+ def LOBYTE(w)
13
+ w & 0xff
14
+ end
15
+
16
+ def HIBYTE(w)
17
+ (w >> 8) & 0xff
18
+ end
19
+
20
+ def MAKELONG(low, high)
21
+ (low & 0xffff) | ((high & 0xffff) << 16)
22
+ end
23
+
24
+ def LOWORD(l)
25
+ l & 0xffff
26
+ end
27
+
28
+ def HIWORD(l)
29
+ (l >> 16) & 0xffff
30
+ end
31
+
32
+ module_function \
33
+ :MAKEWORD, :LOBYTE, :HIBYTE,
34
+ :MAKELONG, :LOWORD, :HIWORD
35
+
36
+ class POINT < FFI::Struct
37
+ layout \
38
+ :x, :long,
39
+ :y, :long
40
+ end
41
+
42
+ class SIZE < FFI::Struct
43
+ layout \
44
+ :cx, :long,
45
+ :cy, :long
46
+ end
47
+
48
+ class RECT < FFI::Struct
49
+ layout \
50
+ :left, :long,
51
+ :top, :long,
52
+ :right, :long,
53
+ :bottom, :long
54
+ end
55
+
56
+ ffi_lib 'kernel32'
57
+ ffi_convention :stdcall
58
+
59
+ attach_function :SetLastError, [
60
+ :ulong
61
+ ], :void
62
+
63
+ attach_function :GetLastError, [
64
+
65
+ ], :ulong
66
+
67
+ def Detonate(on, name, *args)
68
+ raise "#{name} failed" if
69
+ (failed = [*on].include?(result = send(name, *args)))
70
+
71
+ result
72
+ ensure
73
+ yield failed if block_given?
74
+ end
75
+
76
+ def DetonateLastError(on, name, *args)
77
+ raise "#{name} failed (last error: #{GetLastError()})" if
78
+ (failed = [*on].include?(result = send(name, *args)))
79
+
80
+ result
81
+ ensure
82
+ yield failed if block_given?
83
+ end
84
+
85
+ module_function :Detonate, :DetonateLastError
86
+
87
+ class OSVERSIONINFOEX < FFI::Struct
88
+ layout \
89
+ :dwOSVersionInfoSize, :ulong,
90
+ :dwMajorVersion, :ulong,
91
+ :dwMinorVersion, :ulong,
92
+ :dwBuildNumber, :ulong,
93
+ :dwPlatformId, :ulong,
94
+ :szCSDVersion, [:char, 128],
95
+ :wServicePackMajor, :ushort,
96
+ :wServicePackMinor, :ushort,
97
+ :wSuiteMask, :ushort,
98
+ :wProductType, :uchar,
99
+ :wReserved, :uchar
100
+ end
101
+
102
+ attach_function :GetVersionEx, :GetVersionExA, [
103
+ :pointer
104
+ ], :int
105
+
106
+ VERSION = OSVERSIONINFOEX.new.tap { |ovi|
107
+ ovi[:dwOSVersionInfoSize] = ovi.size
108
+
109
+ DetonateLastError(0, :GetVersionEx,
110
+ ovi
111
+ )
112
+ }
113
+
114
+ #{ NTDDI_xxx
115
+ NTDDI_WIN2K = 0x05000000
116
+
117
+ NTDDI_WIN2KSP1 = 0x05000100
118
+ NTDDI_WIN2KSP2 = 0x05000200
119
+ NTDDI_WIN2KSP3 = 0x05000300
120
+ NTDDI_WIN2KSP4 = 0x05000400
121
+
122
+ NTDDI_WINXP = 0x05010000
123
+
124
+ NTDDI_WINXPSP1 = 0x05010100
125
+ NTDDI_WINXPSP2 = 0x05010200
126
+ NTDDI_WINXPSP3 = 0x05010300
127
+ NTDDI_WINXPSP4 = 0x05010400
128
+
129
+ NTDDI_WS03 = 0x05020000
130
+
131
+ NTDDI_WS03SP1 = 0x05020100
132
+ NTDDI_WS03SP2 = 0x05020200
133
+ NTDDI_WS03SP3 = 0x05020300
134
+ NTDDI_WS03SP4 = 0x05020400
135
+
136
+ NTDDI_VISTA = 0x06000000
137
+
138
+ NTDDI_VISTASP1 = 0x06000100
139
+ NTDDI_VISTASP2 = 0x06000200
140
+ NTDDI_VISTASP3 = 0x06000300
141
+ NTDDI_VISTASP4 = 0x06000400
142
+
143
+ NTDDI_WS08 = NTDDI_VISTASP1
144
+
145
+ NTDDI_WS08SP2 = NTDDI_VISTASP2
146
+ NTDDI_WS08SP3 = NTDDI_VISTASP3
147
+ NTDDI_WS08SP4 = NTDDI_VISTASP4
148
+
149
+ NTDDI_WIN7 = 0x06010000
150
+ #}
151
+
152
+ NTDDI_VERSION = MAKELONG(
153
+ MAKEWORD(VERSION[:wServicePackMinor], VERSION[:wServicePackMajor]),
154
+ MAKEWORD(VERSION[:dwMinorVersion], VERSION[:dwMajorVersion])
155
+ )
156
+
157
+ #{ WINxxx
158
+ WIN2K = 0x0500
159
+ WINXP = 0x0501
160
+ WINVISTA = 0x0600
161
+ WIN7 = 0x0601
162
+ #}
163
+
164
+ WINVER = HIWORD(NTDDI_VERSION)
165
+
166
+ attach_function :GetModuleHandle, :GetModuleHandleA, [
167
+ :string
168
+ ], :pointer
169
+
170
+ attach_function :LoadLibrary, :LoadLibraryA, [
171
+ :string
172
+ ], :pointer
173
+
174
+ attach_function :FreeLibrary, [
175
+ :pointer
176
+ ], :int
177
+
178
+ if WINVER >= WINXP
179
+ class ACTCTX < FFI::Struct
180
+ layout \
181
+ :cbSize, :ulong,
182
+ :dwFlags, :ulong,
183
+ :lpSource, :pointer,
184
+ :wProcessorArchitecture, :ushort,
185
+ :wLangId, :ushort,
186
+ :lpAssemblyDirectory, :pointer,
187
+ :lpResourceName, :pointer,
188
+ :lpApplicationName, :pointer,
189
+ :hModule, :pointer
190
+ end
191
+
192
+ attach_function :CreateActCtx, :CreateActCtxA, [
193
+ :pointer
194
+ ], :pointer
195
+
196
+ attach_function :ReleaseActCtx, [
197
+ :pointer
198
+ ], :void
199
+
200
+ attach_function :ActivateActCtx, [
201
+ :pointer,
202
+ :pointer
203
+ ], :int
204
+
205
+ attach_function :DeactivateActCtx, [
206
+ :ulong,
207
+ :ulong
208
+ ], :int
209
+
210
+ COMMON_CONTROLS_ACTCTX = {
211
+ handle: INVALID_HANDLE_VALUE,
212
+ cookie: FFI::MemoryPointer.new(:ulong),
213
+ activated: false
214
+ }
215
+
216
+ at_exit {
217
+ DeactivateActCtx(0, COMMON_CONTROLS_ACTCTX[:cookie].get_ulong(0)) if
218
+ COMMON_CONTROLS_ACTCTX[:activated]
219
+
220
+ ReleaseActCtx(COMMON_CONTROLS_ACTCTX[:handle]) unless
221
+ COMMON_CONTROLS_ACTCTX[:handle] == INVALID_HANDLE_VALUE
222
+
223
+ COMMON_CONTROLS_ACTCTX[:cookie].free
224
+ }
225
+ end
226
+
227
+ def EnableVisualStyles
228
+ return unless WINVER >= WINXP
229
+
230
+ raise 'Visual styles already enabled' if
231
+ COMMON_CONTROLS_ACTCTX[:activated]
232
+
233
+ manifest = "#{ENV['TEMP']}/Microsoft.Windows.Common-Controls.manifest"
234
+
235
+ File.open(manifest, 'w:utf-8') { |file|
236
+ file << <<-XML
237
+ <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
238
+ <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
239
+ <dependency>
240
+ <dependentAssembly>
241
+ <assemblyIdentity
242
+ type='Win32'
243
+ name='Microsoft.Windows.Common-Controls'
244
+ version='6.0.0.0'
245
+ processorArchitecture='*'
246
+ publicKeyToken='6595b64144ccf1df'
247
+ language='*'
248
+ />
249
+ </dependentAssembly>
250
+ </dependency>
251
+ </assembly>
252
+ XML
253
+ }
254
+
255
+ ac = ACTCTX.new
256
+
257
+ ac[:cbSize] = ac.size
258
+ ac[:lpSource] = source = FFI::MemoryPointer.from_string(
259
+ File.expand_path(manifest)
260
+ )
261
+
262
+ COMMON_CONTROLS_ACTCTX[:handle] =
263
+ DetonateLastError(INVALID_HANDLE_VALUE, :CreateActCtx,
264
+ ac
265
+ ) { source.free }
266
+
267
+ DetonateLastError(0, :ActivateActCtx,
268
+ COMMON_CONTROLS_ACTCTX[:handle], COMMON_CONTROLS_ACTCTX[:cookie]
269
+ ) { |failed|
270
+ next unless failed
271
+
272
+ ReleaseActCtx(COMMON_CONTROLS_ACTCTX[:handle])
273
+ COMMON_CONTROLS_ACTCTX[:handle] = INVALID_HANDLE_VALUE
274
+ }
275
+
276
+ COMMON_CONTROLS_ACTCTX[:activated] = true
277
+ end
278
+
279
+ module_function :EnableVisualStyles
280
+
281
+ ffi_lib 'gdi32'
282
+ ffi_convention :stdcall
283
+
284
+ def RGB(r, g, b)
285
+ r | (g << 8) | (b << 16)
286
+ end
287
+
288
+ def GetRValue(rgb)
289
+ LOBYTE(rgb)
290
+ end
291
+
292
+ def GetGValue(rgb)
293
+ LOBYTE(rgb >> 8)
294
+ end
295
+
296
+ def GetBValue(rgb)
297
+ LOBYTE(rgb >> 16)
298
+ end
299
+
300
+ module_function \
301
+ :RGB, :GetRValue, :GetGValue, :GetBValue
302
+
303
+ class LOGFONT < FFI::Struct
304
+ layout \
305
+ :lfHeight, :long,
306
+ :lfWidth, :long,
307
+ :lfEscapement, :long,
308
+ :lfOrientation, :long,
309
+ :lfWeight, :long,
310
+ :lfItalic, :uchar,
311
+ :lfUnderline, :uchar,
312
+ :lfStrikeOut, :uchar,
313
+ :lfCharSet, :uchar,
314
+ :lfOutPrecision, :uchar,
315
+ :lfClipPrecision, :uchar,
316
+ :lfQuality, :uchar,
317
+ :lfPitchAndFamily, :uchar,
318
+ :lfFaceName, [:char, 32]
319
+ end
320
+
321
+ attach_function :CreateFontIndirect, :CreateFontIndirectA, [
322
+ :pointer
323
+ ], :pointer
324
+
325
+ attach_function :DeleteObject, [
326
+ :pointer
327
+ ], :int
328
+
329
+ attach_function :SelectObject, [
330
+ :pointer,
331
+ :pointer
332
+ ], :pointer
333
+
334
+ attach_function :SetBkColor, [
335
+ :pointer,
336
+ :ulong
337
+ ], :ulong
338
+
339
+ attach_function :GetBkColor, [
340
+ :pointer
341
+ ], :ulong
342
+
343
+ attach_function :SetTextColor, [
344
+ :pointer,
345
+ :ulong
346
+ ], :ulong
347
+
348
+ attach_function :GetTextColor, [
349
+ :pointer
350
+ ], :ulong
351
+
352
+ attach_function :MoveToEx, [
353
+ :pointer,
354
+ :int,
355
+ :int,
356
+ :pointer
357
+ ], :int
358
+
359
+ attach_function :LineTo, [
360
+ :pointer,
361
+ :int,
362
+ :int
363
+ ], :int
364
+
365
+ ffi_lib 'user32'
366
+ ffi_convention :stdcall
367
+
368
+ #{ MB_xxx
369
+ MB_OK = 0x00000000
370
+ MB_OKCANCEL = 0x00000001
371
+ MB_YESNO = 0x00000004
372
+ MB_YESNOCANCEL = 0x00000003
373
+ MB_RETRYCANCEL = 0x00000005
374
+ MB_ABORTRETRYIGNORE = 0x00000002
375
+ MB_CANCELTRYCONTINUE = 0x00000006
376
+ MB_HELP = 0x00004000
377
+
378
+ MB_ICONINFORMATION = 0x00000040
379
+ MB_ICONWARNING = 0x00000030
380
+ MB_ICONERROR = 0x00000010
381
+ MB_ICONQUESTION = 0x00000020
382
+
383
+ MB_DEFBUTTON1 = 0x00000000
384
+ MB_DEFBUTTON2 = 0x00000100
385
+ MB_DEFBUTTON3 = 0x00000200
386
+ MB_DEFBUTTON4 = 0x00000300
387
+
388
+ MB_APPLMODAL = 0x00000000
389
+ MB_TASKMODAL = 0x00002000
390
+ MB_SYSTEMMODAL = 0x00001000
391
+ #}
392
+
393
+ #{ IDxxx
394
+ IDOK = 1
395
+ IDCANCEL = 2
396
+ IDYES = 6
397
+ IDNO = 7
398
+ IDABORT = 3
399
+ IDRETRY = 4
400
+ IDIGNORE = 5
401
+ IDTRYAGAIN = 10
402
+ IDCONTINUE = 11
403
+ #}
404
+
405
+ attach_function :MessageBox, :MessageBoxA, [
406
+ :pointer,
407
+ :string,
408
+ :string,
409
+ :uint
410
+ ], :int
411
+
412
+ #{ CS_xxx
413
+ CS_DBLCLKS = 0x0008
414
+ CS_HREDRAW = 0x0002
415
+ CS_VREDRAW = 0x0001
416
+ CS_PARENTDC = 0x0080
417
+ CS_CLASSDC = 0x0040
418
+ CS_OWNDC = 0x0020
419
+ CS_SAVEBITS = 0x0800
420
+ CS_NOCLOSE = 0x0200
421
+ if WINVER >= WINXP
422
+ CS_DROPSHADOW = 0x00020000
423
+ end
424
+ #}
425
+
426
+ callback :WNDPROC, [
427
+ :pointer,
428
+ :uint,
429
+ :uint,
430
+ :long
431
+ ], :long
432
+
433
+ attach_function :DefWindowProc, :DefWindowProcA, [
434
+ :pointer,
435
+ :uint,
436
+ :uint,
437
+ :long
438
+ ], :long
439
+
440
+ #{ IDI_xxx
441
+ IDI_APPLICATION = FFI::Pointer.new(32512)
442
+ #}
443
+
444
+ attach_function :LoadIcon, :LoadIconA, [
445
+ :pointer,
446
+ :pointer
447
+ ], :pointer
448
+
449
+ #{ IDC_xxx
450
+ IDC_ARROW = FFI::Pointer.new(32512)
451
+ IDC_WAIT = FFI::Pointer.new(32514)
452
+ IDC_APPSTARTING = FFI::Pointer.new(32650)
453
+ IDC_HAND = FFI::Pointer.new(32649)
454
+ IDC_SIZEALL = FFI::Pointer.new(32646)
455
+ IDC_SIZENS = FFI::Pointer.new(32645)
456
+ IDC_SIZEWE = FFI::Pointer.new(32644)
457
+ IDC_SIZENWSE = FFI::Pointer.new(32642)
458
+ IDC_SIZENESW = FFI::Pointer.new(32643)
459
+ #}
460
+
461
+ attach_function :LoadCursor, :LoadCursorA, [
462
+ :pointer,
463
+ :pointer
464
+ ], :pointer
465
+
466
+ #{ COLOR/CTLCOLOR_xxx
467
+ COLOR_DESKTOP = 1
468
+ COLOR_APPWORKSPACE = 12
469
+ COLOR_WINDOW = 5
470
+ CTLCOLOR_DLG = 4
471
+ #}
472
+
473
+ class WNDCLASSEX < FFI::Struct
474
+ layout \
475
+ :cbSize, :uint,
476
+ :style, :uint,
477
+ :lpfnWndProc, :WNDPROC,
478
+ :cbClsExtra, :int,
479
+ :cbWndExtra, :int,
480
+ :hInstance, :pointer,
481
+ :hIcon, :pointer,
482
+ :hCursor, :pointer,
483
+ :hbrBackground, :pointer,
484
+ :lpszMenuName, :pointer,
485
+ :lpszClassName, :pointer,
486
+ :hIconSm, :pointer
487
+ end
488
+
489
+ attach_function :RegisterClassEx, :RegisterClassExA, [
490
+ :pointer
491
+ ], :ushort
492
+
493
+ attach_function :UnregisterClass, :UnregisterClassA, [
494
+ :pointer,
495
+ :pointer
496
+ ], :int
497
+
498
+ attach_function :GetClassInfoEx, :GetClassInfoExA, [
499
+ :pointer,
500
+ :pointer,
501
+ :pointer
502
+ ], :int
503
+
504
+ #{ WS_xxx
505
+ WS_BORDER = 0x00800000
506
+ WS_DLGFRAME = 0x00400000
507
+ WS_CAPTION = 0x00C00000
508
+ WS_SYSMENU = 0x00080000
509
+ WS_THICKFRAME = 0x00040000
510
+ WS_MINIMIZEBOX = 0x00020000
511
+ WS_MAXIMIZEBOX = 0x00010000
512
+ WS_HSCROLL = 0x00100000
513
+ WS_VSCROLL = 0x00200000
514
+ WS_DISABLED = 0x08000000
515
+ WS_VISIBLE = 0x10000000
516
+ WS_MINIMIZE = 0x20000000
517
+ WS_MAXIMIZE = 0x01000000
518
+ WS_CLIPCHILDREN = 0x02000000
519
+ WS_CLIPSIBLINGS = 0x04000000
520
+ WS_GROUP = 0x00020000
521
+ WS_TABSTOP = 0x00010000
522
+
523
+ WS_OVERLAPPED = 0x00000000
524
+ WS_OVERLAPPEDWINDOW = WS_OVERLAPPED |
525
+ WS_CAPTION | WS_SYSMENU |
526
+ WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
527
+
528
+ WS_POPUP = 0x80000000
529
+ WS_POPUPWINDOW = WS_POPUP |
530
+ WS_BORDER | WS_SYSMENU
531
+
532
+ WS_CHILD = 0x40000000
533
+ WS_CHILDWINDOW = WS_CHILD
534
+ #}
535
+
536
+ #{ CW_xxx
537
+ CW_USEDEFAULT = -0x80000000
538
+ #}
539
+
540
+ #{ HWND_xxx
541
+ HWND_DESKTOP = FFI::Pointer.new(0)
542
+ HWND_MESSAGE = FFI::Pointer.new(-3)
543
+ #}
544
+
545
+ attach_function :CreateWindowEx, :CreateWindowExA, [
546
+ :ulong,
547
+ :string,
548
+ :string,
549
+ :ulong,
550
+ :int,
551
+ :int,
552
+ :int,
553
+ :int,
554
+ :pointer,
555
+ :pointer,
556
+ :pointer,
557
+ :pointer
558
+ ], :pointer
559
+
560
+ attach_function :DestroyWindow, [
561
+ :pointer
562
+ ], :int
563
+
564
+ #{ GCL/GCW_xxx
565
+ GCL_STYLE = -26
566
+ GCL_WNDPROC = -24
567
+ GCL_CBCLSEXTRA = -20
568
+ GCL_CBWNDEXTRA = -18
569
+ GCL_HMODULE = -16
570
+ GCL_HICON = -14
571
+ GCL_HCURSOR = -12
572
+ GCL_HBRBACKGROUND = -10
573
+ GCL_MENUNAME = -8
574
+ GCL_HICONSM = -34
575
+ GCW_ATOM = -32
576
+ #}
577
+
578
+ attach_function :SetClassLong, :SetClassLongA, [
579
+ :pointer,
580
+ :int,
581
+ :long
582
+ ], :ulong
583
+
584
+ attach_function :GetClassLong, :GetClassLongA, [
585
+ :pointer,
586
+ :int
587
+ ], :ulong
588
+
589
+ attach_function :GetClassName, :GetClassNameA, [
590
+ :pointer,
591
+ :pointer,
592
+ :int
593
+ ], :int
594
+
595
+ #{ GWL_xxx
596
+ GWL_EXSTYLE = -20
597
+ GWL_STYLE = -16
598
+ GWL_HWNDPARENT = -8
599
+ GWL_ID = -12
600
+ GWL_HINSTANCE = -6
601
+ GWL_USERDATA = -21
602
+ GWL_WNDPROC = -4
603
+ #}
604
+
605
+ attach_function :SetWindowLong, :SetWindowLongA, [
606
+ :pointer,
607
+ :int,
608
+ :long
609
+ ], :long
610
+
611
+ attach_function :GetWindowLong, :GetWindowLongA, [
612
+ :pointer,
613
+ :int
614
+ ], :long
615
+
616
+ attach_function :IsWindowEnabled, [
617
+ :pointer
618
+ ], :int
619
+
620
+ attach_function :EnableWindow, [
621
+ :pointer,
622
+ :int
623
+ ], :int
624
+
625
+ attach_function :IsWindowVisible, [
626
+ :pointer
627
+ ], :int
628
+
629
+ #{ SW_xxx
630
+ SW_HIDE = 0
631
+ SW_SHOW = 5
632
+ SW_SHOWNA = 8
633
+ SW_SHOWNORMAL = 1
634
+ SW_SHOWNOACTIVATE = 4
635
+ SW_SHOWMINIMIZED = 2
636
+ SW_SHOWMINNOACTIVE = 7
637
+ SW_SHOWMAXIMIZED = 3
638
+ SW_RESTORE = 9
639
+ #}
640
+
641
+ attach_function :ShowWindow, [
642
+ :pointer,
643
+ :int
644
+ ], :int
645
+
646
+ #{ HWND_xxx
647
+ HWND_TOP = FFI::Pointer.new(0)
648
+ HWND_BOTTOM = FFI::Pointer.new(1)
649
+ HWND_TOPMOST = FFI::Pointer.new(-1)
650
+ HWND_NOTOPMOST = FFI::Pointer.new(-2)
651
+ #}
652
+
653
+ #{ SWP_xxx
654
+ SWP_NOSIZE = 0x0001
655
+ SWP_NOMOVE = 0x0002
656
+ SWP_NOZORDER = 0x0004
657
+ SWP_NOREDRAW = 0x0008
658
+ SWP_NOACTIVATE = 0x0010
659
+ SWP_FRAMECHANGED = 0x0020
660
+ SWP_SHOWWINDOW = 0x0040
661
+ SWP_HIDEWINDOW = 0x0080
662
+ SWP_NOCOPYBITS = 0x0100
663
+ SWP_NOOWNERZORDER = 0x0200
664
+ SWP_NOSENDCHANGING = 0x0400
665
+ SWP_DRAWFRAME = SWP_FRAMECHANGED
666
+ SWP_NOREPOSITION = SWP_NOOWNERZORDER
667
+ SWP_DEFERERASE = 0x2000
668
+ SWP_ASYNCWINDOWPOS = 0x4000
669
+ #}
670
+
671
+ attach_function :SetWindowPos, [
672
+ :pointer,
673
+ :pointer,
674
+ :int,
675
+ :int,
676
+ :int,
677
+ :int,
678
+ :uint
679
+ ], :int
680
+
681
+ attach_function :BeginDeferWindowPos, [
682
+ :int
683
+ ], :pointer
684
+
685
+ attach_function :DeferWindowPos, [
686
+ :pointer,
687
+ :pointer,
688
+ :pointer,
689
+ :int,
690
+ :int,
691
+ :int,
692
+ :int,
693
+ :uint
694
+ ], :pointer
695
+
696
+ attach_function :EndDeferWindowPos, [
697
+ :pointer
698
+ ], :int
699
+
700
+ attach_function :GetWindowRect, [
701
+ :pointer,
702
+ :pointer
703
+ ], :int
704
+
705
+ attach_function :GetClientRect, [
706
+ :pointer,
707
+ :pointer
708
+ ], :int
709
+
710
+ attach_function :GetCursorPos, [
711
+ :pointer
712
+ ], :int
713
+
714
+ attach_function :ScreenToClient, [
715
+ :pointer,
716
+ :pointer
717
+ ], :int
718
+
719
+ attach_function :ClientToScreen, [
720
+ :pointer,
721
+ :pointer
722
+ ], :int
723
+
724
+ attach_function :InvalidateRect, [
725
+ :pointer,
726
+ :pointer,
727
+ :int
728
+ ], :int
729
+
730
+ attach_function :UpdateWindow, [
731
+ :pointer
732
+ ], :int
733
+
734
+ class PAINTSTRUCT < FFI::Struct
735
+ layout \
736
+ :hdc, :pointer,
737
+ :fErase, :int,
738
+ :rcPaint, RECT,
739
+ :fRestore, :int,
740
+ :fIncUpdate, :int,
741
+ :rgbReserved, [:uchar, 32]
742
+ end
743
+
744
+ attach_function :BeginPaint, [
745
+ :pointer,
746
+ :pointer
747
+ ], :pointer
748
+
749
+ attach_function :EndPaint, [
750
+ :pointer,
751
+ :pointer
752
+ ], :int
753
+
754
+ attach_function :SetMenu, [
755
+ :pointer,
756
+ :pointer
757
+ ], :int
758
+
759
+ attach_function :GetMenu, [
760
+ :pointer
761
+ ], :pointer
762
+
763
+ attach_function :DrawMenuBar, [
764
+ :pointer
765
+ ], :int
766
+
767
+ attach_function :GetDlgItem, [
768
+ :pointer,
769
+ :int
770
+ ], :pointer
771
+
772
+ #{ HWND_xxx
773
+ HWND_BROADCAST = FFI::Pointer.new(0xffff)
774
+ #}
775
+
776
+ #{ WM_xxx
777
+ class CREATESTRUCT < FFI::Struct
778
+ layout \
779
+ :lpCreateParams, :pointer,
780
+ :hInstance, :pointer,
781
+ :hMenu, :pointer,
782
+ :hwndParent, :pointer,
783
+ :cy, :int,
784
+ :cx, :int,
785
+ :y, :int,
786
+ :x, :int,
787
+ :style, :long,
788
+ :lpszName, :pointer,
789
+ :lpszClass, :pointer,
790
+ :dwExStyle, :ulong
791
+ end
792
+
793
+ WM_NCCREATE = 0x0081
794
+ WM_CREATE = 0x0001
795
+
796
+ WM_CLOSE = 0x0010
797
+
798
+ WM_DESTROY = 0x0002
799
+ WM_NCDESTROY = 0x0082
800
+
801
+ WM_SETFONT = 0x0030
802
+ WM_GETFONT = 0x0031
803
+
804
+ WM_PAINT = 0x000F
805
+
806
+ WM_LBUTTONDOWN = 0x0201
807
+ WM_LBUTTONUP = 0x0202
808
+ WM_LBUTTONDBLCLK = 0x0203
809
+ WM_RBUTTONDOWN = 0x0204
810
+ WM_RBUTTONUP = 0x0205
811
+ WM_RBUTTONDBLCLK = 0x0206
812
+ WM_MBUTTONDOWN = 0x0207
813
+ WM_MBUTTONUP = 0x0208
814
+ WM_MBUTTONDBLCLK = 0x0209
815
+ WM_MOUSEMOVE = 0x0200
816
+
817
+ WM_COMMAND = 0x0111
818
+
819
+ class NMHDR < FFI::Struct
820
+ layout \
821
+ :hwndFrom, :pointer,
822
+ :idFrom, :uint,
823
+ :code, :uint
824
+ end
825
+
826
+ WM_NOTIFY = 0x004E
827
+
828
+ WM_APP = 0x8000
829
+ #}
830
+
831
+ attach_function :SendMessage, :SendMessageA, [
832
+ :pointer,
833
+ :uint,
834
+ :uint,
835
+ :long
836
+ ], :long
837
+
838
+ attach_function :PostMessage, :PostMessageA, [
839
+ :pointer,
840
+ :uint,
841
+ :uint,
842
+ :long
843
+ ], :int
844
+
845
+ class MSG < FFI::Struct
846
+ layout \
847
+ :hwnd, :pointer,
848
+ :message, :uint,
849
+ :wParam, :uint,
850
+ :lParam, :long,
851
+ :time, :ulong,
852
+ :pt, POINT
853
+ end
854
+
855
+ attach_function :GetMessage, :GetMessageA, [
856
+ :pointer,
857
+ :pointer,
858
+ :uint,
859
+ :uint
860
+ ], :int
861
+
862
+ attach_function :IsDialogMessage, [
863
+ :pointer,
864
+ :pointer
865
+ ], :int
866
+
867
+ attach_function :TranslateAccelerator, :TranslateAcceleratorA, [
868
+ :pointer,
869
+ :pointer,
870
+ :pointer
871
+ ], :int
872
+
873
+ attach_function :TranslateMessage, [
874
+ :pointer
875
+ ], :int
876
+
877
+ attach_function :DispatchMessage, :DispatchMessageA, [
878
+ :pointer
879
+ ], :long
880
+
881
+ attach_function :PostQuitMessage, [
882
+ :int
883
+ ], :void
884
+
885
+ attach_function :CreateMenu, [
886
+
887
+ ], :pointer
888
+
889
+ attach_function :CreatePopupMenu, [
890
+
891
+ ], :pointer
892
+
893
+ attach_function :DestroyMenu, [
894
+ :pointer
895
+ ], :int
896
+
897
+ #{ MF/MFT_xxx
898
+ MF_POPUP = 0x00000010
899
+ MF_STRING = 0x00000000
900
+ MF_BITMAP = 0x00000004
901
+ MF_OWNERDRAW = 0x00000100
902
+ MF_SEPARATOR = 0x00000800
903
+ MF_MENUBARBREAK = 0x00000020
904
+ MF_MENUBREAK = 0x00000040
905
+ MF_RIGHTJUSTIFY = 0x00004000
906
+ MF_ENABLED = 0x00000000
907
+ MF_DISABLED = 0x00000002
908
+ MF_GRAYED = 0x00000001
909
+ MF_CHECKED = 0x00000008
910
+ MFT_RADIOCHECK = 0x00000200
911
+ MF_UNCHECKED = 0x00000000
912
+ MF_HILITE = 0x00000080
913
+ MF_UNHILITE = 0x00000000
914
+ #}
915
+
916
+ attach_function :AppendMenu, :AppendMenuA, [
917
+ :pointer,
918
+ :uint,
919
+ :uint,
920
+ :string
921
+ ], :int
922
+
923
+ #{ MF_xxx
924
+ MF_BYCOMMAND = 0x00000000
925
+ MF_BYPOSITION = 0x00000400
926
+ #}
927
+
928
+ attach_function :EnableMenuItem, [
929
+ :pointer,
930
+ :uint,
931
+ :uint
932
+ ], :int
933
+
934
+ attach_function :CheckMenuItem, [
935
+ :pointer,
936
+ :uint,
937
+ :uint
938
+ ], :ulong
939
+
940
+ attach_function :CheckMenuRadioItem, [
941
+ :pointer,
942
+ :uint,
943
+ :uint,
944
+ :uint,
945
+ :uint
946
+ ], :int
947
+
948
+ attach_function :HiliteMenuItem, [
949
+ :pointer,
950
+ :pointer,
951
+ :uint,
952
+ :uint
953
+ ], :int
954
+
955
+ attach_function :GetMenuState, [
956
+ :pointer,
957
+ :uint,
958
+ :uint
959
+ ], :uint
960
+
961
+ #{ Fxxx
962
+ FVIRTKEY = 1
963
+ FCONTROL = 0x08
964
+ FSHIFT = 0x04
965
+ FALT = 0x10
966
+ #}
967
+
968
+ class ACCEL < FFI::Struct
969
+ layout \
970
+ :fVirt, :uchar,
971
+ :key, :ushort,
972
+ :cmd, :ushort
973
+ end
974
+
975
+ attach_function :CreateAcceleratorTable, :CreateAcceleratorTableA, [
976
+ :pointer,
977
+ :int
978
+ ], :pointer
979
+
980
+ attach_function :DestroyAcceleratorTable, [
981
+ :pointer
982
+ ], :int
983
+
984
+ #{ SPI_xxx
985
+ class NONCLIENTMETRICS < FFI::Struct
986
+ layout *[
987
+ :cbSize, :uint,
988
+ :iBorderWidth, :int,
989
+ :iScrollWidth, :int,
990
+ :iScrollHeight, :int,
991
+ :iCaptionWidth, :int,
992
+ :iCaptionHeight, :int,
993
+ :lfCaptionFont, LOGFONT,
994
+ :iSmCaptionWidth, :int,
995
+ :iSmCaptionHeight, :int,
996
+ :lfSmCaptionFont, LOGFONT,
997
+ :iMenuWidth, :int,
998
+ :iMenuHeight, :int,
999
+ :lfMenuFont, LOGFONT,
1000
+ :lfStatusFont, LOGFONT,
1001
+ :lfMessageFont, LOGFONT,
1002
+ (WINVER >= WINVISTA) ? [:iPaddedBorderWidth, :int] : nil
1003
+ ].tap { |layout|
1004
+ layout.flatten!
1005
+ layout.compact!
1006
+ }
1007
+ end
1008
+
1009
+ SPI_SETNONCLIENTMETRICS = 0x002A
1010
+ SPI_GETNONCLIENTMETRICS = 0x0029
1011
+ #}
1012
+
1013
+ attach_function :SystemParametersInfo, :SystemParametersInfoA, [
1014
+ :uint,
1015
+ :uint,
1016
+ :pointer,
1017
+ :uint
1018
+ ], :int
1019
+ end