-
Notifications
You must be signed in to change notification settings - Fork 2
/
resources.au3
329 lines (276 loc) · 11.7 KB
/
resources.au3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
; by Zedna on the AutoIt forums
; in AutoIt 3.3.12.0 and above is needed to change $ghGDIPDll --> $__g_hGDIPDll
#include-once
#include <Constants.au3>
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
_GDIPlus_Startup()
Global Const $RT_CURSOR = 1
Global Const $RT_BITMAP = 2
Global Const $RT_ICON = 3
Global Const $RT_MENU = 4
Global Const $RT_DIALOG = 5
Global Const $RT_STRING = 6
Global Const $RT_FONTDIR = 7
Global Const $RT_FONT = 8
Global Const $RT_ACCELERATOR = 9
Global Const $RT_RCDATA = 10
Global Const $RT_MESSAGETABLE = 11
Global Const $RT_GROUP_CURSOR = 12
Global Const $RT_GROUP_ICON = 14
Global Const $RT_VERSION = 16
Global Const $RT_DLGINCLUDE = 17
Global Const $RT_PLUGPLAY = 19
Global Const $RT_VXD = 20
Global Const $RT_ANICURSOR = 21
Global Const $RT_ANIICON = 22
Global Const $RT_HTML = 23
Global Const $RT_MANIFEST = 24
Global Const $SND_RESOURCE = 0x00040004
Global Const $SND_SYNC = 0x0
Global Const $SND_ASYNC = 0x1
Global Const $SND_MEMORY = 0x4
Global Const $SND_LOOP = 0x8
Global Const $SND_NOSTOP = 0x10
Global Const $SND_NOWAIT = 0x2000
Global Const $SND_PURGE = 0x40
Func _ResourceGet($ResName, $ResType = 10, $ResLang = 0, $DLL = -1) ; $RT_RCDATA = 10
Local Const $IMAGE_BITMAP = 0
Local $hInstance, $hBitmap, $InfoBlock, $GlobalMemoryBlock, $MemoryPointer, $ResSize
If $DLL = -1 Then
$hInstance = _WinAPI_GetModuleHandle("")
Else
$hInstance = _WinAPI_LoadLibraryEx($DLL, $LOAD_LIBRARY_AS_DATAFILE)
EndIf
If $hInstance = 0 Then Return SetError(1, 0, 0)
If $ResType = $RT_BITMAP Then
$hBitmap = _WinAPI_LoadImage($hInstance, $ResName, $IMAGE_BITMAP, 0, 0, 0)
If @error Then Return SetError(2, 0, 0)
Return $hBitmap ; returns handle to Bitmap
EndIf
If $ResLang <> 0 Then
$InfoBlock = DllCall("kernel32.dll", "ptr", "FindResourceExW", "ptr", $hInstance, "long", $ResType, "wstr", $ResName, "short", $ResLang)
Else
$InfoBlock = DllCall("kernel32.dll", "ptr", "FindResourceW", "ptr", $hInstance, "wstr", $ResName, "long", $ResType)
EndIf
If @error Then Return SetError(3, 0, 0)
$InfoBlock = $InfoBlock[0]
If $InfoBlock = 0 Then Return SetError(4, 0, 0)
$ResSize = DllCall("kernel32.dll", "dword", "SizeofResource", "ptr", $hInstance, "ptr", $InfoBlock)
If @error Then Return SetError(5, 0, 0)
$ResSize = $ResSize[0]
If $ResSize = 0 Then Return SetError(6, 0, 0)
$GlobalMemoryBlock = DllCall("kernel32.dll", "ptr", "LoadResource", "ptr", $hInstance, "ptr", $InfoBlock)
If @error Then Return SetError(7, 0, 0)
$GlobalMemoryBlock = $GlobalMemoryBlock[0]
If $GlobalMemoryBlock = 0 Then Return SetError(8, 0, 0)
$MemoryPointer = DllCall("kernel32.dll", "ptr", "LockResource", "ptr", $GlobalMemoryBlock)
If @error Then Return SetError(9, 0, 0)
$MemoryPointer = $MemoryPointer[0]
If $MemoryPointer = 0 Then Return SetError(10, 0, 0)
;~ If $DLL <> -1 Then _WinAPI_FreeLibrary($hInstance)
;~ If @error Then Return SetError(11, 0, 0)
SetExtended($ResSize)
Return $MemoryPointer
EndFunc ;==>_ResourceGet
; for ANSI strings
Func _ResourceGetAsString($ResName, $ResType = 10, $ResLang = 0, $DLL = -1) ; $RT_RCDATA = 10
Local $ResPointer, $ResSize, $struct
$ResPointer = _ResourceGet($ResName, $ResType, $ResLang, $DLL)
If @error Then
SetError(1, 0, 0)
Return ''
EndIf
$ResSize = @extended
$struct = DllStructCreate("char[" & $ResSize & "]", $ResPointer)
Return DllStructGetData($struct, 1) ; returns string
EndFunc ;==>_ResourceGetAsString
; for Unicode strings (Widechar)
Func _ResourceGetAsStringW($ResName, $ResType = 10, $ResLang = 0, $DLL = -1) ; $RT_RCDATA = 10
Local $ResPointer, $ResSize, $struct
$ResPointer = _ResourceGet($ResName, $ResType, $ResLang, $DLL)
If @error Then
SetError(1, 0, 0)
Return ''
EndIf
$ResSize = @extended
$struct = DllStructCreate("wchar[" & $ResSize & "]", $ResPointer)
Return DllStructGetData($struct, 1) ; returns string
EndFunc ;==>_ResourceGetAsStringW
; _ResourceGetAsBytes() doesn't work for RT_BITMAP type
; because _ResourceGet() returns hBitmap instead of memory pointer in this case
;~ Func _ResourceGetAsBytes($ResName, $ResType = 10, $ResLang = 0, $DLL = -1) ; $RT_RCDATA = 10
;~ Local $ResPointer, $ResSize
;~ $ResPointer = _ResourceGet($ResName, $ResType, $ResLang, $DLL)
;~ If @error Then Return SetError(1, 0, 0)
;~ $ResSize = @extended
;~ $struct = DllStructCreate("byte[" & $ResSize & "]", $ResPointer)
;~ Return DllStructGetData($struct, 1); returns directly bytes
;~ EndFunc
Func _ResourceGetAsBytes($ResName, $ResType = 10, $ResLang = 0, $DLL = -1) ; $RT_RCDATA = 10
Local $struct = _ResourceGetAsStruct($ResName, $ResType, $ResLang, $DLL)
If @error Then Return SetError(1, 0, 0)
Return DllStructGetData($struct, 1); returns directly bytes
EndFunc ;==>_ResourceGetAsBytes
; _ResourceGetAsStruct() doesn't work for RT_BITMAP type
; because _ResourceGet() returns hBitmap instead of memory pointer in this case
Func _ResourceGetAsStruct($ResName, $ResType = 10, $ResLang = 0, $DLL = -1) ; $RT_RCDATA = 10
Local $ResPointer, $ResSize
$ResPointer = _ResourceGet($ResName, $ResType, $ResLang, $DLL)
If @error Then Return SetError(1, 0, 0)
$ResSize = @extended
Return DllStructCreate("byte[" & $ResSize & "]", $ResPointer) ; returns struct with bytes
EndFunc ;==>_ResourceGetAsStruct
; returned hImage can be used in many GDI+ functions:
; $width = _GDIPlus_ImageGetWidth ($hImage)
; $height = _GDIPlus_ImageGetHeight($hImage)
Func _ResourceGetAsImage($ResName, $ResType = 10, $DLL = -1) ; $RT_RCDATA = 10
Local $ResData, $nSize, $hData, $pData, $pStream, $pBitmap, $hBitmap
Local $hImage
$ResData = _ResourceGet($ResName, $ResType, 0, $DLL)
If @error Then Return SetError(1, 0, 0)
$nSize = @extended
If $ResType = $RT_BITMAP Then
; $ResData is hBitmap type
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($ResData)
Else
; $ResData is memory pointer
; thanks ProgAndy
$hData = _MemGlobalAlloc($nSize, 2)
$pData = _MemGlobalLock($hData)
_MemMoveMemory($ResData, $pData, $nSize)
_MemGlobalUnlock($hData)
$pStream = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "ptr", $hData, "int", 1, "ptr*", 0)
$pStream = $pStream[3]
$hImage = DllCall($__g_hGDIPDll, "int", "GdipCreateBitmapFromStream", "ptr", $pStream, "ptr*", 0) ; $ghGDIPDll --> $__g_hGDIPDll
$hImage = $hImage[2]
_WinAPI_DeleteObject($pStream)
; next line must be commented otherwise animated GIFs will not work
; user is responsible for calling _MemGlobalFree($hData) after using image
;~ _MemGlobalFree($hData)
SetExtended($hData)
EndIf
Return $hImage ; hImage type
EndFunc ;==>_ResourceGetAsImage
Func _ResourceGetAsBitmap($ResName, $ResType = 10, $DLL = -1) ; $RT_RCDATA = 10
Local $hImage
$hImage = _ResourceGetAsImage($ResName, $ResType, $DLL)
If @error Then Return SetError(1, 0, 0)
Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
Return $hBitmap ; hBitmap type
EndFunc ;==>_ResourceGetAsBitmap
Func _ResourceSaveToFile($FileName, $ResName, $ResType = 10, $ResLang = 0, $CreatePath = 0, $DLL = -1) ; $RT_RCDATA = 10
Local $ResStruct, $ResSize, $FileHandle
Local $hImage
If $CreatePath Then $CreatePath = 8 ; mode 8 = Create directory structure if it doesn't exist in FileOpen()
If $ResType = $RT_BITMAP Then
; workaround: for RT_BITMAP _ResourceGetAsStruct() doesn't work so use _ResourceGetAsImage()
$hImage = _ResourceGetAsImage($ResName, $ResType)
If @error Then Return SetError(10, 0, 0)
; create filepath if doesn't exist
$FileHandle = FileOpen($FileName, 2 + 16 + $CreatePath)
If @error Then Return SetError(11, 0, 0)
FileClose($FileHandle)
If @error Then Return SetError(12, 0, 0)
_GDIPlus_ImageSaveToFile($hImage, $FileName)
_GDIPlus_ImageDispose($hImage)
$ResSize = FileGetSize($FileName)
Else
; standard way
$ResStruct = _ResourceGetAsStruct($ResName, $ResType, $ResLang, $DLL)
If @error Then Return SetError(1, 0, 0)
$ResSize = DllStructGetSize($ResStruct)
$FileHandle = FileOpen($FileName, 2 + 16 + $CreatePath)
If @error Then Return SetError(2, 0, 0)
FileWrite($FileHandle, DllStructGetData($ResStruct, 1))
If @error Then Return SetError(3, 0, 0)
FileClose($FileHandle)
If @error Then Return SetError(4, 0, 0)
EndIf
Return $ResSize
EndFunc ;==>_ResourceSaveToFile
Func _ResourceSetImageToCtrl($CtrlId, $ResName, $ResType = 10, $DLL = -1) ; $RT_RCDATA = 10
Local $ResData, $nSize, $hData, $pData, $pStream, $pBitmap, $hBitmap
$ResData = _ResourceGet($ResName, $ResType, 0, $DLL)
If @error Then Return SetError(1, 0, 0)
$nSize = @extended
If $ResType = $RT_BITMAP Then
_SetBitmapToCtrl($CtrlId, $ResData)
If @error Then Return SetError(2, 0, 0)
Else
; thanks ProgAndy
; for other types than BITMAP use GDI+ for converting to bitmap first
$hData = _MemGlobalAlloc($nSize, 2)
$pData = _MemGlobalLock($hData)
_MemMoveMemory($ResData, $pData, $nSize)
_MemGlobalUnlock($hData)
$pStream = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "ptr", $hData, "int", 1, "ptr*", 0)
$pStream = $pStream[3]
$pBitmap = DllCall($__g_hGDIPDll, "int", "GdipCreateBitmapFromStream", "ptr", $pStream, "ptr*", 0) ; $ghGDIPDll --> $__g_hGDIPDll
$pBitmap = $pBitmap[2]
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($pBitmap)
_SetBitmapToCtrl($CtrlId, $hBitmap)
If @error Then SetError(3, 0, 0)
_GDIPlus_BitmapDispose($pBitmap)
_WinAPI_DeleteObject($pStream)
_MemGlobalFree($hData)
EndIf
Return 1
EndFunc ;==>_ResourceSetImageToCtrl
; internal helper function
; thanks for improvements Melba
Func _SetBitmapToCtrl($CtrlId, $hBitmap)
Local Const $STM_SETIMAGE = 0x0172
Local Const $STM_GETIMAGE = 0x0173
Local Const $BM_SETIMAGE = 0xF7
Local Const $BM_GETIMAGE = 0xF6
Local Const $IMAGE_BITMAP = 0
Local Const $SS_BITMAP = 0x0E
Local Const $BS_BITMAP = 0x0080
Local Const $GWL_STYLE = -16
Local $hWnd, $hPrev, $Style, $iCtrl_SETIMAGE, $iCtrl_GETIMAGE, $iCtrl_BITMAP
$hWnd = GUICtrlGetHandle($CtrlId)
If $hWnd = 0 Then Return SetError(1, 0, 0)
$CtrlId = _WinAPI_GetDlgCtrlID($hWnd) ; support for $CtrlId = -1
If @error Then Return SetError(2, 0, 0)
; determine control class and adjust constants accordingly
Switch _WinAPI_GetClassName($CtrlId)
Case "Button" ; button,checkbox,radiobutton,groupbox
$iCtrl_SETIMAGE = $BM_SETIMAGE
$iCtrl_GETIMAGE = $BM_GETIMAGE
$iCtrl_BITMAP = $BS_BITMAP
Case "Static" ; picture,icon,label
$iCtrl_SETIMAGE = $STM_SETIMAGE
$iCtrl_GETIMAGE = $STM_GETIMAGE
$iCtrl_BITMAP = $SS_BITMAP
Case Else
Return SetError(3, 0, 0)
EndSwitch
; set SS_BITMAP/BS_BITMAP style to the control
$Style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE)
If @error Then Return SetError(4, 0, 0)
_WinAPI_SetWindowLong($hWnd, $GWL_STYLE, BitOR($Style, $iCtrl_BITMAP))
If @error Then Return SetError(5, 0, 0)
; set image to the control
$hPrev = _SendMessage($hWnd, $iCtrl_SETIMAGE, $IMAGE_BITMAP, $hBitmap)
If @error Then Return SetError(6, 0, 0)
If $hPrev Then _WinAPI_DeleteObject($hPrev)
Return 1
EndFunc ;==>_SetBitmapToCtrl
; thanks Larry,ProgAndy
; MSDN: http://msdn2.microsoft.com/en-us/library/ms712879.aspx
; default flag is $SND_SYNC = 0
Func _ResourcePlaySound($ResName, $Flag = 0, $DLL = -1)
Local $hInstance
If $DLL = -1 Then
$hInstance = 0
Else
$hInstance = _WinAPI_LoadLibraryEx($DLL, $LOAD_LIBRARY_AS_DATAFILE)
EndIf
Local $ret = DllCall("winmm.dll", "int", "PlaySound", "str", $ResName, "hwnd", $hInstance, "int", BitOR($SND_RESOURCE, $Flag))
If @error Then Return SetError(1, 0, 0)
If $DLL <> -1 Then _WinAPI_FreeLibrary($hInstance)
If @error Then Return SetError(2, 0, 0)
Return $ret[0]
EndFunc ;==>_ResourcePlaySound