metasm 1.0.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.
Files changed (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -0,0 +1,3004 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ require 'metasm/dynldr'
7
+
8
+ module Metasm
9
+ module Gui
10
+ class Win32Gui < DynLdr
11
+ new_api_c <<EOS
12
+ #line #{__LINE__}
13
+ typedef char CHAR;
14
+ typedef unsigned char BYTE;
15
+ typedef unsigned short WORD;
16
+ typedef unsigned int UINT;
17
+ typedef long LONG;
18
+ typedef unsigned long ULONG, DWORD;
19
+ typedef int BOOL;
20
+
21
+ typedef intptr_t INT_PTR, LONG_PTR;
22
+ typedef uintptr_t UINT_PTR, ULONG_PTR, DWORD_PTR;
23
+ typedef LONG_PTR LPARAM;
24
+ typedef UINT_PTR WPARAM;
25
+ typedef LONG_PTR LRESULT;
26
+ typedef const CHAR *LPSTR, *LPCSTR;
27
+ typedef void VOID, *PVOID, *LPVOID;
28
+
29
+ typedef WORD ATOM;
30
+ typedef void *HANDLE;
31
+ typedef void *HBITMAP;
32
+ typedef void *HBRUSH;
33
+ typedef void *HCURSOR;
34
+ typedef void *HDC;
35
+ typedef void *HICON;
36
+ typedef void *HINSTANCE;
37
+ typedef void *HMENU;
38
+ typedef void *HMODULE;
39
+ typedef void *HPEN;
40
+ typedef void *HWND;
41
+
42
+ #define DECLSPEC_IMPORT __declspec(dllimport)
43
+ #define WINUSERAPI DECLSPEC_IMPORT
44
+ #define WINAPI __stdcall
45
+ #define CALLBACK __stdcall
46
+ #define CONST const
47
+ #define __in __attribute__((in))
48
+ #define __out __attribute__((out))
49
+ #define __opt __attribute__((opt))
50
+ #define __inout __in __out
51
+ #define __in_opt __in __opt
52
+ #define __out_opt __out __opt
53
+ #define __in_ecount(c) __in
54
+ #define __out_ecount(c) __out
55
+ #define __inout_ecount(c) __inout
56
+
57
+ #define CW_USEDEFAULT ((int)0x80000000)
58
+
59
+ #define WS_OVERLAPPED 0x00000000L
60
+ #define WS_POPUP 0x80000000L
61
+ #define WS_CHILD 0x40000000L
62
+ #define WS_MINIMIZE 0x20000000L
63
+ #define WS_VISIBLE 0x10000000L
64
+ #define WS_DISABLED 0x08000000L
65
+ #define WS_CLIPSIBLINGS 0x04000000L
66
+ #define WS_CLIPCHILDREN 0x02000000L
67
+ #define WS_MAXIMIZE 0x01000000L
68
+ #define WS_CAPTION 0x00C00000L /* WS_BORDER | WS_DLGFRAME */
69
+ #define WS_BORDER 0x00800000L
70
+ #define WS_DLGFRAME 0x00400000L
71
+ #define WS_VSCROLL 0x00200000L
72
+ #define WS_HSCROLL 0x00100000L
73
+ #define WS_SYSMENU 0x00080000L
74
+ #define WS_THICKFRAME 0x00040000L
75
+ #define WS_GROUP 0x00020000L
76
+ #define WS_TABSTOP 0x00010000L
77
+ #define WS_MINIMIZEBOX 0x00020000L
78
+ #define WS_MAXIMIZEBOX 0x00010000L
79
+ #define WS_TILED WS_OVERLAPPED
80
+ #define WS_ICONIC WS_MINIMIZE
81
+ #define WS_SIZEBOX WS_THICKFRAME
82
+ #define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
83
+ #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
84
+ #define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU)
85
+ #define WS_CHILDWINDOW (WS_CHILD)
86
+
87
+ #define WS_EX_DLGMODALFRAME 0x00000001L
88
+ #define WS_EX_NOPARENTNOTIFY 0x00000004L
89
+ #define WS_EX_TOPMOST 0x00000008L
90
+ #define WS_EX_ACCEPTFILES 0x00000010L
91
+ #define WS_EX_TRANSPARENT 0x00000020L
92
+ #define WS_EX_MDICHILD 0x00000040L
93
+ #define WS_EX_TOOLWINDOW 0x00000080L
94
+ #define WS_EX_WINDOWEDGE 0x00000100L
95
+ #define WS_EX_CLIENTEDGE 0x00000200L
96
+ #define WS_EX_CONTEXTHELP 0x00000400L
97
+ #define WS_EX_RIGHT 0x00001000L
98
+ #define WS_EX_LEFT 0x00000000L
99
+ #define WS_EX_RTLREADING 0x00002000L
100
+ #define WS_EX_LTRREADING 0x00000000L
101
+ #define WS_EX_LEFTSCROLLBAR 0x00004000L
102
+ #define WS_EX_RIGHTSCROLLBAR 0x00000000L
103
+ #define WS_EX_CONTROLPARENT 0x00010000L
104
+ #define WS_EX_STATICEDGE 0x00020000L
105
+ #define WS_EX_APPWINDOW 0x00040000L
106
+ #define WS_EX_OVERLAPPEDWINDOW (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE)
107
+ #define WS_EX_PALETTEWINDOW (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)
108
+ #define WS_EX_LAYERED 0x00080000L
109
+ #define WS_EX_NOINHERITEDLAYOUT 0x00100000L
110
+ #define WS_EX_LAYOUTRTL 0x00400000L
111
+ #define WS_EX_COMPOSITED 0x02000000L
112
+ #define WS_EX_NOACTIVATE 0x08000000L
113
+
114
+ #define WM_NULL 0x0000
115
+ #define WM_CREATE 0x0001
116
+ #define WM_DESTROY 0x0002
117
+ #define WM_MOVE 0x0003
118
+ #define WM_SIZE 0x0005
119
+
120
+ #define WM_ACTIVATE 0x0006
121
+ #define WA_INACTIVE 0
122
+ #define WA_ACTIVE 1
123
+ #define WA_CLICKACTIVE 2
124
+
125
+ #define WM_SETFOCUS 0x0007
126
+ #define WM_KILLFOCUS 0x0008
127
+ #define WM_ENABLE 0x000A
128
+ #define WM_SETREDRAW 0x000B
129
+ #define WM_SETTEXT 0x000C
130
+ #define WM_GETTEXT 0x000D
131
+ #define WM_GETTEXTLENGTH 0x000E
132
+ #define WM_PAINT 0x000F
133
+ #define WM_CLOSE 0x0010
134
+ #define WM_QUERYENDSESSION 0x0011
135
+ #define WM_QUERYOPEN 0x0013
136
+ #define WM_ENDSESSION 0x0016
137
+ #define WM_QUIT 0x0012
138
+ #define WM_ERASEBKGND 0x0014
139
+ #define WM_SYSCOLORCHANGE 0x0015
140
+ #define WM_SHOWWINDOW 0x0018
141
+ #define WM_WININICHANGE 0x001A
142
+ #define WM_SETTINGCHANGE WM_WININICHANGE
143
+ #define WM_DEVMODECHANGE 0x001B
144
+ #define WM_ACTIVATEAPP 0x001C
145
+ #define WM_FONTCHANGE 0x001D
146
+ #define WM_TIMECHANGE 0x001E
147
+ #define WM_CANCELMODE 0x001F
148
+ #define WM_SETCURSOR 0x0020
149
+ #define WM_MOUSEACTIVATE 0x0021
150
+ #define WM_CHILDACTIVATE 0x0022
151
+ #define WM_QUEUESYNC 0x0023
152
+ #define WM_GETMINMAXINFO 0x0024
153
+ typedef struct tagPOINT {
154
+ LONG x;
155
+ LONG y;
156
+ } POINT, *PPOINT, *LPPOINT;
157
+
158
+ #define WM_PAINTICON 0x0026
159
+ #define WM_ICONERASEBKGND 0x0027
160
+ #define WM_NEXTDLGCTL 0x0028
161
+ #define WM_SPOOLERSTATUS 0x002A
162
+ #define WM_DRAWITEM 0x002B
163
+ #define WM_MEASUREITEM 0x002C
164
+ #define WM_DELETEITEM 0x002D
165
+ #define WM_VKEYTOITEM 0x002E
166
+ #define WM_CHARTOITEM 0x002F
167
+ #define WM_SETFONT 0x0030
168
+ #define WM_GETFONT 0x0031
169
+ #define WM_SETHOTKEY 0x0032
170
+ #define WM_GETHOTKEY 0x0033
171
+ #define WM_QUERYDRAGICON 0x0037
172
+ #define WM_COMPAREITEM 0x0039
173
+ #define WM_GETOBJECT 0x003D
174
+ #define WM_COMPACTING 0x0041
175
+ #define WM_COMMNOTIFY 0x0044
176
+ #define WM_WINDOWPOSCHANGING 0x0046
177
+ #define WM_WINDOWPOSCHANGED 0x0047
178
+ #define WM_POWER 0x0048
179
+ #define PWR_OK 1
180
+ #define PWR_FAIL (-1)
181
+ #define PWR_SUSPENDREQUEST 1
182
+ #define PWR_SUSPENDRESUME 2
183
+ #define PWR_CRITICALRESUME 3
184
+ #define WM_COPYDATA 0x004A
185
+ #define WM_CANCELJOURNAL 0x004B
186
+ #define WM_NOTIFY 0x004E
187
+ #define WM_INPUTLANGCHANGEREQUEST 0x0050
188
+ #define WM_INPUTLANGCHANGE 0x0051
189
+ #define WM_TCARD 0x0052
190
+ #define WM_HELP 0x0053
191
+ #define WM_USERCHANGED 0x0054
192
+ #define WM_NOTIFYFORMAT 0x0055
193
+ #define NFR_ANSI 1
194
+ #define NFR_UNICODE 2
195
+ #define NF_QUERY 3
196
+ #define NF_REQUERY 4
197
+ #define WM_CONTEXTMENU 0x007B
198
+ #define WM_STYLECHANGING 0x007C
199
+ #define WM_STYLECHANGED 0x007D
200
+ #define WM_DISPLAYCHANGE 0x007E
201
+ #define WM_GETICON 0x007F
202
+ #define WM_SETICON 0x0080
203
+ #define WM_NCCREATE 0x0081
204
+ #define WM_NCDESTROY 0x0082
205
+ #define WM_NCCALCSIZE 0x0083
206
+ #define WM_NCHITTEST 0x0084
207
+ #define WM_NCPAINT 0x0085
208
+ #define WM_NCACTIVATE 0x0086
209
+ #define WM_GETDLGCODE 0x0087
210
+ #define WM_SYNCPAINT 0x0088
211
+ #define WM_NCMOUSEMOVE 0x00A0
212
+ #define WM_NCLBUTTONDOWN 0x00A1
213
+ #define WM_NCLBUTTONUP 0x00A2
214
+ #define WM_NCLBUTTONDBLCLK 0x00A3
215
+ #define WM_NCRBUTTONDOWN 0x00A4
216
+ #define WM_NCRBUTTONUP 0x00A5
217
+ #define WM_NCRBUTTONDBLCLK 0x00A6
218
+ #define WM_NCMBUTTONDOWN 0x00A7
219
+ #define WM_NCMBUTTONUP 0x00A8
220
+ #define WM_NCMBUTTONDBLCLK 0x00A9
221
+ #define WM_NCXBUTTONDOWN 0x00AB
222
+ #define WM_NCXBUTTONUP 0x00AC
223
+ #define WM_NCXBUTTONDBLCLK 0x00AD
224
+ #define WM_INPUT 0x00FF
225
+ #define WM_KEYFIRST 0x0100
226
+ #define WM_KEYDOWN 0x0100
227
+ #define WM_KEYUP 0x0101
228
+ #define WM_CHAR 0x0102
229
+ #define WM_DEADCHAR 0x0103
230
+ #define WM_SYSKEYDOWN 0x0104
231
+ #define WM_SYSKEYUP 0x0105
232
+ #define WM_SYSCHAR 0x0106
233
+ #define WM_SYSDEADCHAR 0x0107
234
+ #define WM_UNICHAR 0x0109
235
+ #define WM_KEYLAST 0x0109
236
+ #define UNICODE_NOCHAR 0xFFFF
237
+ #define WM_IME_STARTCOMPOSITION 0x010D
238
+ #define WM_IME_ENDCOMPOSITION 0x010E
239
+ #define WM_IME_COMPOSITION 0x010F
240
+ #define WM_IME_KEYLAST 0x010F
241
+
242
+ #define WM_INITDIALOG 0x0110
243
+ #define WM_COMMAND 0x0111
244
+ #define WM_SYSCOMMAND 0x0112
245
+ #define WM_TIMER 0x0113
246
+ #define WM_HSCROLL 0x0114
247
+ #define WM_VSCROLL 0x0115
248
+ #define WM_INITMENU 0x0116
249
+ #define WM_INITMENUPOPUP 0x0117
250
+ #define WM_MENUSELECT 0x011F
251
+ #define WM_MENUCHAR 0x0120
252
+ #define WM_ENTERIDLE 0x0121
253
+ #define WM_MENURBUTTONUP 0x0122
254
+ #define WM_MENUDRAG 0x0123
255
+ #define WM_MENUGETOBJECT 0x0124
256
+ #define WM_UNINITMENUPOPUP 0x0125
257
+ #define WM_MENUCOMMAND 0x0126
258
+ #define WM_CHANGEUISTATE 0x0127
259
+ #define WM_UPDATEUISTATE 0x0128
260
+ #define WM_QUERYUISTATE 0x0129
261
+ #define UIS_SET 1
262
+ #define UIS_CLEAR 2
263
+ #define UIS_INITIALIZE 3
264
+ #define UISF_HIDEFOCUS 0x1
265
+ #define UISF_HIDEACCEL 0x2
266
+ #define WM_CTLCOLORMSGBOX 0x0132
267
+ #define WM_CTLCOLOREDIT 0x0133
268
+ #define WM_CTLCOLORLISTBOX 0x0134
269
+ #define WM_CTLCOLORBTN 0x0135
270
+ #define WM_CTLCOLORDLG 0x0136
271
+ #define WM_CTLCOLORSCROLLBAR 0x0137
272
+ #define WM_CTLCOLORSTATIC 0x0138
273
+ #define MN_GETHMENU 0x01E1
274
+ #define WM_MOUSEFIRST 0x0200
275
+ #define WM_MOUSEMOVE 0x0200
276
+ #define WM_LBUTTONDOWN 0x0201
277
+ #define WM_LBUTTONUP 0x0202
278
+ #define WM_LBUTTONDBLCLK 0x0203
279
+ #define WM_RBUTTONDOWN 0x0204
280
+ #define WM_RBUTTONUP 0x0205
281
+ #define WM_RBUTTONDBLCLK 0x0206
282
+ #define WM_MBUTTONDOWN 0x0207
283
+ #define WM_MBUTTONUP 0x0208
284
+ #define WM_MBUTTONDBLCLK 0x0209
285
+ #define WM_MOUSEWHEEL 0x020A
286
+ #define WM_XBUTTONDOWN 0x020B
287
+ #define WM_XBUTTONUP 0x020C
288
+ #define WM_XBUTTONDBLCLK 0x020D
289
+ #define WHEEL_DELTA 120
290
+
291
+ #define WHEEL_PAGESCROLL (UINT_MAX)
292
+ #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
293
+ #define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
294
+ #define GET_NCHITTEST_WPARAM(wParam) ((short)LOWORD(wParam))
295
+ #define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
296
+
297
+ #define XBUTTON1 0x0001
298
+ #define XBUTTON2 0x0002
299
+
300
+ #define WM_PARENTNOTIFY 0x0210
301
+ #define WM_ENTERMENULOOP 0x0211
302
+ #define WM_EXITMENULOOP 0x0212
303
+ #define WM_NEXTMENU 0x0213
304
+ #define WM_SIZING 0x0214
305
+ #define WM_CAPTURECHANGED 0x0215
306
+ #define WM_MOVING 0x0216
307
+ #define WM_DEVICECHANGE 0x0219
308
+ #define WM_MDICREATE 0x0220
309
+ #define WM_MDIDESTROY 0x0221
310
+ #define WM_MDIACTIVATE 0x0222
311
+ #define WM_MDIRESTORE 0x0223
312
+ #define WM_MDINEXT 0x0224
313
+ #define WM_MDIMAXIMIZE 0x0225
314
+ #define WM_MDITILE 0x0226
315
+ #define WM_MDICASCADE 0x0227
316
+ #define WM_MDIICONARRANGE 0x0228
317
+ #define WM_MDIGETACTIVE 0x0229
318
+ #define WM_MDISETMENU 0x0230
319
+ #define WM_ENTERSIZEMOVE 0x0231
320
+ #define WM_EXITSIZEMOVE 0x0232
321
+ #define WM_DROPFILES 0x0233
322
+ #define WM_MDIREFRESHMENU 0x0234
323
+ #define WM_IME_SETCONTEXT 0x0281
324
+ #define WM_IME_NOTIFY 0x0282
325
+ #define WM_IME_CONTROL 0x0283
326
+ #define WM_IME_COMPOSITIONFULL 0x0284
327
+ #define WM_IME_SELECT 0x0285
328
+ #define WM_IME_CHAR 0x0286
329
+ #define WM_IME_REQUEST 0x0288
330
+ #define WM_IME_KEYDOWN 0x0290
331
+ #define WM_IME_KEYUP 0x0291
332
+ #define WM_NCMOUSEHOVER 0x02A0
333
+ #define WM_MOUSEHOVER 0x02A1
334
+ #define WM_NCMOUSELEAVE 0x02A2
335
+ #define WM_MOUSELEAVE 0x02A3
336
+ #define WM_WTSSESSION_CHANGE 0x02B1
337
+ #define WM_TABLET_FIRST 0x02c0
338
+ #define WM_TABLET_LAST 0x02df
339
+ #define WM_CUT 0x0300
340
+ #define WM_COPY 0x0301
341
+ #define WM_PASTE 0x0302
342
+ #define WM_CLEAR 0x0303
343
+ #define WM_UNDO 0x0304
344
+ #define WM_RENDERFORMAT 0x0305
345
+ #define WM_RENDERALLFORMATS 0x0306
346
+ #define WM_DESTROYCLIPBOARD 0x0307
347
+ #define WM_DRAWCLIPBOARD 0x0308
348
+ #define WM_PAINTCLIPBOARD 0x0309
349
+ #define WM_VSCROLLCLIPBOARD 0x030A
350
+ #define WM_SIZECLIPBOARD 0x030B
351
+ #define WM_ASKCBFORMATNAME 0x030C
352
+ #define WM_CHANGECBCHAIN 0x030D
353
+ #define WM_HSCROLLCLIPBOARD 0x030E
354
+ #define WM_QUERYNEWPALETTE 0x030F
355
+ #define WM_PALETTEISCHANGING 0x0310
356
+ #define WM_PALETTECHANGED 0x0311
357
+ #define WM_HOTKEY 0x0312
358
+ #define WM_PRINT 0x0317
359
+ #define WM_PRINTCLIENT 0x0318
360
+ #define WM_APPCOMMAND 0x0319
361
+ #define WM_THEMECHANGED 0x031A
362
+ #define WM_HANDHELDFIRST 0x0358
363
+ #define WM_HANDHELDLAST 0x035F
364
+ #define WM_AFXFIRST 0x0360
365
+ #define WM_AFXLAST 0x037F
366
+ #define WM_PENWINFIRST 0x0380
367
+ #define WM_PENWINLAST 0x038F
368
+ #define WM_USER 0x0400
369
+ #define WM_APP 0x8000
370
+
371
+ #define WMSZ_LEFT 1
372
+ #define WMSZ_RIGHT 2
373
+ #define WMSZ_TOP 3
374
+ #define WMSZ_TOPLEFT 4
375
+ #define WMSZ_TOPRIGHT 5
376
+ #define WMSZ_BOTTOM 6
377
+ #define WMSZ_BOTTOMLEFT 7
378
+ #define WMSZ_BOTTOMRIGHT 8
379
+
380
+ #define SWP_NOSIZE 0x0001
381
+ #define SWP_NOMOVE 0x0002
382
+ #define SWP_NOZORDER 0x0004
383
+ #define SWP_NOREDRAW 0x0008
384
+ #define SWP_NOACTIVATE 0x0010
385
+ #define SWP_FRAMECHANGED 0x0020 /* The frame changed: send WM_NCCALCSIZE */
386
+ #define SWP_SHOWWINDOW 0x0040
387
+ #define SWP_HIDEWINDOW 0x0080
388
+ #define SWP_NOCOPYBITS 0x0100
389
+ #define SWP_NOOWNERZORDER 0x0200 /* Don't do owner Z ordering */
390
+ #define SWP_NOSENDCHANGING 0x0400 /* Don't send WM_WINDOWPOSCHANGING */
391
+ #define SWP_DRAWFRAME SWP_FRAMECHANGED
392
+ #define SWP_NOREPOSITION SWP_NOOWNERZORDER
393
+ #define SWP_DEFERERASE 0x2000
394
+ #define SWP_ASYNCWINDOWPOS 0x4000
395
+
396
+ #define HWND_TOP 0
397
+ #define HWND_BOTTOM 1
398
+ #define HWND_TOPMOST -1
399
+ #define HWND_NOTOPMOST -2
400
+
401
+ #define SIZE_RESTORED 0
402
+ #define SIZE_MINIMIZED 1
403
+ #define SIZE_MAXIMIZED 2
404
+ #define SIZE_MAXSHOW 3
405
+ #define SIZE_MAXHIDE 4
406
+
407
+ #define MK_LBUTTON 0x0001
408
+ #define MK_RBUTTON 0x0002
409
+ #define MK_SHIFT 0x0004
410
+ #define MK_CONTROL 0x0008
411
+ #define MK_MBUTTON 0x0010
412
+ #define MK_XBUTTON1 0x0020
413
+ #define MK_XBUTTON2 0x0040
414
+
415
+ typedef struct tagTRACKMOUSEEVENT {
416
+ DWORD cbSize;
417
+ DWORD dwFlags;
418
+ HWND hwndTrack;
419
+ DWORD dwHoverTime;
420
+ } TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
421
+
422
+ WINUSERAPI
423
+ BOOL
424
+ WINAPI
425
+ TrackMouseEvent(
426
+ __inout LPTRACKMOUSEEVENT lpEventTrack);
427
+
428
+ #define FVIRTKEY TRUE /* Assumed to be == TRUE */
429
+ #define FNOINVERT 0x02
430
+ #define FSHIFT 0x04
431
+ #define FCONTROL 0x08
432
+ #define FALT 0x10
433
+
434
+ #define FALSE 0
435
+ #define TRUE 1
436
+
437
+ #define SW_HIDE 0
438
+ #define SW_SHOWNORMAL 1
439
+ #define SW_NORMAL 1
440
+ #define SW_SHOWMINIMIZED 2
441
+ #define SW_SHOWMAXIMIZED 3
442
+ #define SW_MAXIMIZE 3
443
+ #define SW_SHOWNOACTIVATE 4
444
+ #define SW_SHOW 5
445
+ #define SW_MINIMIZE 6
446
+ #define SW_SHOWMINNOACTIVE 7
447
+ #define SW_SHOWNA 8
448
+ #define SW_RESTORE 9
449
+ #define SW_SHOWDEFAULT 10
450
+ #define SW_FORCEMINIMIZE 11
451
+ #define SW_MAX 11
452
+
453
+ #define CS_VREDRAW 0x0001
454
+ #define CS_HREDRAW 0x0002
455
+ #define CS_DBLCLKS 0x0008
456
+ #define CS_OWNDC 0x0020
457
+ #define CS_CLASSDC 0x0040
458
+ #define CS_PARENTDC 0x0080
459
+ #define CS_NOCLOSE 0x0200
460
+ #define CS_SAVEBITS 0x0800
461
+ #define CS_BYTEALIGNCLIENT 0x1000
462
+ #define CS_BYTEALIGNWINDOW 0x2000
463
+ #define CS_GLOBALCLASS 0x4000
464
+ #define CS_IME 0x00010000
465
+ #define CS_DROPSHADOW 0x00020000
466
+
467
+ #define MF_INSERT 0x00000000L
468
+ #define MF_CHANGE 0x00000080L
469
+ #define MF_APPEND 0x00000100L
470
+ #define MF_DELETE 0x00000200L
471
+ #define MF_REMOVE 0x00001000L
472
+ #define MF_BYCOMMAND 0x00000000L
473
+ #define MF_BYPOSITION 0x00000400L
474
+ #define MF_SEPARATOR 0x00000800L
475
+ #define MF_ENABLED 0x00000000L
476
+ #define MF_GRAYED 0x00000001L
477
+ #define MF_DISABLED 0x00000002L
478
+ #define MF_UNCHECKED 0x00000000L
479
+ #define MF_CHECKED 0x00000008L
480
+ #define MF_USECHECKBITMAPS 0x00000200L
481
+ #define MF_STRING 0x00000000L
482
+ #define MF_BITMAP 0x00000004L
483
+ #define MF_OWNERDRAW 0x00000100L
484
+ #define MF_POPUP 0x00000010L
485
+ #define MF_MENUBARBREAK 0x00000020L
486
+ #define MF_MENUBREAK 0x00000040L
487
+ #define MF_UNHILITE 0x00000000L
488
+ #define MF_HILITE 0x00000080L
489
+ #define MF_DEFAULT 0x00001000L
490
+ #define MF_SYSMENU 0x00002000L
491
+ #define MF_HELP 0x00004000L
492
+ #define MF_RIGHTJUSTIFY 0x00004000L
493
+ #define MF_MOUSESELECT 0x00008000L
494
+
495
+ #define IDI_APPLICATION 32512
496
+ #define IDI_HAND 32513
497
+ #define IDI_QUESTION 32514
498
+ #define IDI_EXCLAMATION 32515
499
+ #define IDI_ASTERISK 32516
500
+ #define IDI_WINLOGO 32517
501
+
502
+ #define MB_OK 0x00000000L
503
+ #define MB_OKCANCEL 0x00000001L
504
+ #define MB_ABORTRETRYIGNORE 0x00000002L
505
+ #define MB_YESNOCANCEL 0x00000003L
506
+ #define MB_YESNO 0x00000004L
507
+ #define MB_RETRYCANCEL 0x00000005L
508
+ #define MB_CANCELTRYCONTINUE 0x00000006L
509
+ #define MB_ICONHAND 0x00000010L
510
+ #define MB_ICONQUESTION 0x00000020L
511
+ #define MB_ICONEXCLAMATION 0x00000030L
512
+ #define MB_ICONASTERISK 0x00000040L
513
+ #define MB_USERICON 0x00000080L
514
+ #define MB_ICONWARNING MB_ICONEXCLAMATION
515
+ #define MB_ICONERROR MB_ICONHAND
516
+ #define MB_ICONINFORMATION MB_ICONASTERISK
517
+ #define MB_ICONSTOP MB_ICONHAND
518
+ #define MB_DEFBUTTON1 0x00000000L
519
+ #define MB_DEFBUTTON2 0x00000100L
520
+ #define MB_DEFBUTTON3 0x00000200L
521
+ #define MB_DEFBUTTON4 0x00000300L
522
+ #define MB_APPLMODAL 0x00000000L
523
+ #define MB_SYSTEMMODAL 0x00001000L
524
+ #define MB_TASKMODAL 0x00002000L
525
+ #define MB_HELP 0x00004000L
526
+ #define MB_NOFOCUS 0x00008000L
527
+ #define MB_SETFOREGROUND 0x00010000L
528
+ #define MB_DEFAULT_DESKTOP_ONLY 0x00020000L
529
+ #define MB_TOPMOST 0x00040000L
530
+ #define MB_RIGHT 0x00080000L
531
+ #define MB_RTLREADING 0x00100000L
532
+ #define MB_SERVICE_NOTIFICATION 0x00200000L
533
+ #define MB_SERVICE_NOTIFICATION_NT3X 0x00040000L
534
+
535
+ #define IDOK 1
536
+ #define IDCANCEL 2
537
+ #define IDABORT 3
538
+ #define IDRETRY 4
539
+ #define IDIGNORE 5
540
+ #define IDYES 6
541
+ #define IDNO 7
542
+ #define IDCLOSE 8
543
+ #define IDHELP 9
544
+ #define IDTRYAGAIN 10
545
+ #define IDCONTINUE 11
546
+ #define IDTIMEOUT 32000
547
+
548
+ #define PM_NOREMOVE 0
549
+ #define PM_REMOVE 1
550
+ #define PM_NOYIELD 2
551
+
552
+ #define IDC_ARROW 32512
553
+ #define IDC_IBEAM 32513
554
+ #define IDC_WAIT 32514
555
+ #define IDC_CROSS 32515
556
+ #define IDC_UPARROW 32516
557
+ #define IDC_SIZE 32640
558
+ #define IDC_ICON 32641
559
+ #define IDC_SIZENWSE 32642
560
+ #define IDC_SIZENESW 32643
561
+ #define IDC_SIZEWE 32644
562
+ #define IDC_SIZENS 32645
563
+ #define IDC_SIZEALL 32646
564
+ #define IDC_NO 32648
565
+ #define IDC_HAND 32649
566
+ #define IDC_APPSTARTING 32650
567
+ #define IDC_HELP 32651
568
+
569
+ #define WHITE_BRUSH 0
570
+ #define LTGRAY_BRUSH 1
571
+ #define GRAY_BRUSH 2
572
+ #define DKGRAY_BRUSH 3
573
+ #define BLACK_BRUSH 4
574
+ #define NULL_BRUSH 5
575
+ #define HOLLOW_BRUSH NULL_BRUSH
576
+ #define WHITE_PEN 6
577
+ #define BLACK_PEN 7
578
+ #define NULL_PEN 8
579
+ #define OEM_FIXED_FONT 10
580
+ #define ANSI_FIXED_FONT 11
581
+ #define ANSI_VAR_FONT 12
582
+ #define SYSTEM_FONT 13
583
+ #define DEVICE_DEFAULT_FONT 14
584
+ #define DEFAULT_PALETTE 15
585
+ #define SYSTEM_FIXED_FONT 16
586
+ #define DEFAULT_GUI_FONT 17
587
+ #define DC_BRUSH 18
588
+ #define DC_PEN 19
589
+
590
+ #define VK_LBUTTON 0x01
591
+ #define VK_RBUTTON 0x02
592
+ #define VK_CANCEL 0x03
593
+ #define VK_MBUTTON 0x04
594
+ #define VK_XBUTTON1 0x05
595
+ #define VK_XBUTTON2 0x06
596
+ #define VK_BACK 0x08
597
+ #define VK_TAB 0x09
598
+ #define VK_CLEAR 0x0C
599
+ #define VK_RETURN 0x0D
600
+ #define VK_SHIFT 0x10
601
+ #define VK_CONTROL 0x11
602
+ #define VK_MENU 0x12
603
+ #define VK_PAUSE 0x13
604
+ #define VK_CAPITAL 0x14
605
+ #define VK_ESCAPE 0x1B
606
+ #define VK_CONVERT 0x1C
607
+ #define VK_NONCONVERT 0x1D
608
+ #define VK_ACCEPT 0x1E
609
+ #define VK_MODECHANGE 0x1F
610
+ #define VK_SPACE 0x20
611
+ #define VK_PRIOR 0x21
612
+ #define VK_NEXT 0x22
613
+ #define VK_END 0x23
614
+ #define VK_HOME 0x24
615
+ #define VK_LEFT 0x25
616
+ #define VK_UP 0x26
617
+ #define VK_RIGHT 0x27
618
+ #define VK_DOWN 0x28
619
+ #define VK_SELECT 0x29
620
+ #define VK_PRINT 0x2A
621
+ #define VK_EXECUTE 0x2B
622
+ #define VK_SNAPSHOT 0x2C
623
+ #define VK_INSERT 0x2D
624
+ #define VK_DELETE 0x2E
625
+ #define VK_HELP 0x2F
626
+ // VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
627
+ // VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
628
+ #define VK_LWIN 0x5B
629
+ #define VK_RWIN 0x5C
630
+ #define VK_APPS 0x5D
631
+ #define VK_SLEEP 0x5F
632
+ #define VK_NUMPAD0 0x60
633
+ #define VK_NUMPAD1 0x61
634
+ #define VK_NUMPAD2 0x62
635
+ #define VK_NUMPAD3 0x63
636
+ #define VK_NUMPAD4 0x64
637
+ #define VK_NUMPAD5 0x65
638
+ #define VK_NUMPAD6 0x66
639
+ #define VK_NUMPAD7 0x67
640
+ #define VK_NUMPAD8 0x68
641
+ #define VK_NUMPAD9 0x69
642
+ #define VK_MULTIPLY 0x6A
643
+ #define VK_ADD 0x6B
644
+ #define VK_SEPARATOR 0x6C
645
+ #define VK_SUBTRACT 0x6D
646
+ #define VK_DECIMAL 0x6E
647
+ #define VK_DIVIDE 0x6F
648
+ #define VK_F1 0x70
649
+ #define VK_F2 0x71
650
+ #define VK_F3 0x72
651
+ #define VK_F4 0x73
652
+ #define VK_F5 0x74
653
+ #define VK_F6 0x75
654
+ #define VK_F7 0x76
655
+ #define VK_F8 0x77
656
+ #define VK_F9 0x78
657
+ #define VK_F10 0x79
658
+ #define VK_F11 0x7A
659
+ #define VK_F12 0x7B
660
+ #define VK_F13 0x7C
661
+ #define VK_F14 0x7D
662
+ #define VK_F15 0x7E
663
+ #define VK_F16 0x7F
664
+ #define VK_F17 0x80
665
+ #define VK_F18 0x81
666
+ #define VK_F19 0x82
667
+ #define VK_F20 0x83
668
+ #define VK_F21 0x84
669
+ #define VK_F22 0x85
670
+ #define VK_F23 0x86
671
+ #define VK_F24 0x87
672
+
673
+ #define QS_KEY 0x0001
674
+ #define QS_MOUSEMOVE 0x0002
675
+ #define QS_MOUSEBUTTON 0x0004
676
+ #define QS_POSTMESSAGE 0x0008
677
+ #define QS_TIMER 0x0010
678
+ #define QS_PAINT 0x0020
679
+ #define QS_SENDMESSAGE 0x0040
680
+ #define QS_HOTKEY 0x0080
681
+ #define QS_ALLPOSTMESSAGE 0x0100
682
+ #define QS_RAWINPUT 0x0400
683
+ #define QS_MOUSE (QS_MOUSEMOVE | QS_MOUSEBUTTON)
684
+ #define QS_INPUT (QS_MOUSE | QS_KEY | QS_RAWINPUT)
685
+ #define QS_ALLEVENTS (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY)
686
+ #define QS_ALLINPUT (QS_ALLEVENTS | QS_SENDMESSAGE)
687
+
688
+ #define WAIT_TIMEOUT 258L
689
+
690
+ #define CF_TEXT 1
691
+ #define CF_BITMAP 2
692
+ #define CF_METAFILEPICT 3
693
+ #define CF_SYLK 4
694
+ #define CF_DIF 5
695
+ #define CF_TIFF 6
696
+ #define CF_OEMTEXT 7
697
+ #define CF_DIB 8
698
+ #define CF_PALETTE 9
699
+ #define CF_PENDATA 10
700
+ #define CF_RIFF 11
701
+ #define CF_WAVE 12
702
+ #define CF_UNICODETEXT 13
703
+ #define CF_ENHMETAFILE 14
704
+ #define CF_HDROP 15
705
+ #define CF_LOCALE 16
706
+ #define CF_DIBV5 17
707
+
708
+ #define COLOR_SCROLLBAR 0
709
+ #define COLOR_BACKGROUND 1
710
+ #define COLOR_ACTIVECAPTION 2
711
+ #define COLOR_INACTIVECAPTION 3
712
+ #define COLOR_MENU 4
713
+ #define COLOR_WINDOW 5
714
+ #define COLOR_WINDOWFRAME 6
715
+ #define COLOR_MENUTEXT 7
716
+ #define COLOR_WINDOWTEXT 8
717
+ #define COLOR_CAPTIONTEXT 9
718
+ #define COLOR_ACTIVEBORDER 10
719
+ #define COLOR_INACTIVEBORDER 11
720
+ #define COLOR_APPWORKSPACE 12
721
+ #define COLOR_HIGHLIGHT 13
722
+ #define COLOR_HIGHLIGHTTEXT 14
723
+ #define COLOR_BTNFACE 15
724
+ #define COLOR_BTNSHADOW 16
725
+ #define COLOR_GRAYTEXT 17
726
+ #define COLOR_BTNTEXT 18
727
+ #define COLOR_INACTIVECAPTIONTEXT 19
728
+ #define COLOR_BTNHIGHLIGHT 20
729
+ #define COLOR_3DDKSHADOW 21
730
+ #define COLOR_3DLIGHT 22
731
+ #define COLOR_INFOTEXT 23
732
+ #define COLOR_INFOBK 24
733
+ #define COLOR_HOTLIGHT 26
734
+ #define COLOR_GRADIENTACTIVECAPTION 27
735
+ #define COLOR_GRADIENTINACTIVECAPTION 28
736
+ #define COLOR_MENUHILIGHT 29
737
+ #define COLOR_MENUBAR 30
738
+ #define COLOR_DESKTOP COLOR_BACKGROUND
739
+ #define COLOR_3DFACE COLOR_BTNFACE
740
+ #define COLOR_3DSHADOW COLOR_BTNSHADOW
741
+ #define COLOR_3DHIGHLIGHT COLOR_BTNHIGHLIGHT
742
+ #define COLOR_3DHILIGHT COLOR_BTNHIGHLIGHT
743
+ #define COLOR_BTNHILIGHT COLOR_BTNHIGHLIGHT
744
+
745
+
746
+ WINUSERAPI DWORD WINAPI GetSysColor(__in int nIndex);
747
+
748
+
749
+ WINUSERAPI
750
+ int
751
+ WINAPI
752
+ GetSystemMetrics(
753
+ __in int nIndex);
754
+
755
+ typedef struct tagMSG {
756
+ HWND hwnd;
757
+ UINT message;
758
+ WPARAM wParam;
759
+ LPARAM lParam;
760
+ DWORD time;
761
+ POINT pt;
762
+ } MSG, *PMSG, *LPMSG;
763
+
764
+ WINUSERAPI
765
+ BOOL
766
+ WINAPI
767
+ GetMessageA(
768
+ __out LPMSG lpMsg,
769
+ __in_opt HWND hWnd,
770
+ __in UINT wMsgFilterMin,
771
+ __in UINT wMsgFilterMax);
772
+ WINUSERAPI
773
+ BOOL
774
+ WINAPI
775
+ PeekMessageA(
776
+ __out LPMSG lpMsg,
777
+ __in_opt HWND hWnd,
778
+ __in UINT wMsgFilterMin,
779
+ __in UINT wMsgFilterMax,
780
+ __in UINT wRemoveMsg);
781
+ WINUSERAPI
782
+ BOOL
783
+ WINAPI
784
+ TranslateMessage(
785
+ __in CONST MSG *lpMsg);
786
+ WINUSERAPI
787
+ LRESULT
788
+ WINAPI
789
+ DispatchMessageA(
790
+ __in CONST MSG *lpMsg);
791
+ #define MOD_ALT 0x0001
792
+ #define MOD_CONTROL 0x0002
793
+ #define MOD_SHIFT 0x0004
794
+ #define MOD_WIN 0x0008
795
+ WINUSERAPI
796
+ LRESULT
797
+ WINAPI
798
+ SendMessageA(
799
+ __in HWND hWnd,
800
+ __in UINT Msg,
801
+ __in WPARAM wParam,
802
+ __in LPARAM lParam);
803
+ WINUSERAPI
804
+ BOOL
805
+ WINAPI
806
+ PostMessageA(
807
+ __in_opt HWND hWnd,
808
+ __in UINT Msg,
809
+ __in WPARAM wParam,
810
+ __in LPARAM lParam);
811
+ WINUSERAPI
812
+ LRESULT
813
+ WINAPI
814
+ DefWindowProcA(
815
+ __in HWND hWnd,
816
+ __in UINT Msg,
817
+ __in WPARAM wParam,
818
+ __in LPARAM lParam);
819
+ WINUSERAPI
820
+ VOID
821
+ WINAPI
822
+ PostQuitMessage(
823
+ __in int nExitCode);
824
+ WINUSERAPI
825
+ DWORD
826
+ WINAPI
827
+ MsgWaitForMultipleObjects(
828
+ __in DWORD nCount,
829
+ __in_opt CONST HANDLE *pHandles,
830
+ __in BOOL fWaitAll,
831
+ __in DWORD dwMilliseconds,
832
+ __in DWORD dwWakeMask);
833
+ WINUSERAPI DWORD WINAPI GetKeyState(__in int nVirtKey);
834
+
835
+ WINUSERAPI BOOL WINAPI OpenClipboard(__in_opt HWND hWndNewOwner);
836
+ WINUSERAPI BOOL WINAPI CloseClipboard(VOID);
837
+ WINUSERAPI HANDLE WINAPI SetClipboardData(__in UINT uFormat, __in_opt HANDLE hMem);
838
+ WINUSERAPI HANDLE WINAPI GetClipboardData(__in UINT uFormat);
839
+ WINUSERAPI BOOL WINAPI EmptyClipboard(VOID);
840
+
841
+ #define GMEM_FIXED 0x0000
842
+ #define GMEM_MOVEABLE 0x0002
843
+ #define GMEM_NOCOMPACT 0x0010
844
+ #define GMEM_NODISCARD 0x0020
845
+ #define GMEM_ZEROINIT 0x0040
846
+ #define GMEM_MODIFY 0x0080
847
+ #define GMEM_DISCARDABLE 0x0100
848
+ #define GMEM_NOT_BANKED 0x1000
849
+ #define GMEM_SHARE 0x2000
850
+ #define GMEM_DDESHARE 0x2000
851
+ #define GMEM_NOTIFY 0x4000
852
+ #define GMEM_LOWER GMEM_NOT_BANKED
853
+ #define GMEM_INVALID_HANDLE 0x8000
854
+ HANDLE WINAPI GlobalAlloc(__in UINT uFlags, __in DWORD dwBytes);
855
+ DWORD WINAPI GlobalSize(__in HANDLE hMem);
856
+ LPVOID WINAPI GlobalLock(__in HANDLE hMem);
857
+ BOOL WINAPI GlobalUnlock(__in HANDLE hMem);
858
+ HANDLE WINAPI GlobalFree(HANDLE hMem);
859
+
860
+ typedef __stdcall LRESULT (*WNDPROC)(HWND, UINT, WPARAM, LPARAM);
861
+ typedef struct tagWNDCLASSEXA {
862
+ UINT cbSize;
863
+ UINT style;
864
+ WNDPROC lpfnWndProc;
865
+ int cbClsExtra;
866
+ int cbWndExtra;
867
+ HINSTANCE hInstance;
868
+ HICON hIcon;
869
+ HCURSOR hCursor;
870
+ HBRUSH hbrBackground;
871
+ LPCSTR lpszMenuName;
872
+ LPCSTR lpszClassName;
873
+ HICON hIconSm;
874
+ } WNDCLASSEXA;
875
+ WINUSERAPI
876
+ ATOM
877
+ WINAPI
878
+ RegisterClassExA(
879
+ __in CONST WNDCLASSEXA *);
880
+ WINUSERAPI
881
+ HWND
882
+ WINAPI
883
+ CreateWindowExA(
884
+ __in DWORD dwExStyle,
885
+ __in_opt LPCSTR lpClassName,
886
+ __in_opt LPCSTR lpWindowName,
887
+ __in DWORD dwStyle,
888
+ __in int X,
889
+ __in int Y,
890
+ __in int nWidth,
891
+ __in int nHeight,
892
+ __in_opt HWND hWndParent,
893
+ __in_opt HMENU hMenu,
894
+ __in_opt HINSTANCE hInstance,
895
+ __in_opt LPVOID lpParam);
896
+ WINUSERAPI
897
+ BOOL
898
+ WINAPI
899
+ DestroyWindow(
900
+ __in HWND hWnd);
901
+ WINUSERAPI
902
+ BOOL
903
+ WINAPI
904
+ ShowWindow(
905
+ __in HWND hWnd,
906
+ __in int nCmdShow);
907
+ WINUSERAPI
908
+ BOOL
909
+ WINAPI
910
+ CloseWindow(
911
+ __in HWND hWnd);
912
+ WINUSERAPI
913
+ BOOL
914
+ WINAPI
915
+ MoveWindow(
916
+ __in HWND hWnd,
917
+ __in int X,
918
+ __in int Y,
919
+ __in int nWidth,
920
+ __in int nHeight,
921
+ __in BOOL bRepaint);
922
+ WINUSERAPI
923
+ BOOL
924
+ WINAPI
925
+ SetWindowPos(
926
+ __in HWND hWnd,
927
+ __in_opt HWND hWndInsertAfter,
928
+ __in int X,
929
+ __in int Y,
930
+ __in int cx,
931
+ __in int cy,
932
+ __in UINT uFlags);
933
+ #define SRCCOPY (DWORD)0x00CC0020 /* dest = source */
934
+ #define SRCPAINT (DWORD)0x00EE0086 /* dest = source OR dest */
935
+ #define SRCAND (DWORD)0x008800C6 /* dest = source AND dest */
936
+ #define SRCINVERT (DWORD)0x00660046 /* dest = source XOR dest */
937
+ #define SRCERASE (DWORD)0x00440328 /* dest = source AND (NOT dest ) */
938
+ #define NOTSRCCOPY (DWORD)0x00330008 /* dest = (NOT source) */
939
+ #define NOTSRCERASE (DWORD)0x001100A6 /* dest = (NOT src) AND (NOT dest) */
940
+ #define MERGECOPY (DWORD)0x00C000CA /* dest = (source AND pattern) */
941
+ #define MERGEPAINT (DWORD)0x00BB0226 /* dest = (NOT source) OR dest */
942
+ #define PATCOPY (DWORD)0x00F00021 /* dest = pattern */
943
+ #define PATPAINT (DWORD)0x00FB0A09 /* dest = DPSnoo */
944
+ #define PATINVERT (DWORD)0x005A0049 /* dest = pattern XOR dest */
945
+ #define DSTINVERT (DWORD)0x00550009 /* dest = (NOT dest) */
946
+ #define BLACKNESS (DWORD)0x00000042 /* dest = BLACK */
947
+ #define WHITENESS (DWORD)0x00FF0062 /* dest = WHITE */
948
+ #define NOMIRRORBITMAP (DWORD)0x80000000 /* Do not Mirror the bitmap in this call */
949
+ #define CAPTUREBLT (DWORD)0x40000000 /* Include layered windows */
950
+ BOOL WINAPI BitBlt(__in HDC hdcDst, __in int x, __in int y, __in int cx, __in int cy, __in_opt HDC hdcSrc, __in int x1, __in int y1, __in DWORD rop);
951
+ HBITMAP WINAPI CreateCompatibleBitmap(__in HDC hdc, __in int cx, __in int cy);
952
+ HDC WINAPI CreateCompatibleDC(__in_opt HDC hdc);
953
+ BOOL WINAPI DeleteDC(__in HDC hdc);
954
+ HDC WINAPI GetDC(__in_opt HWND hWnd);
955
+ int WINAPI ReleaseDC(__in_opt HWND hWnd, __in HDC hDC);
956
+ BOOL
957
+ WINAPI
958
+ GetTextExtentPoint32A(
959
+ __in HDC hdc,
960
+ __in_ecount(c) LPCSTR lpString,
961
+ __in int c,
962
+ __out LPPOINT lpsz);
963
+ WINUSERAPI
964
+ BOOL
965
+ WINAPI
966
+ SetMenu(
967
+ __in HWND hWnd,
968
+ __in_opt HMENU hMenu);
969
+ WINUSERAPI
970
+ HMENU
971
+ WINAPI
972
+ CreateMenu(VOID);
973
+ WINUSERAPI
974
+ HMENU
975
+ WINAPI
976
+ CreatePopupMenu(VOID);
977
+ WINUSERAPI
978
+ BOOL
979
+ WINAPI
980
+ DestroyMenu(
981
+ __in HMENU hMenu);
982
+ WINUSERAPI
983
+ DWORD
984
+ WINAPI
985
+ CheckMenuItem(
986
+ __in HMENU hMenu,
987
+ __in UINT uIDCheckItem,
988
+ __in UINT uCheck);
989
+ WINUSERAPI
990
+ BOOL
991
+ WINAPI
992
+ AppendMenuA(
993
+ __in HMENU hMenu,
994
+ __in UINT uFlags,
995
+ __in UINT_PTR uIDNewItem,
996
+ __in_opt LPCSTR lpNewItem);
997
+
998
+ #define TRANSPARENT 1
999
+ #define OPAQUE 2
1000
+ int WINAPI SetBkMode(__in HDC hdc, __in int mode);
1001
+
1002
+ typedef struct tagRECT {
1003
+ LONG left;
1004
+ LONG top;
1005
+ LONG right;
1006
+ LONG bottom;
1007
+ } RECT, *LPRECT;
1008
+
1009
+ WINUSERAPI
1010
+ int
1011
+ WINAPI
1012
+ DrawTextA(
1013
+ __in HDC hdc,
1014
+ __inout_ecount(cchText) LPCSTR lpchText,
1015
+ __in int cchText,
1016
+ __inout LPRECT lprc,
1017
+ __in UINT format);
1018
+
1019
+ typedef struct tagPAINTSTRUCT {
1020
+ HDC hdc;
1021
+ BOOL fErase;
1022
+ RECT rcPaint;
1023
+ BOOL fRestore;
1024
+ BOOL fIncUpdate;
1025
+ BYTE rgbReserved[32];
1026
+ } PAINTSTRUCT, *LPPAINTSTRUCT;
1027
+ WINUSERAPI
1028
+ HDC
1029
+ WINAPI
1030
+ BeginPaint(
1031
+ __in HWND hWnd,
1032
+ __out LPPAINTSTRUCT lpPaint);
1033
+ WINUSERAPI
1034
+ BOOL
1035
+ WINAPI
1036
+ EndPaint(
1037
+ __in HWND hWnd,
1038
+ __in CONST PAINTSTRUCT *lpPaint);
1039
+ WINUSERAPI
1040
+ BOOL
1041
+ WINAPI
1042
+ InvalidateRect(
1043
+ __in_opt HWND hWnd,
1044
+ __in_opt CONST RECT *lpRect,
1045
+ __in BOOL bErase);
1046
+ WINUSERAPI
1047
+ BOOL
1048
+ WINAPI
1049
+ SetWindowTextA(
1050
+ __in HWND hWnd,
1051
+ __in_opt LPCSTR lpString);
1052
+ WINUSERAPI
1053
+ int
1054
+ WINAPI
1055
+ GetWindowTextA(
1056
+ __in HWND hWnd,
1057
+ __out_ecount(nMaxCount) LPSTR lpString,
1058
+ __in int nMaxCount);
1059
+ WINUSERAPI
1060
+ int
1061
+ WINAPI
1062
+ MessageBoxA(
1063
+ __in_opt HWND hWnd,
1064
+ __in_opt LPCSTR lpText,
1065
+ __in_opt LPCSTR lpCaption,
1066
+ __in UINT uType);
1067
+
1068
+ WINUSERAPI
1069
+ HICON
1070
+ WINAPI
1071
+ LoadIconA(
1072
+ __in_opt HINSTANCE hInstance,
1073
+ __in LPCSTR lpIconName);
1074
+ WINUSERAPI
1075
+ HCURSOR
1076
+ WINAPI
1077
+ LoadCursorA(
1078
+ __in_opt HINSTANCE hInstance,
1079
+ __in LPCSTR lpCursorName);
1080
+ WINAPI PVOID GetStockObject(__in int i);
1081
+ WINUSERAPI
1082
+ BOOL
1083
+ WINAPI
1084
+ UpdateWindow(
1085
+ __in HWND hWnd);
1086
+ WINUSERAPI
1087
+ BOOL
1088
+ WINAPI
1089
+ GetClientRect(
1090
+ __in HWND hWnd,
1091
+ __out LPRECT lpRect);
1092
+ WINUSERAPI
1093
+ BOOL
1094
+ WINAPI
1095
+ GetWindowRect(
1096
+ __in HWND hWnd,
1097
+ __out LPRECT lpRect);
1098
+ WINUSERAPI
1099
+ BOOL
1100
+ WINAPI
1101
+ AdjustWindowRect(
1102
+ __inout LPRECT lpRect,
1103
+ __in DWORD dwStyle,
1104
+ __in BOOL bMenu);
1105
+ WINUSERAPI
1106
+ BOOL
1107
+ WINAPI
1108
+ AdjustWindowRectEx(
1109
+ __inout LPRECT lpRect,
1110
+ __in DWORD dwStyle,
1111
+ __in BOOL bMenu,
1112
+ __in DWORD dwExStyle);
1113
+ #define PS_SOLID 0
1114
+ #define PS_DASH 1 /* ------- */
1115
+ #define PS_DOT 2 /* ....... */
1116
+ #define PS_DASHDOT 3 /* _._._._ */
1117
+ #define PS_DASHDOTDOT 4 /* _.._.._ */
1118
+ #define PS_NULL 5
1119
+ #define PS_INSIDEFRAME 6
1120
+ #define PS_USERSTYLE 7
1121
+ #define PS_ALTERNATE 8
1122
+ DWORD WINAPI SetTextColor(__in HDC hdc, __in DWORD color);
1123
+ BOOL WINAPI TextOutA( __in HDC hdc, __in int x, __in int y, __in_ecount(c) LPCSTR lpString, __in int c);
1124
+ BOOL WINAPI MoveToEx( __in HDC hdc, __in int x, __in int y, __out_opt LPPOINT lppt);
1125
+ BOOL WINAPI LineTo( __in HDC hdc, __in int x, __in int y);
1126
+ BOOL WINAPI Rectangle(__in HDC hdc, __in int left, __in int top, __in int right, __in int bottom);
1127
+ HANDLE WINAPI SelectObject(__in HDC hdc, __in HANDLE h);
1128
+ BOOL WINAPI DeleteObject(__in HANDLE ho);
1129
+ DWORD WINAPI SetBkColor(__in HDC hdc, __in DWORD color);
1130
+ HANDLE WINAPI CreateSolidBrush(__in DWORD color);
1131
+ //DWORD WINAPI SetDCBrushColor(__in HDC hdc, __in DWORD color);
1132
+ HANDLE WINAPI CreatePen(__in int style, __in int width, __in DWORD color);
1133
+ //DWORD WINAPI SetDCPenColor(__in HDC hdc, __in DWORD color);
1134
+ int WINAPI FillRect(__in HDC hDC, __in CONST RECT *lprc, __in HBRUSH hbr);
1135
+
1136
+ WINUSERAPI HWND WINAPI GetCapture(VOID);
1137
+ WINUSERAPI HWND WINAPI SetCapture(__in HWND hWnd);
1138
+ WINUSERAPI BOOL WINAPI ReleaseCapture(VOID);
1139
+
1140
+ #define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100
1141
+ #define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200
1142
+ #define FORMAT_MESSAGE_FROM_STRING 0x00000400
1143
+ #define FORMAT_MESSAGE_FROM_HMODULE 0x00000800
1144
+ #define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
1145
+ #define FORMAT_MESSAGE_ARGUMENT_ARRAY 0x00002000
1146
+ #define FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF
1147
+
1148
+ DWORD
1149
+ WINAPI
1150
+ GetLastError(VOID);
1151
+ VOID
1152
+ WINAPI
1153
+ SetLastError(
1154
+ __in DWORD dwErrCode
1155
+ );
1156
+ DWORD
1157
+ WINAPI
1158
+ FormatMessageA(
1159
+ DWORD dwFlags,
1160
+ LPVOID lpSource,
1161
+ DWORD dwMessageId,
1162
+ DWORD dwLanguageId,
1163
+ LPSTR lpBuffer,
1164
+ DWORD nSize,
1165
+ void *Arguments
1166
+ );
1167
+
1168
+ #define OFN_READONLY 0x00000001
1169
+ #define OFN_OVERWRITEPROMPT 0x00000002
1170
+ #define OFN_HIDEREADONLY 0x00000004
1171
+ #define OFN_NOCHANGEDIR 0x00000008
1172
+ #define OFN_SHOWHELP 0x00000010
1173
+ #define OFN_ENABLEHOOK 0x00000020
1174
+ #define OFN_ENABLETEMPLATE 0x00000040
1175
+ #define OFN_ENABLETEMPLATEHANDLE 0x00000080
1176
+ #define OFN_NOVALIDATE 0x00000100
1177
+ #define OFN_ALLOWMULTISELECT 0x00000200
1178
+ #define OFN_EXTENSIONDIFFERENT 0x00000400
1179
+ #define OFN_PATHMUSTEXIST 0x00000800
1180
+ #define OFN_FILEMUSTEXIST 0x00001000
1181
+ #define OFN_CREATEPROMPT 0x00002000
1182
+ #define OFN_SHAREAWARE 0x00004000
1183
+ #define OFN_NOREADONLYRETURN 0x00008000
1184
+ #define OFN_NOTESTFILECREATE 0x00010000
1185
+ #define OFN_NONETWORKBUTTON 0x00020000
1186
+ #define OFN_NOLONGNAMES 0x00040000 // force no long names for 4.x modules
1187
+ #define OFN_EXPLORER 0x00080000 // new look commdlg
1188
+ #define OFN_NODEREFERENCELINKS 0x00100000
1189
+ #define OFN_LONGNAMES 0x00200000 // force long names for 3.x modules
1190
+ #define OFN_ENABLEINCLUDENOTIFY 0x00400000 // send include message to callback
1191
+ #define OFN_ENABLESIZING 0x00800000
1192
+ #define OFN_DONTADDTORECENT 0x02000000
1193
+ #define OFN_FORCESHOWHIDDEN 0x10000000 // Show All files including System and hidden files
1194
+ typedef struct tagOFNA {
1195
+ DWORD lStructSize;
1196
+ HWND hwndOwner;
1197
+ HINSTANCE hInstance;
1198
+ LPCSTR lpstrFilter;
1199
+ LPSTR lpstrCustomFilter;
1200
+ DWORD nMaxCustFilter;
1201
+ DWORD nFilterIndex;
1202
+ LPSTR lpstrFile;
1203
+ DWORD nMaxFile;
1204
+ LPSTR lpstrFileTitle;
1205
+ DWORD nMaxFileTitle;
1206
+ LPCSTR lpstrInitialDir;
1207
+ LPCSTR lpstrTitle;
1208
+ DWORD Flags;
1209
+ WORD nFileOffset;
1210
+ WORD nFileExtension;
1211
+ LPCSTR lpstrDefExt;
1212
+ LPARAM lCustData;
1213
+ LPVOID lpfnHook;
1214
+ LPCSTR lpTemplateName;
1215
+ //void * pvReserved; // undef for win98 compat
1216
+ //DWORD dwReserved;
1217
+ //DWORD FlagsEx;
1218
+ } OPENFILENAMEA, *LPOPENFILENAMEA;
1219
+ BOOL WINAPI GetOpenFileNameA(LPOPENFILENAMEA);
1220
+ BOOL WINAPI GetSaveFileNameA(LPOPENFILENAMEA);
1221
+
1222
+ #define SB_HORZ 0
1223
+ #define SB_VERT 1
1224
+ #define SB_CTL 2
1225
+ #define SB_BOTH 3
1226
+
1227
+ #define SB_LINEUP 0
1228
+ #define SB_LINELEFT 0
1229
+ #define SB_LINEDOWN 1
1230
+ #define SB_LINERIGHT 1
1231
+ #define SB_PAGEUP 2
1232
+ #define SB_PAGELEFT 2
1233
+ #define SB_PAGEDOWN 3
1234
+ #define SB_PAGERIGHT 3
1235
+ #define SB_THUMBPOSITION 4
1236
+ #define SB_THUMBTRACK 5
1237
+ #define SB_TOP 6
1238
+ #define SB_LEFT 6
1239
+ #define SB_BOTTOM 7
1240
+ #define SB_RIGHT 7
1241
+ #define SB_ENDSCROLL 8
1242
+
1243
+ #define SIF_RANGE 0x0001
1244
+ #define SIF_PAGE 0x0002
1245
+ #define SIF_POS 0x0004
1246
+ #define SIF_DISABLENOSCROLL 0x0008
1247
+ #define SIF_TRACKPOS 0x0010
1248
+ #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
1249
+
1250
+ WINUSERAPI
1251
+ int
1252
+ WINAPI
1253
+ SetScrollPos(
1254
+ __in HWND hWnd,
1255
+ __in int nBar,
1256
+ __in int nPos,
1257
+ __in BOOL bRedraw);
1258
+
1259
+ WINUSERAPI
1260
+ int
1261
+ WINAPI
1262
+ GetScrollPos(
1263
+ __in HWND hWnd,
1264
+ __in int nBar);
1265
+
1266
+ typedef struct tagSCROLLINFO
1267
+ {
1268
+ UINT cbSize;
1269
+ UINT fMask;
1270
+ int nMin;
1271
+ int nMax;
1272
+ UINT nPage;
1273
+ int nPos;
1274
+ int nTrackPos;
1275
+ } SCROLLINFO, *LPSCROLLINFO;
1276
+ typedef SCROLLINFO CONST *LPCSCROLLINFO;
1277
+
1278
+ WINUSERAPI
1279
+ int
1280
+ WINAPI
1281
+ SetScrollInfo(
1282
+ __in HWND hwnd,
1283
+ __in int nBar,
1284
+ __in LPCSCROLLINFO lpsi,
1285
+ __in BOOL redraw);
1286
+
1287
+ WINUSERAPI
1288
+ BOOL
1289
+ WINAPI
1290
+ GetScrollInfo(
1291
+ __in HWND hwnd,
1292
+ __in int nBar,
1293
+ __inout LPSCROLLINFO lpsi);
1294
+ EOS
1295
+
1296
+ new_api_c <<EOS, 'shell32'
1297
+ typedef HANDLE HDROP;
1298
+ WINAPI UINT DragQueryFileA(HDROP,UINT,LPSTR,UINT);
1299
+ WINAPI BOOL DragQueryPoint(HDROP,LPPOINT);
1300
+ WINAPI void DragFinish(HDROP);
1301
+ WINAPI void DragAcceptFiles(HWND,BOOL);
1302
+ EOS
1303
+
1304
+ def self.last_error_msg(errno = getlasterror)
1305
+ message = ' '*512
1306
+ if formatmessagea(FORMAT_MESSAGE_FROM_SYSTEM, nil, errno, 0, message, message.length, nil) == 0
1307
+ message = 'unknown error %x' % errno
1308
+ else
1309
+ message = message[0, message.index(?\0)] if message.index(?\0)
1310
+ message.chomp!
1311
+ end
1312
+ message
1313
+ end
1314
+
1315
+ def self.setdcbrushcolor(hdc, col)
1316
+ @@brushes ||= {}
1317
+ b = @@brushes[col] ||= createsolidbrush(col)
1318
+ selectobject(hdc, b)
1319
+ end
1320
+ def self.setdcpencolor(hdc, col)
1321
+ @@pens ||= {}
1322
+ p = @@pens[col] ||= createpen(PS_SOLID, 0, col)
1323
+ selectobject(hdc, p)
1324
+ end
1325
+ end
1326
+
1327
+ module Protect
1328
+ @@lasterror = Time.now
1329
+ def protect
1330
+ yield
1331
+ rescue Object
1332
+ puts $!.message, $!.backtrace # also dump on stdout, for c/c
1333
+ delay = Time.now-@@lasterror
1334
+ sleep 1-delay if delay < 1 # msgbox flood protection
1335
+ @@lasterror = Time.now
1336
+ messagebox([$!.message, $!.backtrace].join("\n"), $!.class.name)
1337
+ end
1338
+ end
1339
+
1340
+ module Msgbox
1341
+ include Protect
1342
+
1343
+ def toplevel
1344
+ p = self
1345
+ p = p.parent while p.respond_to? :parent and p.parent
1346
+ p
1347
+ end
1348
+
1349
+ # shows a message box (non-modal)
1350
+ # args: message, title/optionhash
1351
+ def messagebox(*a)
1352
+ MessageBox.new(toplevel, *a)
1353
+ end
1354
+
1355
+ # asks for user input, yields the result (unless 'cancel' clicked)
1356
+ # args: prompt, :text => default text, :title => title
1357
+ def inputbox(*a)
1358
+ InputBox.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
1359
+ end
1360
+
1361
+ # asks to chose a file to open, yields filename
1362
+ # args: title, :path => path
1363
+ def openfile(*a)
1364
+ OpenFile.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
1365
+ end
1366
+
1367
+ # same as openfile, but for writing a (new) file
1368
+ def savefile(*a)
1369
+ SaveFile.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
1370
+ end
1371
+
1372
+ # displays a popup showing a table, yields the selected row
1373
+ # args: title, [[col0 title, col1 title...], [col0 val0, col1 val0...], [val1], [val2]...]
1374
+ def listwindow(*a)
1375
+ ListWindow.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
1376
+ end
1377
+ end
1378
+
1379
+ class WinWidget
1380
+ include Msgbox
1381
+ attr_accessor :parent, :hwnd, :x, :y, :width, :height
1382
+
1383
+ def initialize
1384
+ @parent = nil
1385
+ @hwnd = nil
1386
+ @x = @y = @width = @height = 0
1387
+ end
1388
+
1389
+ def grab_focus
1390
+ return if not @parent
1391
+ @parent.set_focus(self) if @parent.respond_to? :set_focus
1392
+ end
1393
+
1394
+ def focus?
1395
+ return true if not @parent
1396
+ (@parent.respond_to?(:focus?) ? @parent.focus? : true) and
1397
+ (@parent.respond_to?(:has_focus?) ? @parent.has_focus?(self) : true)
1398
+ end
1399
+
1400
+ def redraw
1401
+ invalidate(0, 0, @width, @height)
1402
+ end
1403
+
1404
+ def invalidate(x, y, w, h)
1405
+ x += @x
1406
+ y += @y
1407
+ rect = Win32Gui.alloc_c_struct('RECT', :left => x, :right => x+w, :top => y, :bottom => y+h)
1408
+ Win32Gui.invalidaterect(@hwnd, rect, Win32Gui::FALSE)
1409
+ end
1410
+ end
1411
+
1412
+ class ContainerChoiceWidget < WinWidget
1413
+ attr_accessor :views, :view_indexes
1414
+ def initialize(*a, &b)
1415
+ @views = {}
1416
+ @view_indexes = []
1417
+ @curview = nil
1418
+ @visible = false
1419
+
1420
+ super()
1421
+
1422
+ initialize_widget(*a, &b)
1423
+ end
1424
+
1425
+ def initialize_visible_
1426
+ @visible = true
1427
+ @views.each { |k, v| v.initialize_visible_ }
1428
+ end
1429
+
1430
+ def view(i)
1431
+ @views[i]
1432
+ end
1433
+
1434
+ def showview(i)
1435
+ @curview = @views[i]
1436
+ @curview.redraw if @curview
1437
+ end
1438
+
1439
+ def addview(name, w)
1440
+ @view_indexes << name
1441
+ @views[name] = w
1442
+ @curview ||= w
1443
+ w.parent = self
1444
+ w.hwnd = @hwnd
1445
+ w.x, w.y, w.width, w.height = @x, @y, @width, @height
1446
+ w.initialize_visible_ if @visible
1447
+ w
1448
+ end
1449
+
1450
+ def curview
1451
+ @curview
1452
+ end
1453
+
1454
+ def curview_index
1455
+ @views.index(@curview)
1456
+ end
1457
+
1458
+ %w[click click_ctrl mouserelease mousemove rightclick doubleclick mouse_wheel mouse_wheel_ctrl keypress_ keypress_ctrl_].each { |m|
1459
+ define_method(m) { |*a| @curview.send(m, *a) if @curview and @curview.respond_to? m }
1460
+ }
1461
+
1462
+ def paint_(rc)
1463
+ @curview.paint_(rc) if @curview
1464
+ end
1465
+
1466
+ def resized_(w, h)
1467
+ @width = w
1468
+ @height = h
1469
+ @views.each { |k, v|
1470
+ v.x = @x
1471
+ v.y = @y
1472
+ v.resized_(w, h)
1473
+ }
1474
+ end
1475
+
1476
+ def hwnd=(h)
1477
+ @hwnd = h
1478
+ @views.each { |k, v| v.hwnd = h }
1479
+ end
1480
+
1481
+ def has_focus?(c)
1482
+ c == @curview
1483
+ end
1484
+
1485
+ def set_focus(c)
1486
+ @curview = c
1487
+ redraw
1488
+ end
1489
+ end
1490
+
1491
+ class ContainerVBoxWidget < WinWidget
1492
+ def initialize(*a, &b)
1493
+ @views = []
1494
+ @focus_idx = 0
1495
+ @visible = false
1496
+ @wantheight = {}
1497
+ @spacing = 3
1498
+ @resizing = nil
1499
+
1500
+ super()
1501
+
1502
+ initialize_widget(*a, &b)
1503
+ end
1504
+
1505
+ def initialize_visible_
1506
+ @visible = true
1507
+ @views.each { |v| v.initialize_visible_ }
1508
+ end
1509
+
1510
+ def add(w, opts={})
1511
+ @views << w
1512
+ w.parent = self
1513
+ w.hwnd = @hwnd
1514
+ resized_(@width, @height)
1515
+ w.initialize_visible_ if @visible
1516
+ end
1517
+
1518
+ def click(x, y)
1519
+ cy = 0
1520
+ pv = []
1521
+ @views.each_with_index { |v, i|
1522
+ if y >= cy and y < cy + v.height
1523
+ if @focus_idx != i
1524
+ @focus_idx = i
1525
+ redraw
1526
+ end
1527
+ v.click(x, y-v.y) if v.respond_to? :click
1528
+ return
1529
+ end
1530
+ cy += v.height
1531
+ if y >= cy and y < cy+@spacing
1532
+ vsz = v
1533
+ @resizing = v
1534
+ @wantheight[@resizing] ||= v.height
1535
+ @tmpwantheight = []
1536
+ pv.each { |vv| @tmpwantheight << vv if not @wantheight[vv] ; @wantheight[vv] ||= vv.height }
1537
+ return
1538
+ end
1539
+ cy += @spacing
1540
+ pv << v
1541
+ }
1542
+ end
1543
+
1544
+ def mousemove(x, y)
1545
+ if @resizing
1546
+ @wantheight[@resizing] = [0, y - @resizing.y].max
1547
+ resized_(@width, @height)
1548
+ elsif v = @views[@focus_idx]
1549
+ v.mousemove(x, y-v.y) if v.respond_to? :mousemove
1550
+ end
1551
+ end
1552
+
1553
+ def mouserelease(x, y)
1554
+ if @resizing
1555
+ @wantheight[@resizing] = [0, y - @resizing.y].max
1556
+ @resizing = nil
1557
+ @tmpwantheight.each { |vv| @wantheight.delete vv }
1558
+ @tmpwantheight = nil
1559
+ resized_(@width, @height)
1560
+ elsif v = @views[@focus_idx]
1561
+ v.mouserelease(x, y-v.y) if v.respond_to? :mouserelease
1562
+ end
1563
+ end
1564
+
1565
+ %w[click_ctrl rightclick doubleclick].each { |m|
1566
+ define_method(m) { |x, y|
1567
+ if v = find_view_y(y, true)
1568
+ v.send(m, x, y-v.y) if v.respond_to? m
1569
+ end
1570
+ }
1571
+ }
1572
+
1573
+ %w[mouse_wheel mouse_wheel_ctrl].each { |m|
1574
+ define_method(m) { |d, x, y|
1575
+ if v = find_view_y(y, false)
1576
+ v.send(m, d, x, y-v.y) if v.respond_to? m
1577
+ end
1578
+ }
1579
+ }
1580
+ %w[keypress_ keypress_ctrl_].each { |m|
1581
+ define_method(m) { |k|
1582
+ if v = @views[@focus_idx] and v.respond_to? m
1583
+ v.send(m, k)
1584
+ end
1585
+ }
1586
+ }
1587
+
1588
+ def paint_(hdc)
1589
+ # TODO check invalidated rectangle
1590
+ x = @x
1591
+ y = @y
1592
+ Win32Gui.selectobject(hdc, Win32Gui.getstockobject(Win32Gui::DC_BRUSH))
1593
+ Win32Gui.selectobject(hdc, Win32Gui.getstockobject(Win32Gui::DC_PEN))
1594
+ col = Win32Gui.getsyscolor(Win32Gui::COLOR_BTNFACE)
1595
+ Win32Gui.setdcbrushcolor(hdc, col)
1596
+ Win32Gui.setdcpencolor(hdc, col)
1597
+ @views.each { |v|
1598
+ v.paint_(hdc) if v.height > 0
1599
+ y += v.height
1600
+ Win32Gui.rectangle(hdc, x, y, x+@width, y+@spacing)
1601
+ y += @spacing
1602
+ }
1603
+ Win32Gui.rectangle(hdc, x, y, x+@width, y+@height)
1604
+ end
1605
+
1606
+ def resized_(w, h)
1607
+ @width = w
1608
+ @height = h
1609
+ x = @x
1610
+ y = @y
1611
+ freesize = h
1612
+ freesize -= @spacing*(@views.length-1)
1613
+ nrfree = 0
1614
+ @views.each { |v|
1615
+ if @wantheight[v]
1616
+ freesize -= @wantheight[v]
1617
+ else
1618
+ nrfree += 1
1619
+ end
1620
+ }
1621
+ freesize = 0 if freesize < 0
1622
+ @views.each { |v|
1623
+ v.x = x
1624
+ v.y = y
1625
+ ch = @wantheight[v] || freesize/nrfree
1626
+ v.resized_(w, ch)
1627
+ y += ch + @spacing
1628
+ }
1629
+ redraw
1630
+ end
1631
+
1632
+ def find_view_y(ty, update_focus=false)
1633
+ y = 0
1634
+ @views.each_with_index { |v, i|
1635
+ if ty >= y and ty < y + v.height
1636
+ if update_focus and @focus_idx != i
1637
+ @focus_idx = i
1638
+ redraw
1639
+ end
1640
+ return v
1641
+ end
1642
+ y += v.height + @spacing
1643
+ }
1644
+ nil
1645
+ end
1646
+
1647
+ def hwnd=(h)
1648
+ @hwnd = h
1649
+ @views.each { |v| v.hwnd = h }
1650
+ end
1651
+
1652
+ def resize_child(cld, w, h)
1653
+ return if @wantheight[cld] == h
1654
+ if h < 0
1655
+ @wantheight.delete cld
1656
+ else
1657
+ @wantheight[cld] = h
1658
+ end
1659
+ resized_(@width, @height)
1660
+ end
1661
+
1662
+ def has_focus?(c)
1663
+ c == @views[@focus_idx]
1664
+ end
1665
+
1666
+ def set_focus(c)
1667
+ @focus_idx = @views.index(c)
1668
+ redraw
1669
+ end
1670
+ end
1671
+
1672
+ module TextWidget
1673
+ attr_accessor :caret_x, :caret_y, :hl_word, :font_width, :font_height
1674
+
1675
+ def initialize_text
1676
+ @caret_x = @caret_y = 0 # text cursor position
1677
+ @oldcaret_x = @oldcaret_y = 1
1678
+ @font_width = @font_height = 1
1679
+ @hl_word = nil
1680
+ end
1681
+
1682
+ def update_hl_word(line, offset)
1683
+ return if not line
1684
+ word = line[0...offset].to_s[/\w*$/] << line[offset..-1].to_s[/^\w*/]
1685
+ word = nil if word == ''
1686
+ @hl_word = word if @hl_word != word
1687
+ end
1688
+
1689
+ def set_caret_from_click(x, y)
1690
+ @caret_x = (x-1).to_i / @font_width
1691
+ @caret_y = y.to_i / @font_height
1692
+ update_caret
1693
+ end
1694
+
1695
+ def invalidate_caret(cx, cy, x=0, y=0)
1696
+ invalidate(x + cx*@font_width, y + cy*@font_height, 2, @font_height)
1697
+ end
1698
+
1699
+ def clipboard_copy(buf)
1700
+ Win32Gui.openclipboard(@hwnd)
1701
+ Win32Gui.emptyclipboard
1702
+ if buf and not buf.empty?
1703
+ h = Win32Gui.globalalloc(Win32Gui::GMEM_MOVEABLE, buf.length+1)
1704
+ ptr = Win32Gui.globallock(h)
1705
+ Win32Gui.memory_write(ptr, buf)
1706
+ Win32Gui.globalunlock(h)
1707
+ Win32Gui.setclipboarddata(Win32Gui::CF_TEXT, h)
1708
+ # on(WM_DESTROYCLIPBOARD) { Win32Gui.globalfree(h) }
1709
+ end
1710
+ Win32Gui.closeclipboard
1711
+ end
1712
+
1713
+ def clipboard_paste
1714
+ Win32Gui.openclipboard(@hwnd)
1715
+ h = Win32Gui.getclipboarddata(Win32Gui::CF_TEXT)
1716
+ if h and h != 0 and h != Win32Gui::GMEM_INVALID_HANDLE
1717
+ sz = Win32Gui.globalsize(h)
1718
+ ptr = Win32Gui.globallock(h)
1719
+ buf = Win32Gui.memory_read(ptr, sz)
1720
+ Win32Gui.globalunlock(h)
1721
+ Win32Gui.closeclipboard
1722
+ buf.chomp(0.chr)
1723
+ end
1724
+ end
1725
+
1726
+ def set_font(todo)
1727
+ hdc = Win32Gui.getdc(@hwnd)
1728
+ # selectobject(hdc, hfont)
1729
+ sz = Win32Gui.alloc_c_struct('POINT')
1730
+ Win32Gui.gettextextentpoint32a(hdc, 'x', 1, sz)
1731
+ @font_width = sz[:x]
1732
+ @font_height = sz[:y]
1733
+ Win32Gui.releasedc(@hwnd, hdc)
1734
+ end
1735
+ end
1736
+
1737
+ class DrawableWidget < WinWidget
1738
+ include TextWidget
1739
+
1740
+ attr_accessor :buttons
1741
+
1742
+ def initialize(*a, &b)
1743
+ @color = {}
1744
+ @default_color_association = { :background => :winbg }
1745
+ @buttons = nil
1746
+
1747
+ super()
1748
+
1749
+ initialize_text
1750
+ initialize_widget(*a, &b)
1751
+ end
1752
+
1753
+ def initialize_widget
1754
+ end
1755
+
1756
+ def initialize_visible_
1757
+ { :white => 'fff', :palegrey => 'ddd', :black => '000', :grey => '444',
1758
+ :red => 'f00', :darkred => '800', :palered => 'fcc',
1759
+ :green => '0f0', :darkgreen => '080', :palegreen => 'cfc',
1760
+ :blue => '00f', :darkblue => '008', :paleblue => 'ccf',
1761
+ :yellow => 'ff0', :darkyellow => '440', :paleyellow => 'ffc',
1762
+ }.each { |tag, val|
1763
+ @color[tag] = color(val)
1764
+ }
1765
+ @color[:winbg] = Win32Gui.getsyscolor(Win32Gui::COLOR_BTNFACE)
1766
+ set_color_association(@default_color_association) # should be called after Gui.main
1767
+ set_font('courier 10')
1768
+ initialize_visible if respond_to? :initialize_visible
1769
+ end
1770
+
1771
+ def set_color_association(h)
1772
+ h.each { |k, v| @color[k] = color(v) }
1773
+ gui_update
1774
+ end
1775
+
1776
+ def paint_(realhdc)
1777
+ @hdc = Win32Gui.createcompatibledc(realhdc)
1778
+ bmp = Win32Gui.createcompatiblebitmap(realhdc, @width, @height)
1779
+ Win32Gui.selectobject(@hdc, bmp)
1780
+ Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::DC_BRUSH))
1781
+ Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::DC_PEN))
1782
+ Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::ANSI_FIXED_FONT))
1783
+ Win32Gui.setbkmode(@hdc, Win32Gui::TRANSPARENT)
1784
+ draw_rectangle_color(:background, 0, 0, @width, @height)
1785
+ paint
1786
+ Win32Gui.bitblt(realhdc, @x, @y, @width, @height, @hdc, 0, 0, Win32Gui::SRCCOPY)
1787
+ Win32Gui.deleteobject(bmp)
1788
+ Win32Gui.deletedc(@hdc)
1789
+ @hdc = nil
1790
+ end
1791
+
1792
+ def resized_(w, h)
1793
+ @width = w
1794
+ @height = h
1795
+ resized(w, h) if respond_to? :resized
1796
+ end
1797
+
1798
+ def keypress_(key)
1799
+ # XXX my gtk api sux
1800
+ if not respond_to? :keypress or not protect { keypress(key) }
1801
+ protect { @parent.keypress(key) } if @parent.respond_to? :keypress
1802
+ end
1803
+ end
1804
+
1805
+ def keypress_ctrl_(key)
1806
+ if not respond_to? :keypress_ctrl or not protect { keypress_ctrl(key) }
1807
+ protect { @parent.keypress_ctrl(key) } if @parent.respond_to? :keypress_ctrl
1808
+ end
1809
+ end
1810
+
1811
+ def gui_update
1812
+ redraw
1813
+ end
1814
+
1815
+ def color(col)
1816
+ @color[col] ||= col.sub(/^(\w)(\w)(\w)$/, '\\3\\3\\2\\2\\1\\1').to_i(16)
1817
+ end
1818
+
1819
+ def draw_color(col)
1820
+ col = color(col)
1821
+ Win32Gui.settextcolor(@hdc, col)
1822
+ Win32Gui.setdcpencolor(@hdc, col)
1823
+ Win32Gui.setdcbrushcolor(@hdc, col)
1824
+ end
1825
+
1826
+ def draw_line(x, y, ex, ey)
1827
+ Win32Gui.movetoex(@hdc, x, y, 0)
1828
+ Win32Gui.lineto(@hdc, ex, ey)
1829
+ end
1830
+
1831
+ def draw_line_color(col, x, y, ex, ey)
1832
+ Win32Gui.setdcpencolor(@hdc, color(col))
1833
+ draw_line(x, y, ex, ey)
1834
+ end
1835
+
1836
+ def draw_rectangle(x, y, w, h)
1837
+ Win32Gui.rectangle(@hdc, x, y, x+w, y+h)
1838
+ end
1839
+
1840
+ def draw_rectangle_color(col, x, y, w, h)
1841
+ Win32Gui.setdcbrushcolor(@hdc, color(col))
1842
+ Win32Gui.setdcpencolor(@hdc, color(col)) # rect border
1843
+ draw_rectangle(x, y, w, h)
1844
+ end
1845
+
1846
+ def draw_string(x, y, text)
1847
+ return if not text or text == ''
1848
+ Win32Gui.textouta(@hdc, x, y, text, text.length)
1849
+ end
1850
+
1851
+ def draw_string_color(col, x, y, text)
1852
+ Win32Gui.settextcolor(@hdc, color(col))
1853
+ draw_string(x, y, text)
1854
+ end
1855
+
1856
+ def keyboard_state(query=nil)
1857
+ case query
1858
+ when :control, :ctrl
1859
+ Win32Gui.getkeystate(Win32Gui::VK_CONTROL) & 0x8000 > 0
1860
+ when :shift
1861
+ Win32Gui.getkeystate(Win32Gui::VK_SHIFT) & 0x8000 > 0
1862
+ when :alt
1863
+ Win32Gui.getkeystate(Win32Gui::VK_MENU) & 0x8000 > 0
1864
+ else
1865
+ [:control, :shift, :alt].find_all { |s| keyboard_state(s) }
1866
+ end
1867
+ end
1868
+
1869
+ # represents a clickable area with a label (aka button)
1870
+ class Button
1871
+ attr_accessor :x, :y, :w, :h, :c1, :c2, :text, :down, :action
1872
+
1873
+ # create a new Button with the specified text & border color
1874
+ def initialize(text='Ok', c1=:palegrey, c2=:grey, &b)
1875
+ @x = @y = @w = @h = 0
1876
+ @c1, @c2 = c1, c2
1877
+ @text = text
1878
+ @down = false
1879
+ @action = b
1880
+ end
1881
+
1882
+ # move the button (x y w h)
1883
+ def move(nx=@x, ny=@y, nw=@w, nh=@h)
1884
+ @x, @y, @w, @h = nx, ny, nw, nh
1885
+ end
1886
+
1887
+ # draw the button on the parent widget
1888
+ def paint(w)
1889
+ c1, c2 = @c1, @c2
1890
+ c1, c2 = c2, c1 if @down
1891
+ w.draw_string_color(:text, @x+(@w-w.font_width*@text.length)/2, @y+(@h - w.font_height)/2, @text)
1892
+ w.draw_line_color(c1, @x, @y, @x, @y+@h)
1893
+ w.draw_line_color(c1, @x, @y, @x+@w, @y)
1894
+ w.draw_line_color(c2, @x+@w, @y+@h, @x, @y+@h)
1895
+ w.draw_line_color(c2, @x+@w, @y+@h, @x+@w, @y)
1896
+ end
1897
+
1898
+ # checks if the click is on the button, returns true if so
1899
+ def click(x, y)
1900
+ @down = true if x >= @x and x < @x+@w and y >= @y and y < @y+@h
1901
+ end
1902
+
1903
+ def mouserelease(x, y)
1904
+ if @down
1905
+ @down = false
1906
+ @action.call
1907
+ true
1908
+ end
1909
+ end
1910
+ end
1911
+
1912
+ # add a new button to the widget
1913
+ def add_button(text='Ok', *a, &b)
1914
+ @buttons ||= []
1915
+ @buttons << Button.new(text, *a, &b)
1916
+ end
1917
+
1918
+ # render the buttons on the widget
1919
+ # should be called during #paint
1920
+ def paint_buttons
1921
+ @buttons.each { |b| b.paint(self) }
1922
+ end
1923
+
1924
+ # checks if the click is inside a button, returns true if it is
1925
+ # should be called during #click
1926
+ def click_buttons(x, y)
1927
+ @buttons.find { |b| b.click(x, y) }
1928
+ end
1929
+
1930
+ # the mouse was released, call button action if it is pressed
1931
+ # should be called during #mouserelease
1932
+ def mouserelease_buttons(x, y)
1933
+ @buttons.find { |b| b.mouserelease(x, y) }
1934
+ end
1935
+ end
1936
+
1937
+ class Window
1938
+ include Msgbox
1939
+
1940
+ attr_accessor :menu, :hwnd, :popups
1941
+ def initialize(*a, &b)
1942
+ @widget = nil
1943
+ @controlid = 1 # next free control id for menu items, buttons etc
1944
+ @control_action = {}
1945
+ (@@mainwindow_list ||= []) << self
1946
+ @visible = false
1947
+ @popups = []
1948
+ @parent ||= nil
1949
+
1950
+ cname = "metasm_w32gui_#{object_id}"
1951
+ cls = Win32Gui.alloc_c_struct 'WNDCLASSEXA', :cbsize => :size,
1952
+ :style => Win32Gui::CS_DBLCLKS,
1953
+ :hcursor => Win32Gui.loadcursora(0, Win32Gui::IDC_ARROW),
1954
+ :lpszclassname => cname,
1955
+ :lpfnwndproc => Win32Gui.callback_alloc_c('__stdcall int wndproc(int, int, int, int)') { |hwnd, msg, wp, lp| windowproc(hwnd, msg, wp, lp) }
1956
+
1957
+ Win32Gui.registerclassexa(cls)
1958
+
1959
+ @hwnd = Win32Gui.createwindowexa(win32styleex, cname, 'win32gui window', win32style, Win32Gui::CW_USEDEFAULT, Win32Gui::SW_HIDE, Win32Gui::CW_USEDEFAULT, 0, 0, 0, 0, 0)
1960
+
1961
+ initialize_window(*a, &b)
1962
+
1963
+ if respond_to? :build_menu
1964
+ @menu = []
1965
+ @menuhwnd = 0
1966
+ build_menu
1967
+ update_menu
1968
+ end
1969
+
1970
+ Win32Gui.dragacceptfiles(@hwnd, Win32Gui::TRUE)
1971
+
1972
+ show
1973
+ end
1974
+ def win32styleex; 0 ; end
1975
+ def win32style; Win32Gui::WS_OVERLAPPEDWINDOW ; end
1976
+
1977
+ def show
1978
+ Win32Gui.showwindow(@hwnd, Win32Gui::SW_SHOWDEFAULT)
1979
+ Win32Gui.updatewindow(@hwnd)
1980
+ end
1981
+
1982
+ def keyboard_state(query=nil)
1983
+ case query
1984
+ when :control, :ctrl
1985
+ Win32Gui.getkeystate(Win32Gui::VK_CONTROL) & 0x8000 > 0
1986
+ when :shift
1987
+ Win32Gui.getkeystate(Win32Gui::VK_SHIFT) & 0x8000 > 0
1988
+ when :alt
1989
+ Win32Gui.getkeystate(Win32Gui::VK_MENU) & 0x8000 > 0
1990
+ end
1991
+ end
1992
+
1993
+ # keypress event keyval traduction table
1994
+ Keyboard_trad = Win32Gui.cp.lexer.definition.keys.grep(/^VK_/).inject({}) { |h, cst|
1995
+ v = Win32Gui.const_get(cst)
1996
+ key = cst.to_s.sub(/^VK_/, '').downcase.to_sym
1997
+ h.update v => {
1998
+ :prior => :pgup, :next => :pgdown,
1999
+ :escape => :esc, :return => :enter,
2000
+ :back => :backspace,
2001
+ }.fetch(key, key)
2002
+ }
2003
+
2004
+ #MSGNAME = Win32Gui.cp.lexer.definition.keys.grep(/WM_/).sort.inject({}) { |h, c| h.update Win32Gui.const_get(c) => c }
2005
+ def windowproc(hwnd, msg, wparam, lparam)
2006
+ #puts "wproc #{'%x' % hwnd} #{MSGNAME[msg] || msg} #{'%x' % wparam} #{'%x' % lparam}" if not %w[WM_NCHITTEST WM_SETCURSOR WM_MOUSEMOVE WM_NCMOUSEMOVE].include? MSGNAME[msg]
2007
+ @hwnd ||= hwnd # some messages are sent before createwin returns
2008
+ case msg
2009
+ when Win32Gui::WM_NCHITTEST, Win32Gui::WM_SETCURSOR
2010
+ # most frequent messages (with MOUSEMOVE)
2011
+ return Win32Gui.defwindowproca(hwnd, msg, wparam, lparam)
2012
+ when Win32Gui::WM_MOUSEMOVE, Win32Gui::WM_LBUTTONDOWN, Win32Gui::WM_RBUTTONDOWN,
2013
+ Win32Gui::WM_LBUTTONDBLCLK, Win32Gui::WM_MOUSEWHEEL, Win32Gui::WM_LBUTTONUP
2014
+ mouse_msg(msg, wparam, lparam)
2015
+ when Win32Gui::WM_PAINT
2016
+ ps = Win32Gui.alloc_c_struct('PAINTSTRUCT')
2017
+ hdc = Win32Gui.beginpaint(hwnd, ps)
2018
+ if @widget
2019
+ @widget.paint_(hdc)
2020
+ else
2021
+ Win32Gui.selectobject(hdc, Win32Gui.getstockobject(Win32Gui::DC_BRUSH))
2022
+ Win32Gui.selectobject(hdc, Win32Gui.getstockobject(Win32Gui::DC_PEN))
2023
+ col = Win32Gui.getsyscolor(Win32Gui::COLOR_BTNFACE)
2024
+ Win32Gui.setdcbrushcolor(hdc, col)
2025
+ Win32Gui.setdcpencolor(hdc, col)
2026
+ Win32Gui.rectangle(hdc, 0, 0, @width, @height)
2027
+ end
2028
+ Win32Gui.endpaint(hwnd, ps)
2029
+ when Win32Gui::WM_MOVE
2030
+ rect = Win32Gui.alloc_c_struct('RECT')
2031
+ Win32Gui.getwindowrect(@hwnd, rect)
2032
+ @x, @y, @width, @height = rect[:left], rect[:top], rect[:right]-rect[:left], rect[:bottom]-rect[:top]
2033
+ @clientx = lparam & 0xffff
2034
+ @clienty = (lparam >> 16) & 0xffff
2035
+ when Win32Gui::WM_SIZE
2036
+ rect = Win32Gui.alloc_c_struct('RECT')
2037
+ Win32Gui.getwindowrect(@hwnd, rect)
2038
+ @x, @y, @width, @height = rect[:left], rect[:top], rect[:right]-rect[:left], rect[:bottom]-rect[:top]
2039
+ @clientwidth = lparam & 0xffff
2040
+ @clientheight = (lparam >> 16) & 0xffff
2041
+ @widget.resized_(lparam & 0xffff, (lparam >> 16) & 0xffff) if @widget
2042
+ redraw
2043
+ when Win32Gui::WM_WINDOWPOSCHANGING
2044
+ if @popups.first
2045
+ # must move popups to top before updating hwndInsertafter
2046
+ f = Win32Gui::SWP_NOACTIVATE | Win32Gui::SWP_NOMOVE | Win32Gui::SWP_NOSIZE |
2047
+ Win32Gui::SWP_NOOWNERZORDER | Win32Gui::SWP_NOSENDCHANGING
2048
+ @popups.each { |pw| Win32Gui.setwindowpos(pw.hwnd, Win32Gui::HWND_TOP, 0, 0, 0, 0, f) }
2049
+ Win32Gui.memory_write_int(lparam+Win32Gui.cp.typesize[:ptr], @popups.first.hwnd)
2050
+ end
2051
+ when Win32Gui::WM_SHOWWINDOW
2052
+ initialize_visible_
2053
+ when Win32Gui::WM_KEYDOWN, Win32Gui::WM_SYSKEYDOWN
2054
+ # SYSKEYDOWN for f10 (default = activate the menu bar)
2055
+ if key = Keyboard_trad[wparam]
2056
+ if keyboard_state(:control)
2057
+ @widget.keypress_ctrl_(key) if @widget
2058
+ else
2059
+ @widget.keypress_(key) if @widget
2060
+ end
2061
+ end
2062
+ Win32Gui.defwindowproca(hwnd, msg, wparam, lparam) if key != :f10 # alt+f4 etc
2063
+ when Win32Gui::WM_CHAR
2064
+ if keyboard_state(:control) and not keyboard_state(:alt) # altgr+[ returns CTRL on..
2065
+ if ?a.kind_of?(String)
2066
+ wparam += (keyboard_state(:shift) ? ?A.ord : ?a.ord) - 1 if wparam < 0x1a
2067
+ k = wparam.chr
2068
+ else
2069
+ wparam += (keyboard_state(:shift) ? ?A : ?a) - 1 if wparam < 0x1a
2070
+ k = wparam
2071
+ end
2072
+ @widget.keypress_ctrl_(k) if @widget
2073
+ else
2074
+ k = (?a.kind_of?(String) ? wparam.chr : wparam)
2075
+ @widget.keypress_(k) if @widget
2076
+ end
2077
+ when Win32Gui::WM_DESTROY
2078
+ destroy_window
2079
+ when Win32Gui::WM_COMMAND
2080
+ if a = @control_action[wparam]
2081
+ protect { a.call }
2082
+ end
2083
+ when Win32Gui::WM_DROPFILES
2084
+ cnt = Win32Gui.dragqueryfilea(wparam, -1, 0, 0)
2085
+ cnt.times { |i|
2086
+ buf = [0].pack('C')*1024
2087
+ len = Win32Gui.dragqueryfilea(wparam, i, buf, buf.length)
2088
+ protect { @widget.dragdropfile(buf[0, len]) } if @widget and @widget.respond_to? :dragdropfile
2089
+ }
2090
+ Win32Gui.dragfinish(wparam)
2091
+ else return Win32Gui.defwindowproca(hwnd, msg, wparam, lparam)
2092
+ end
2093
+ 0
2094
+ end
2095
+
2096
+ def mouse_msg(msg, wparam, lparam)
2097
+ return if not @widget
2098
+ x = Expression.make_signed(lparam & 0xffff, 16)
2099
+ y = Expression.make_signed((lparam >> 16) & 0xffff, 16)
2100
+ ctrl = true if wparam & Win32Gui::MK_CONTROL > 0
2101
+ cmsg =
2102
+ case msg
2103
+ when Win32Gui::WM_MOUSEMOVE
2104
+ :mousemove
2105
+ when Win32Gui::WM_LBUTTONDOWN
2106
+ ctrl ? :click_ctrl : :click
2107
+ when Win32Gui::WM_LBUTTONUP
2108
+ :mouserelease
2109
+ when Win32Gui::WM_RBUTTONDOWN
2110
+ :rightclick
2111
+ when Win32Gui::WM_LBUTTONDBLCLK
2112
+ :doubleclick
2113
+ when Win32Gui::WM_MOUSEWHEEL
2114
+ off = Expression.make_signed((wparam >> 16) & 0xffff, 16)
2115
+ dir = off > 0 ? :up : :down
2116
+ if ctrl
2117
+ return(@widget.mouse_wheel_ctrl(dir, x-@clientx, y-@clienty) if @widget.respond_to? :mouse_wheel_ctrl)
2118
+ else
2119
+ return(@widget.mouse_wheel(dir, x-@clientx, y-@clienty) if @widget.respond_to? :mouse_wheel)
2120
+ end
2121
+ end
2122
+
2123
+ case cmsg
2124
+ when :click
2125
+ Win32Gui.setcapture(@hwnd)
2126
+ when :mouserelease
2127
+ Win32Gui.releasecapture
2128
+ end
2129
+
2130
+ @widget.send(cmsg, x, y) if cmsg and @widget.respond_to? cmsg
2131
+ end
2132
+
2133
+ def initialize_visible_
2134
+ return if @visible
2135
+ @visible = true
2136
+ @widget.initialize_visible_ if @widget
2137
+ end
2138
+
2139
+ attr_reader :x, :y, :width, :height
2140
+ attr_reader :clientx, :clienty, :clientwidth, :clientheight
2141
+ def x=(newx)
2142
+ Win32Gui.movewindow(@hwnd, newx, @y, @width, @height, Win32Gui::TRUE)
2143
+ end
2144
+ def y=(newy)
2145
+ Win32Gui.movewindow(@hwnd, @x, newy, @width, @height, Win32Gui::TRUE)
2146
+ end
2147
+ def width=(newwidth)
2148
+ Win32Gui.movewindow(@hwnd, @x, @y, newwidth, @height, Win32Gui::TRUE)
2149
+ end
2150
+ def height=(newheight)
2151
+ Win32Gui.movewindow(@hwnd, @x, @y, @width, newheight, Win32Gui::TRUE)
2152
+ end
2153
+
2154
+ def widget ; @widget ; end
2155
+ def widget=(w)
2156
+ @widget = w
2157
+ w.hwnd = @hwnd if w
2158
+ w.parent = self if w
2159
+ if @visible and w
2160
+ @widget.initialize_visible_
2161
+ rect = Win32Gui.alloc_c_struct('RECT')
2162
+ Win32Gui.getclientrect(@hwnd, rect)
2163
+ @widget.resized_(rect[:right], rect[:bottom])
2164
+ end
2165
+ redraw
2166
+ end
2167
+
2168
+ def redraw
2169
+ Win32Gui.invalidaterect(@hwnd, 0, Win32Gui::FALSE)
2170
+ end
2171
+
2172
+ def destroy
2173
+ Win32Gui.sendmessagea(@hwnd, Win32Gui::WM_CLOSE, 0, 0)
2174
+ end
2175
+
2176
+ def destroy_window
2177
+ @destroyed = true
2178
+ @@mainwindow_list.delete self
2179
+ Gui.main_quit if @@mainwindow_list.empty? # XXX we didn't call Gui.main, we shouldn't Gui.main_quit...
2180
+ end
2181
+
2182
+ def destroyed? ; @destroyed ||= false ; end
2183
+
2184
+ def new_menu
2185
+ []
2186
+ end
2187
+
2188
+ # finds a menu by name (recursive)
2189
+ # returns a valid arg for addsubmenu(ret)
2190
+ def find_menu(name, from=@menu)
2191
+ name = name.gsub('_', '')
2192
+ if not l = from.find { |e| e.grep(::String).find { |es| es.gsub('_', '') == name } }
2193
+ l = from.map { |e| e.grep(::Array).map { |ae| find_menu(name, ae) }.compact.first }.compact.first
2194
+ end
2195
+ l.grep(::Array).first if l
2196
+ end
2197
+
2198
+ # append stuff to a menu
2199
+ # arglist:
2200
+ # empty = menu separator
2201
+ # string = menu entry display name (use a single '_' keyboard for shortcut, eg 'Sho_rtcut' => 'r')
2202
+ # :check = menu entry is a checkbox type, add a true/false argument to specify initial value
2203
+ # second string = keyboard shortcut (accelerator) - use '^' for Ctrl, and '<up>' for special keys
2204
+ # a menu object = this entry will open a submenu (you must specify a name, and action is ignored)
2205
+ # the method takes a block or a Proc argument that will be run whenever the menu item is selected
2206
+ #
2207
+ # use @menu to reference the top-level menu bar
2208
+ # call update_menu when the menu is done
2209
+ def addsubmenu(menu, *args, &action)
2210
+ args << action if action
2211
+ menu << args
2212
+ menu.last
2213
+ end
2214
+
2215
+ # make the window's MenuBar reflect the content of @menu
2216
+ def update_menu
2217
+ Win32Gui.destroymenu(@menuhwnd) if @menuhwnd != 0
2218
+ @menuhwnd = Win32Gui.createmenu()
2219
+ @menu.each { |e| create_menu_item(@menuhwnd, e) }
2220
+ Win32Gui.setmenu(@hwnd, @menuhwnd)
2221
+ end
2222
+
2223
+ def create_menu_item(menu, entry)
2224
+ args = entry.dup
2225
+
2226
+ stock = (%w[OPEN SAVE CLOSE QUIT] & args).first
2227
+ args.delete stock if stock
2228
+ accel = args.grep(/^\^?(\w|<\w+>)$/).first
2229
+ args.delete accel if accel
2230
+ check = args.delete :check
2231
+ action = args.grep(::Proc).first
2232
+ args.delete action if action
2233
+ if submenu = args.grep(::Array).first
2234
+ args.delete submenu
2235
+ sm = Win32Gui.createmenu()
2236
+ submenu.each { |e| create_menu_item(sm, e) }
2237
+ submenu = sm
2238
+ end
2239
+ label = args.shift
2240
+
2241
+ label ||= '_' + stock.capitalize if stock
2242
+
2243
+ flags = 0
2244
+
2245
+ if check
2246
+ checked = args.shift
2247
+ flags |= (checked ? Win32Gui::MF_CHECKED : Win32Gui::MF_UNCHECKED)
2248
+ end
2249
+ flags |= Win32Gui::MF_POPUP if submenu
2250
+ if label
2251
+ flags |= Win32Gui::MF_STRING
2252
+ label = label.gsub('&', '&&')
2253
+ label = label.tr('_', '&')
2254
+ else
2255
+ flags |= Win32Gui::MF_SEPARATOR
2256
+ end
2257
+
2258
+ if accel
2259
+ key = accel[-1]
2260
+ key = accel[/<(.*)>/, 1] if key == ?>
2261
+ label += "\t#{'c-' if accel[0] == ?^}#{key.kind_of?(Integer) ? key.chr : key}"
2262
+ end
2263
+
2264
+ if action
2265
+ id = @controlid
2266
+ if not check
2267
+ @control_action[id] = action
2268
+ else
2269
+ @control_action[id] = lambda {
2270
+ checked = action.call(!checked)
2271
+ Win32Gui.checkmenuitem(menu, id, (checked ? Win32Gui::MF_CHECKED : Win32Gui::MF_UNCHECKED))
2272
+ }
2273
+ end
2274
+ @controlid += 1
2275
+ end
2276
+
2277
+ Win32Gui.appendmenua(menu, flags, id || submenu, label)
2278
+ end
2279
+
2280
+ def title; @title; end
2281
+ def title=(t)
2282
+ @title = t
2283
+ Win32Gui.setwindowtexta(@hwnd, @title)
2284
+ end
2285
+
2286
+ def initialize_window
2287
+ end
2288
+ end
2289
+
2290
+ class ToolWindow < Window
2291
+ def win32styleex; Win32Gui::WS_EX_TOOLWINDOW ; end
2292
+ def win32style; Win32Gui::WS_POPUP | Win32Gui::WS_SYSMENU | Win32Gui::WS_CAPTION | Win32Gui::WS_THICKFRAME ; end
2293
+
2294
+ def initialize_visible_
2295
+ super
2296
+ # center on the parent from size in initial_size
2297
+ w, h = @widget.initial_size
2298
+ r1 = Win32Gui.alloc_c_struct('RECT')
2299
+ Win32Gui.getwindowrect(@parent.hwnd, r1)
2300
+ r2 = Win32Gui.alloc_c_struct('RECT', :left => 0, :top => 0, :right => w, :bottom => h)
2301
+ Win32Gui.adjustwindowrectex(r2, @parent.win32style, Win32Gui::FALSE, @parent.win32styleex)
2302
+ x = r1[:left]+(r1[:right]-r1[:left]-r2[:right]+r2[:left])/2
2303
+ y = r1[:top ]+(r1[:bottom]-r1[:top]-r2[:bottom]+r2[:top])/2
2304
+ Win32Gui.movewindow(@hwnd, x, y, r2[:right]-r2[:left], r2[:bottom]-r2[:top], Win32Gui::FALSE)
2305
+ end
2306
+
2307
+ def initialize(parent, *a, &b)
2308
+ @parent = parent
2309
+ super(*a, &b)
2310
+ @@mainwindow_list.delete self
2311
+ @parent.popups << self if parent
2312
+ end
2313
+
2314
+ def destroy_window
2315
+ @parent.popups.delete self if @parent
2316
+ super
2317
+ end
2318
+ end
2319
+
2320
+ class OpenFile
2321
+ def w32api(arg)
2322
+ Win32Gui.getopenfilenamea(arg)
2323
+ end
2324
+ def w32flags
2325
+ Win32Gui::OFN_PATHMUSTEXIST
2326
+ end
2327
+
2328
+ def initialize(win, title, opts={})
2329
+ buf = [0].pack('C')*512
2330
+ ofn = Win32Gui.alloc_c_struct 'OPENFILENAMEA',
2331
+ :lstructsize => :size,
2332
+ #:hwndowner => win.hwnd, # 0 for nonmodal
2333
+ :lpstrfilter => "All Files\0*.*\0\0",
2334
+ :lpstrfile => buf,
2335
+ :lpstrtitle => title,
2336
+ :nmaxfile => buf.length,
2337
+ :flags => Win32Gui::OFN_DONTADDTORECENT | Win32Gui::OFN_LONGNAMES |
2338
+ Win32Gui::OFN_HIDEREADONLY | w32flags
2339
+ ofn[:lpstrinitialdir] = opts[:path] if opts[:path]
2340
+ return if w32api(ofn) == 0
2341
+ buf = buf[0, buf.index(0.chr)] if buf.index(0.chr)
2342
+ yield buf if buf != ''
2343
+ end
2344
+ end
2345
+
2346
+ class SaveFile < OpenFile
2347
+ def w32api(arg)
2348
+ Win32Gui.getsavefilenamea(arg)
2349
+ end
2350
+ def w32flags
2351
+ Win32Gui::OFN_OVERWRITEPROMPT
2352
+ end
2353
+ end
2354
+
2355
+ class MessageBox
2356
+ def initialize(win, msg, opts={})
2357
+ opts = { :title => opts } if opts.kind_of? String
2358
+ Win32Gui.messageboxa(0, msg, opts[:title], 0)
2359
+ end
2360
+ end
2361
+
2362
+ class InputBox < ToolWindow
2363
+ class IBoxWidget < DrawableWidget
2364
+ def initialize_widget(label, opts, &b)
2365
+ @label = label
2366
+ @action = b
2367
+ @textdown = false
2368
+ @curline = opts[:text].to_s.dup
2369
+ @oldsel_x = @caret_x_select = 0
2370
+ @caret_x = @curline.length
2371
+ @caret_x_start = 0
2372
+
2373
+ add_button('Ok', :btnc1, :btnc2) { keypress(:enter) }
2374
+ add_button('Cancel', :btnc1, :btnc2) { keypress(:esc) }
2375
+
2376
+ @default_color_association = { :background => :winbg, :label => :black,
2377
+ :text => :black, :textbg => :white, :caret => :black, :btnc1 => :palegrey,
2378
+ :btnc2 => :grey, :textsel => :white, :textselbg => :darkblue }
2379
+ end
2380
+
2381
+ def resized(w, h)
2382
+ bw = 10*@font_width
2383
+ bh = @font_height*3/2
2384
+ @buttons[0].move((w-2*bw-3*@font_width)/2, 0, bw, bh)
2385
+ @buttons[1].move(@buttons[0].x + 3*@font_width + bw, 0, bw, bh)
2386
+ end
2387
+
2388
+ def initial_size
2389
+ [40*@font_width, 6*@font_height + @font_height/4]
2390
+ end
2391
+
2392
+ def paint
2393
+ y = @font_height/2
2394
+
2395
+ fixedfont = Win32Gui.selectobject(@hdc, Win32Gui.getstockobject(Win32Gui::ANSI_VAR_FONT))
2396
+ sz = Win32Gui.alloc_c_struct('POINT')
2397
+ Win32Gui.gettextextentpoint32a(@hdc, 'x', 1, sz)
2398
+ var_font_height = sz[:y]
2399
+ @label.each_line { |l|
2400
+ draw_string_color(:label, @font_width, y, l)
2401
+ y += var_font_height
2402
+ }
2403
+ y += @font_height
2404
+ @texty = y-1
2405
+ @texth = @font_height+1
2406
+
2407
+ Win32Gui.selectobject(@hdc, fixedfont)
2408
+
2409
+ y += @font_height*2
2410
+ @buttons.each { |b| b.y = y }
2411
+ paint_buttons
2412
+
2413
+ w_c = width/@font_width - 2
2414
+
2415
+ if @caret_x <= @caret_x_start
2416
+ @caret_x_start = [@caret_x-1, 0].max
2417
+ elsif @caret_x_start > 0 and @curline[@caret_x_start..-1].length < w_c-1
2418
+ @caret_x_start = [@curline.length-w_c+1, 0].max
2419
+ elsif @caret_x_start + w_c <= @caret_x
2420
+ @caret_x_start = [@caret_x-w_c+1, 0].max
2421
+ end
2422
+ draw_rectangle_color(:textbg, @font_width, @texty-1, @width-2*@font_width, @font_height+1)
2423
+ draw_string_color(:text, @font_width+1, @texty, @curline[@caret_x_start, w_c])
2424
+
2425
+ if @caret_x_select
2426
+ c1, c2 = [@caret_x_select, @caret_x].sort
2427
+ c1 = [[c1, @caret_x_start].max, @caret_x_start+w_c].min
2428
+ c2 = [[c2, @caret_x_start].max, @caret_x_start+w_c].min
2429
+ if c1 != c2
2430
+ draw_rectangle_color(:textselbg, @font_width+1+(c1-@caret_x_start)*@font_width, @texty-1, (c2-c1)*@font_width, @font_height+1)
2431
+ draw_string_color(:textsel, @font_width+1+(c1-@caret_x_start)*@font_width, @texty, @curline[c1...c2])
2432
+ end
2433
+ end
2434
+
2435
+ cx = [@caret_x-@caret_x_start+1, w_c].min*@font_width+1
2436
+ draw_line_color(:caret, cx, @texty, cx, @texty+@font_height-1)
2437
+ @oldcaret_x = @caret_x
2438
+ end
2439
+
2440
+ def keypress_ctrl(key)
2441
+ case key
2442
+ when ?a
2443
+ @caret_x_select = 0
2444
+ @caret_x = @curline.length
2445
+ redraw
2446
+ when ?c
2447
+ if @caret_x_select
2448
+ c1, c2 = [@caret_x, @caret_x_select].sort
2449
+ clipboard_copy @curline[c1...c2]
2450
+ end
2451
+ when ?v
2452
+ cptext = clipboard_paste.to_s
2453
+ cx = @caret_x_select || @caret_x
2454
+ @caret_x_select = nil
2455
+ c1, c2 = [cx, @caret_x].sort
2456
+ @curline[c1...c2] = cptext
2457
+ @caret_x_select = nil
2458
+ @caret_x = c1 + cptext.length
2459
+ redraw
2460
+ when ?x
2461
+ if @caret_x_select
2462
+ c1, c2 = [@caret_x, @caret_x_select].sort
2463
+ clipboard_copy @curline[c1...c2]
2464
+ @curline[c1..c2] = ''
2465
+ @caret_x_select = nil
2466
+ @caret_x = c1
2467
+ redraw
2468
+ end
2469
+ else return false
2470
+ end
2471
+ true
2472
+ end
2473
+
2474
+ def keypress(key)
2475
+ case key
2476
+ when :left
2477
+ if keyboard_state(:shift)
2478
+ @caret_x_select ||= @caret_x
2479
+ else
2480
+ @caret_x_select = nil
2481
+ end
2482
+ @caret_x -= 1 if @caret_x > 0
2483
+ update_caret
2484
+ when :right
2485
+ if keyboard_state(:shift)
2486
+ @caret_x_select ||= @caret_x
2487
+ else
2488
+ @caret_x_select = nil
2489
+ end
2490
+ @caret_x += 1 if @caret_x < @curline.length
2491
+ update_caret
2492
+ when :home
2493
+ if keyboard_state(:shift)
2494
+ @caret_x_select ||= @caret_x
2495
+ else
2496
+ @caret_x_select = nil
2497
+ end
2498
+ @caret_x = 0
2499
+ update_caret
2500
+ when :end
2501
+ if keyboard_state(:shift)
2502
+ @caret_x_select ||= @caret_x
2503
+ else
2504
+ @caret_x_select = nil
2505
+ end
2506
+ @caret_x = @curline.length
2507
+ update_caret
2508
+ when :enter
2509
+ destroy
2510
+ Gui.main_iter
2511
+ protect { @action.call(@curline.strip) }
2512
+ when :esc
2513
+ if @buttons.find { |b| b.down }
2514
+ @buttons.each { |b| b.down = false }
2515
+ redraw
2516
+ else
2517
+ destroy
2518
+ end
2519
+ when ?\x20..?\x7e
2520
+ cx = @caret_x_select || @caret_x
2521
+ @caret_x_select = nil
2522
+ c1, c2 = [cx, @caret_x].sort
2523
+ @curline[c1...c2] = key.chr
2524
+ @caret_x = c1+1
2525
+ redraw
2526
+ when :delete
2527
+ if @caret_x_select
2528
+ c1, c2 = [@caret_x, @caret_x_select].sort
2529
+ @curline[c1...c2] = ''
2530
+ @caret_x_select = nil
2531
+ @caret_x = c1
2532
+ redraw
2533
+ elsif @caret_x < @curline.length
2534
+ @curline[@caret_x, 1] = ''
2535
+ redraw
2536
+ end
2537
+ when :backspace
2538
+ if @caret_x_select
2539
+ c1, c2 = [@caret_x, @caret_x_select].sort
2540
+ @curline[c1...c2] = ''
2541
+ @caret_x_select = nil
2542
+ @caret_x = c1
2543
+ redraw
2544
+ elsif @caret_x > 0
2545
+ @caret_x -= 1
2546
+ @curline[@caret_x, 1] = ''
2547
+ redraw
2548
+ end
2549
+ else return false
2550
+ end
2551
+ true
2552
+ end
2553
+
2554
+ def click(x, y)
2555
+ if y >= @texty and y < @texty+@texth
2556
+ @caret_x_select = nil
2557
+ @caret_x = x.to_i / @font_width - 1 + @caret_x_start
2558
+ @caret_x = [[@caret_x, 0].max, @curline.length].min
2559
+ @textdown = @caret_x
2560
+ update_caret
2561
+ elsif click_buttons(x, y)
2562
+ redraw
2563
+ end
2564
+ end
2565
+
2566
+ def mousemove(x, y)
2567
+ if @textdown
2568
+ x = x.to_i / @font_width - 1 + @caret_x_start
2569
+ x = [[x, 0].max, @curline.length].min
2570
+ if x != @textdown
2571
+ @caret_x_select = @textdown
2572
+ @caret_x = x
2573
+ redraw
2574
+ end
2575
+ end
2576
+ end
2577
+
2578
+ def mouserelease(x, y)
2579
+ if @textdown
2580
+ x = x.to_i / @font_width - 1 + @caret_x_start
2581
+ x = [[x, 0].max, @curline.length].min
2582
+ if x != @textdown
2583
+ @caret_x_select = @textdown
2584
+ @caret_x = x
2585
+ redraw
2586
+ end
2587
+ @textdown = false
2588
+ elsif mouserelease_buttons(x, y)
2589
+ end
2590
+ end
2591
+
2592
+ def update_caret
2593
+ return if @oldcaret_x == @caret_x and @oldsel_x == @caret_x_select
2594
+ redraw
2595
+ @oldsel_x = @caret_x_select
2596
+ @oldcaret_x = @caret_x
2597
+ end
2598
+
2599
+ def destroy
2600
+ @parent.destroy
2601
+ end
2602
+
2603
+ def text
2604
+ @curline
2605
+ end
2606
+ def text=(t)
2607
+ @curline = t
2608
+ @caret_x_select = 0
2609
+ @caret_x = t.length
2610
+ redraw
2611
+ end
2612
+
2613
+ def dragdropfile(f)
2614
+ cx = @caret_x_select || @caret_x
2615
+ @caret_x_select = nil
2616
+ c1, c2 = [cx, @caret_x].sort
2617
+ @curline[c1...c2] = f
2618
+ @caret_x_select = nil
2619
+ @caret_x = c1 + f.length
2620
+ redraw
2621
+ end
2622
+ end
2623
+ def initialize_window(prompt, opts={}, &b)
2624
+ self.title = opts[:title] ? opts[:title] : 'input'
2625
+ self.widget = IBoxWidget.new(prompt, opts, &b)
2626
+ end
2627
+
2628
+ def text ; @widget.text ; end
2629
+ def text=(t) ; @widget.text = t ; end
2630
+ end
2631
+
2632
+ class ListWindow < ToolWindow
2633
+ class LBoxWidget < DrawableWidget
2634
+ def initialize_widget(list, opts={}, &b)
2635
+ ccnt = list.first.length
2636
+ # store a true/false per column saying if the original data was integers (for col sorting)
2637
+ @list_ints = list[1..-1].transpose.map { |col| col.all? { |e| e.kind_of? Integer } } rescue []
2638
+ @list = list.map { |l|
2639
+ l += ['']*(ccnt - l.length) if l.length < ccnt
2640
+ l = l[0, ccnt] if l.length > ccnt
2641
+ l.map { |w| w.to_s }
2642
+ }
2643
+ # length of the longest element of the column
2644
+ @colwmax = @list.transpose.map { |l| l.map { |w| w.length }.max }
2645
+ @titles = @list.shift
2646
+
2647
+ @action = b
2648
+ @linehead = 0
2649
+ @color_callback = opts[:color_callback] # lambda { |ary_entries_text| [color_font, color_bg] }
2650
+ @noclose_dblclick = opts[:noclose_dblclick]
2651
+ # index of the currently selected row
2652
+ @linesel = nil
2653
+ # ary indicating whether a title label is being clicked
2654
+ @btndown = []
2655
+ @btnheight = @font_height * 4/3
2656
+ @sbh = 0 # position of the hz scrollbar
2657
+ @sbv = 0
2658
+
2659
+ @default_color_association = { :background => :winbg, :label => :black,
2660
+ :text => :black, :textbg => :white, :btnc1 => :white, :btnc2 => :grey,
2661
+ :textsel => :white, :textselbg => :darkblue }
2662
+ end
2663
+
2664
+ def initial_size
2665
+ @colw = @colwmax.map { |w| (w+1) * @font_width }
2666
+ allw = @colw.inject(0) { |a, i| a+i }
2667
+ [[allw, 80*@font_width].min, [@list.length+1, 30].min * @font_height+2]
2668
+ end
2669
+
2670
+ def resized(w, h)
2671
+ # scrollbar stuff
2672
+ fullw = @colwmax.inject(0) { |a, i| a+i+1 } * @font_width
2673
+ @sbh = fullw-w if @sbh > fullw-w
2674
+ @sbh = 0 if @sbh < 0
2675
+ sif = Win32Gui.alloc_c_struct('SCROLLINFO',
2676
+ :cbsize => :size, :fmask => Win32Gui::SIF_ALL,
2677
+ :nmin => 0, :nmax => fullw-1, :npage => w, :npos => @sbh)
2678
+ Win32Gui.setscrollinfo(@hwnd, Win32Gui::SB_HORZ, sif, Win32Gui::TRUE)
2679
+
2680
+ fullh = @list.length * @font_height + @btnheight
2681
+ @sbv = fullh-h if @sbv > fullh-h
2682
+ @sbv = 0 if @sbv < 0
2683
+ sif = Win32Gui.alloc_c_struct('SCROLLINFO',
2684
+ :cbsize => :size, :fmask => Win32Gui::SIF_ALL,
2685
+ :nmin => 0, :nmax => fullh-1, :npage => h, :npos => @sbv)
2686
+ Win32Gui.setscrollinfo(@hwnd, Win32Gui::SB_VERT, sif, Win32Gui::TRUE)
2687
+
2688
+ # resize columns to fill available hz space
2689
+ if w > fullw
2690
+ mi = (w-fullw) / @colw.length
2691
+ mm = (w-fullw) % @colw.length
2692
+ @colw.length.times { |i|
2693
+ @colw[i] = (@colwmax[i]+1)*@font_width + mi + (i < mm ? 1 : 0)
2694
+ }
2695
+ redraw
2696
+ end
2697
+ end
2698
+
2699
+ def paint
2700
+ @btnx = []
2701
+ @btny = 0
2702
+ @btnheight = @font_height * 4/3
2703
+ x = 0
2704
+ @colw.each { |w|
2705
+ @btnx << x
2706
+ x += w
2707
+ }
2708
+
2709
+ x -= @sbh
2710
+ y = @btnheight
2711
+ @linehead = @sbv / @font_height
2712
+ y -= @sbv % @font_height
2713
+ tl = (@linesel || -1) - @linehead
2714
+ @lineshown = @list[@linehead, (height-y)/@font_height+1].to_a.length
2715
+ @list[@linehead, @lineshown].to_a.each { |l|
2716
+ x = @btnx.first - @sbh
2717
+ ct, cb = @color_callback[l] if @color_callback
2718
+ ct ||= :text
2719
+ cb ||= :textbg
2720
+ ct, cb = :textsel, :textselbg if tl == 0
2721
+ tl -= 1
2722
+ draw_rectangle_color(cb, x, y, width-2*x, @font_height)
2723
+ l.zip(@colw).each { |t, w|
2724
+ draw_string_color(ct, x+@font_width/2, y, t[0, w/@font_width-1])
2725
+ x += w
2726
+ }
2727
+ y += @font_height
2728
+ }
2729
+
2730
+ @titles.zip(@colw, @btnx, @btndown).each { |t, w, bx, d|
2731
+ x = bx - @sbh
2732
+ y = @btny
2733
+ h = @btnheight-1
2734
+ c1 = d ? :btnc2 : :btnc1
2735
+ c2 = d ? :btnc1 : :btnc2
2736
+ draw_rectangle_color(:background, x, y, w-1, h)
2737
+ draw_line_color(c1, x, y, x, y+h)
2738
+ draw_line_color(c1, x, y, x+w-1, y)
2739
+ draw_line_color(c2, x+w-1, y+h, x, y+h)
2740
+ draw_line_color(c2, x+w-1, y+h, x+w-1, y)
2741
+
2742
+ cw = w/@font_width-1
2743
+ xo = [(cw-t.length) * @font_width/2, 0].max # center titles
2744
+ draw_string_color(:label, x+@font_width/2+xo, y+@font_height/6, t[0, cw])
2745
+ }
2746
+ end
2747
+
2748
+ def keypress(key)
2749
+ case key
2750
+ when :up
2751
+ if not @linesel
2752
+ @linesel = @linehead
2753
+ elsif @linesel > 0
2754
+ @linesel -= 1
2755
+ vscroll(@linesel*@font_height) if @linesel < @linehead
2756
+ end
2757
+ redraw
2758
+ when :down
2759
+ if not @linesel
2760
+ @linesel = @linehead
2761
+ elsif @linesel < @list.length-1
2762
+ @linesel += 1
2763
+ vscroll((@linesel-(@lineshown-1))*@font_height) if @linehead < @linesel-(@lineshown-1)
2764
+ end
2765
+ redraw
2766
+ when :pgup
2767
+ off = [@lineshown, [@lineshown/2, 5].max].min
2768
+ if not @linesel
2769
+ @linesel = @linehead
2770
+ elsif @linesel != @linehead
2771
+ @linesel = [@linehead, @linesel-off].max
2772
+ else
2773
+ @linesel = [0, @linehead-off].max
2774
+ vscroll(@linesel*@font_height)
2775
+ end
2776
+ redraw
2777
+ when :pgdown
2778
+ n = @lineshown-1
2779
+ off = [@lineshown, [@lineshown/2, 5].max].min
2780
+ if not @linesel
2781
+ @linesel = @linehead+n
2782
+ elsif @linesel != @linehead+n
2783
+ @linesel = [@linehead+n, @linesel+off].min
2784
+ else
2785
+ vscroll((@linehead+off)*@font_height)
2786
+ @linesel = [@linehead+n, @list.length-1].min
2787
+ end
2788
+ redraw
2789
+ when :home
2790
+ @linesel = 0
2791
+ vscroll(0)
2792
+ redraw
2793
+ when :end
2794
+ @linesel = @list.length-1
2795
+ vscroll(@list.length*@font_height)
2796
+ redraw
2797
+ when :enter
2798
+ if @linesel and @list[@linesel]
2799
+ protect { @action.call(@list[@linesel]) }
2800
+ end
2801
+ when :esc
2802
+ if not @btndown.compact.empty?
2803
+ @btndown = []
2804
+ redraw
2805
+ else
2806
+ destroy
2807
+ end
2808
+ else return false
2809
+ end
2810
+ true
2811
+ end
2812
+
2813
+ def mouse_wheel(dir, x, y)
2814
+ case dir
2815
+ when :up
2816
+ off = [@lineshown, [@lineshown/2, 5].max].min
2817
+ vscroll((@linehead-off)*@font_height)
2818
+ redraw
2819
+ when :down
2820
+ n = @lineshown-1
2821
+ off = [@lineshown, [@lineshown/2, 5].max].min
2822
+ vscroll((@linehead+off)*@font_height)
2823
+ redraw
2824
+ end
2825
+ end
2826
+
2827
+ def hscroll(val)
2828
+ Win32Gui.setscrollpos(@hwnd, Win32Gui::SB_HORZ, val, Win32Gui::TRUE)
2829
+ @sbh = Win32Gui.getscrollpos(@hwnd, Win32Gui::SB_HORZ) # clipping, etc
2830
+ redraw
2831
+ end
2832
+
2833
+ def vscroll(val)
2834
+ Win32Gui.setscrollpos(@hwnd, Win32Gui::SB_VERT, val, Win32Gui::TRUE)
2835
+ @sbv = Win32Gui.getscrollpos(@hwnd, Win32Gui::SB_VERT)
2836
+ redraw
2837
+ end
2838
+
2839
+ def xtobtn(x)
2840
+ x += @sbh
2841
+ if x < @btnx.first
2842
+ return 0
2843
+ elsif x >= @btnx.last + @colw.last
2844
+ return @btnx.length-1
2845
+ else
2846
+ @btnx.zip(@colw).each_with_index { |(bx, bw), i|
2847
+ return i if x >= bx and x < bx+bw
2848
+ }
2849
+ end
2850
+ end
2851
+
2852
+ def click(x, y)
2853
+ if y >= @btny and y < @btny+@btnheight
2854
+ # TODO column resize
2855
+ @btndown[xtobtn(x)] = true
2856
+ redraw
2857
+ elsif y >= @btny+@btnheight
2858
+ y += @sbv % @font_height
2859
+ cy = @linehead + (y - @btny - @btnheight)/@font_height
2860
+ if cy < @list.length
2861
+ @linesel = cy
2862
+ redraw
2863
+ Gui.main_iter
2864
+ protect { @action.call(@list[@linesel]) }
2865
+ end
2866
+ end
2867
+ end
2868
+
2869
+ def doubleclick(x, y)
2870
+ if y >= @btny+@btnheight
2871
+ return click(x, y) if @noclose_dblclick
2872
+ y += @sbv % @font_height
2873
+ cy = @linehead + (y - @btny - @btnheight)/@font_height
2874
+ if cy < @list.length
2875
+ destroy
2876
+ Gui.main_iter
2877
+ protect { @action.call(@list[@linesel]) }
2878
+ end
2879
+ end
2880
+ end
2881
+
2882
+ def mousemove(x, y)
2883
+ if @btndown.compact.first
2884
+ @btndown = []
2885
+ @btndown[xtobtn(x)] = true
2886
+ redraw
2887
+ end
2888
+ end
2889
+
2890
+ def mouserelease(x, y)
2891
+ if @btndown.compact.first
2892
+ @btndown = []
2893
+ col = xtobtn(x)
2894
+ cursel = @list[@linesel] if @linesel
2895
+ if @list_ints[col]
2896
+ nlist = @list.sort_by { |a| [a[col].to_i, a] }
2897
+ else
2898
+ nlist = @list.sort_by { |a| [a[col], a] }
2899
+ end
2900
+ nlist.reverse! if nlist == @list
2901
+ @list = nlist
2902
+ @linehead = 0
2903
+ if cursel
2904
+ @linesel = @list.index(cursel)
2905
+ @linehead = @linesel - (@lineshown-1) if @linehead < @linesel-(@lineshown-1)
2906
+ end
2907
+ redraw
2908
+ end
2909
+ end
2910
+
2911
+ def destroy
2912
+ @parent.destroy
2913
+ end
2914
+ end
2915
+ def initialize_window(title, list, opts={}, &b)
2916
+ @ondestroy = opts[:ondestroy]
2917
+ self.title = title
2918
+ self.widget = LBoxWidget.new(list, opts, &b)
2919
+ end
2920
+
2921
+ def destroy_window
2922
+ @ondestroy.call if @ondestroy
2923
+ super()
2924
+ end
2925
+
2926
+ def windowproc(hwnd, msg, wparam, lparam)
2927
+ case msg
2928
+ when Win32Gui::WM_HSCROLL
2929
+ sif = Win32Gui.alloc_c_struct('SCROLLINFO', :cbsize => :size, :fmask => Win32Gui::SIF_ALL)
2930
+ Win32Gui.getscrollinfo(@hwnd, Win32Gui::SB_HORZ, sif)
2931
+ case wparam & 0xffff
2932
+ when Win32Gui::SB_THUMBPOSITION; val = sif.ntrackpos
2933
+ when Win32Gui::SB_THUMBTRACK; val = sif.ntrackpos
2934
+ when Win32Gui::SB_LINELEFT; val = sif.npos - 1
2935
+ when Win32Gui::SB_LINERIGHT; val = sif.npos + 1
2936
+ when Win32Gui::SB_PAGELEFT; val = sif.npos - sif.npage
2937
+ when Win32Gui::SB_PAGERIGHT; val = sif.npos + sif.npage
2938
+ else return 0
2939
+ end
2940
+ @widget.hscroll val
2941
+ when Win32Gui::WM_VSCROLL
2942
+ sif = Win32Gui.alloc_c_struct('SCROLLINFO', :cbsize => :size, :fmask => Win32Gui::SIF_ALL)
2943
+ Win32Gui.getscrollinfo(@hwnd, Win32Gui::SB_VERT, sif)
2944
+ case wparam & 0xffff
2945
+ when Win32Gui::SB_THUMBPOSITION; val = sif.ntrackpos
2946
+ when Win32Gui::SB_THUMBTRACK; val = sif.ntrackpos; nopos = true
2947
+ when Win32Gui::SB_LINEDOWN; val = sif.npos + 1
2948
+ when Win32Gui::SB_LINEUP; val = sif.npos - 1
2949
+ when Win32Gui::SB_PAGEDOWN; val = sif.npos + sif.npage
2950
+ when Win32Gui::SB_PAGEUP; val = sif.npos - sif.npage
2951
+ else return 0
2952
+ end
2953
+ @widget.vscroll val
2954
+ else return super(hwnd, msg, wparam, lparam)
2955
+ end
2956
+ 0
2957
+ end
2958
+ end
2959
+
2960
+ def Gui.main
2961
+ @idle_procs ||= []
2962
+ msg = Win32Gui.alloc_c_struct('MSG')
2963
+ loop do
2964
+ if Win32Gui.peekmessagea(msg, 0, 0, 0, Win32Gui::PM_NOREMOVE) != 0 or
2965
+ Win32Gui.msgwaitformultipleobjects(0, 0, Win32Gui::FALSE, 500,
2966
+ Win32Gui::QS_ALLINPUT) != Win32Gui::WAIT_TIMEOUT
2967
+ ret = Win32Gui.getmessagea(msg, 0, 0, 0)
2968
+ break if ret == 0
2969
+ raise Win32Gui.last_error_msg if ret < 0
2970
+ Win32Gui.translatemessage(msg)
2971
+ Win32Gui.dispatchmessagea(msg)
2972
+ end
2973
+ while not @idle_procs.empty? and Win32Gui.peekmessagea(msg, 0, 0, 0, Win32Gui::PM_NOREMOVE) == 0
2974
+ @idle_procs.delete_if { |ip| not ip.call }
2975
+ end
2976
+ end
2977
+ msg[:wparam]
2978
+ end
2979
+
2980
+ def Gui.main_quit
2981
+ Win32Gui.postquitmessage(0)
2982
+ end
2983
+
2984
+ def Gui.main_iter
2985
+ msg = Win32Gui.alloc_c_struct('MSG')
2986
+ while Win32Gui.peekmessagea(msg, 0, 0, 0, Win32Gui::PM_REMOVE) != 0
2987
+ Win32Gui.translatemessage(msg)
2988
+ Win32Gui.dispatchmessagea(msg)
2989
+ end
2990
+ end
2991
+
2992
+ # add a lambda to be run whenever the messageloop is idle
2993
+ # the lambda is removed if it returns nil/false
2994
+ def Gui.idle_add(&b)
2995
+ @idle_procs ||= []
2996
+ @idle_procs << b
2997
+ end
2998
+
2999
+ end
3000
+ end
3001
+
3002
+ require 'metasm/gui/dasm_main'
3003
+ require 'metasm/gui/debug'
3004
+