metasm 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- 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
|
+
|