metasm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+