- Сообщения
- 5,379
- Репутация
- 2,724
По поводу иконок. Если объединить последний код в этой ветке с этим, то получится то, что надо. Иконки будут работать только в Windows Vista и выше.
Settings.ini
Example.au3
Тоже самое, только для контекстного меню.
Settings.ini
Код:
[Menu]
Open=Файл>Открыть
Save=Файл>Сохранить
SaveAs=Файл>Сохранить как...
Copy=Редактировать>Копировать
Paste=Редактировать>Вставить
Separator=*
Skin=Настройки>Интерфейс>Скин
Size=Настройки>Интерфейс>Размеры
Color=Настройки>Интерфейс>Цвет
Separator=Настройки>Интерфейс>*
Expert=Настройки>Интерфейс>Дополнительно...
Miscellaneous=Настройки>Общие
Separator=*
Exit=Выход
[Icon]
Open=shell32.dll,45
Save=shell32.dll,258
SaveAs=shell32.dll,68
Copy=shell32.dll,134
Paste=shell32.dll,260
Skin=shell32.dll,303
Size=shell32.dll,240
Color=mspaint.exe,0
Expert=shell32.dll,300
Miscellaneous=shell32.dll,21
Exit=shell32.dll,131
Example.au3
Код:
#NoTrayIcon
#Include <Constants.au3>
#Include <GDIPlus.au3>
#Include <GUIMenu.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>
Opt('TrayMenuMode', 3)
Global $ID
#cs
$ID[i][0] - ID of the menu item
$ID[i][1] - Command
#ce
If Not _IniCreateTrayMenu(-1, @ScriptDir & '\Settings.ini', $ID) Then
MsgBox(16, 'Error', 'Ошибка создания меню.')
Exit
EndIf
TraySetState()
While 1
$Msg = TrayGetMsg()
Switch $Msg
Case 0
ContinueLoop
Case Else
For $i = 1 To $ID[0][0]
If $ID[$i][0] = $Msg Then
; Здесь проверяются все пункты меню по их ключу в .ini файле
Switch $ID[$i][1]
; Case 'Open'
; Case 'Save'
; Case ...
Case 'Exit'
Exit
Case Else
MsgBox(0, '', $ID[$i][1])
EndSwitch
ExitLoop
EndIf
Next
EndSwitch
WEnd
Func _Create32BitHBITMAP($hIcon, $fDelete = 0)
Local $tBI, $tBIHDR, $hDC, $hDstDC, $hDstSv, $hSrcDC, $hSrcSv, $hBitmap, $hImage, $hObj, $tBits, $pBits, $aIcon, $Width, $Height, $Alpha = True, $Error = False
$aIcon = _WinAPI_GetIconInfo($hIcon)
If Not IsArray($aIcon) Then
Return 0
EndIf
$tBI = DllStructCreate($tagBITMAP)
If _WinAPI_GetObject($aIcon[5], DllStructGetSize($tBI), DllStructGetPtr($tBI)) Then
$Width = DllStructGetData($tBI, 'bmWidth')
$Height = DllStructGetData($tBI, 'bmHeight')
$tBits = DllStructCreate('byte[' & (4 * $Width * $Height) & ']')
If _WinAPI_GetBitmapBits($aIcon[5], DllStructGetSize($tBits), DllStructGetPtr($tBits)) Then
;~ If StringReplace(StringRegExpReplace(DllStructGetData($tBits, 1), '0x|(.{6})(.{2})', '\2'), '0', '') Then
If StringRegExp(DllStructGetData($tBits, 1), '^(0x)?(.{6}(00))+\Z') Then
$Alpha = 0
EndIf
Else
$Error = 1
EndIf
Else
$Error = 1
EndIf
For $i = 4 To 5
_WinAPI_DeleteObject($aIcon[$i])
Next
If $Error Then
Return 0
EndIf
$tBIHDR = DllStructCreate($tagBITMAPINFOHEADER)
DllStructSetData($tBIHDR, 'biSize', DllStructGetSize($tBIHDR))
DllStructSetData($tBIHDR, 'biWidth', $Width)
DllStructSetData($tBIHDR, 'biHeight', $Height)
DllStructSetData($tBIHDR, 'biPlanes', 1)
DllStructSetData($tBIHDR, 'biBitCount', 32)
DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
$hDC = _WinAPI_GetDC(0)
$hDstDC = _WinAPI_CreateCompatibleDC($hDC)
$hBitmap = _WinAPI_CreateDIBSection($hDC, $tBIHDR, $DIB_RGB_COLORS, $pBits)
$hDstSv = _WinAPI_SelectObject($hDstDC, $hBitmap)
If $Alpha Then
_WinAPI_DrawIconEx($hDstDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
Else
_GDIPlus_Startup()
$hImage = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromHICON', 'ptr', $hIcon, 'ptr*', 0)
If (Not @error) And (Not $hImage[0]) Then
$hObj = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage[2])
_GDIPlus_ImageDispose($hImage[2])
Else
$hObj = 0
EndIf
_GDIPlus_Shutdown()
If $hObj Then
$hSrcDC = _WinAPI_CreateCompatibleDC($hDC)
$hSrcSv = _WinAPI_SelectObject($hSrcDC, $hObj)
_WinAPI_BitBlt($hDstDC, 0, 0, $Width, $Height, $hSrcDC, 0, 0, $SRCCOPY)
_WinAPI_SelectObject($hSrcDC, $hSrcSv)
_WinAPI_DeleteObject($hObj)
_WinAPI_DeleteDC($hSrcDC)
Else
$Error = 1
EndIf
EndIf
_WinAPI_ReleaseDC(0, $hDC)
_WinAPI_SelectObject($hDstDC, $hDstSv)
_WinAPI_DeleteDC($hDstDC)
If $fDelete Then
_WinAPI_DestroyIcon($hIcon)
EndIf
If $Error Then
_WinAPI_DeleteObject($hBitmap)
Return 0
EndIf
Return $hBitmap
EndFunc ;==>_Create32BitHBITMAP
Func _IniCreateTrayMenu($CtrlID, $sPath, ByRef $aID, $sRoot = '', $iLevel = 0)
Static $aIco, $aIni
Local $hWnd, $Icon, $Item, $Menu, $Path, $Index = -1
If Not $iLevel Then
$aIni = IniReadSection($sPath, 'Menu')
If @error Then
Return 0
Else
$Item = 0
For $i = 1 To $aIni[0][0]
If ($aIni[$i][1]) And (StringRegExpReplace($aIni[$i][1], '^.*>', '') <> '*') Then
$Item += 1
EndIf
Next
If $Item Then
Dim $aID[$Item + 1][2] = [[0]]
Else
$aID = 0
Return 0
EndIf
EndIf
If _WinAPI_GetVersion() >= '6.0' Then
$aIco = IniReadSection($sPath, 'Icon')
Else
$aIco = 0
EndIf
EndIf
While 1
$aIni[0][1] += 1
If $aIni[0][1] > $aIni[0][0] Then
Return 1
EndIf
$aIni[$aIni[0][1]][1] = StringRegExpReplace(StringRegExpReplace($aIni[$aIni[0][1]][1], '\A>*|>*\Z', ''), '>+', '>')
If Not $aIni[$aIni[0][1]][1] Then
ContinueLoop
EndIf
$Path = StringRegExpReplace($aIni[$aIni[0][1]][1], '>.[^>]*\Z', '')
$Item = StringSplit($aIni[$aIni[0][1]][1], '>')
If $Item[0] = 1 Then
If $sRoot Then
$aIni[0][1] -= 1
Return 1
EndIf
Else
If $Path <> $sRoot Then
If (Not $sRoot) Or (StringInStr($Path, $sRoot) = 1) Then
If $sRoot Then
$Item = StringSplit(StringReplace($aIni[$aIni[0][1]][1], $sRoot & '>', '', 1), '>')
$Path = $sRoot & '>' & $Item[1]
Else
$Item = StringSplit($aIni[$aIni[0][1]][1], '>')
$Path = $Item[1]
EndIf
$aIni[0][1] -= 1
$Menu = TrayCreateMenu($Item[1], $CtrlID)
If Not _IniCreateTrayMenu($Menu, '', $aID, $Path, $iLevel + 1) Then
Return 0
EndIf
$Index += 1
Else
$aIni[0][1] -= 1
Return 1
EndIf
ContinueLoop
EndIf
EndIf
$Index += 1
If $Item[$Item[0]] <> '*' Then
$aID[0][0] += 1
$aID[$aID[0][0]][0] = TrayCreateItem($Item[$Item[0]], $CtrlID)
$aID[$aID[0][0]][1] = $aIni[$aIni[0][1]][0]
Else
TrayCreateItem('', $CtrlID)
EndIf
If IsArray($aIco) Then
For $i = 1 To $aIco[0][0]
If $aIco[$i][0] = $aIni[$aIni[0][1]][0] Then
If $CtrlID <> -1 Then
$hWnd = TrayItemGetHandle($CtrlID)
Else
$hWnd = TrayItemGetHandle(0)
EndIf
$Icon = _WinAPI_PathParseIconLocation($aIco[$i][1])
If Not @error Then
_GUICtrlMenu_SetItemBmp($hWnd, $Index, _Create32BitHBITMAP(_WinAPI_ShellExtractIcon($Icon[0], $Icon[1], 16, 16), 1))
EndIf
ExitLoop
EndIf
Next
EndIf
WEnd
Return 1
EndFunc ;==>_IniCreateTrayMenu
Тоже самое, только для контекстного меню.
Код:
#Include <Array.au3>
#Include <Constants.au3>
#Include <GDIPlus.au3>
#Include <GUIConstantsEx.au3>
#Include <GUIMenu.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>
Global $ID
#cs
$ID[i][0] - ID of the menu item
$ID[i][1] - Command
#ce
GUICreate('MyGUI', 400, 400)
$Menu = GUICtrlCreateContextMenu()
If Not _IniCreateMenu($Menu, @ScriptDir & '\Settings.ini', $ID) Then
MsgBox(16, 'Error', 'Ошибка создания меню.')
Exit
Else
; _ArrayDisplay($ID)
EndIf
GUISetState()
While 1
$Msg = GUIGetMsg()
Switch $Msg
Case 0
ContinueLoop
Case $GUI_EVENT_CLOSE
Exit
Case Else
For $i = 1 To $ID[0][0]
If $ID[$i][0] = $Msg Then
; Здесь проверяются все пункты меню по их ключу в .ini файле
Switch $ID[$i][1]
; Case 'Open'
; Case 'Save'
; Case ...
Case 'Exit'
Exit
Case Else
ConsoleWrite($ID[$i][1] & @CR)
EndSwitch
ExitLoop
EndIf
Next
EndSwitch
WEnd
Func _Create32BitHBITMAP($hIcon, $fDelete = 0)
Local $tBI, $tBIHDR, $hDC, $hDstDC, $hDstSv, $hSrcDC, $hSrcSv, $hBitmap, $hImage, $hObj, $tBits, $pBits, $aIcon, $Width, $Height, $Alpha = True, $Error = False
$aIcon = _WinAPI_GetIconInfo($hIcon)
If Not IsArray($aIcon) Then
Return 0
EndIf
$tBI = DllStructCreate($tagBITMAP)
If _WinAPI_GetObject($aIcon[5], DllStructGetSize($tBI), DllStructGetPtr($tBI)) Then
$Width = DllStructGetData($tBI, 'bmWidth')
$Height = DllStructGetData($tBI, 'bmHeight')
$tBits = DllStructCreate('byte[' & (4 * $Width * $Height) & ']')
If _WinAPI_GetBitmapBits($aIcon[5], DllStructGetSize($tBits), DllStructGetPtr($tBits)) Then
;~ If StringReplace(StringRegExpReplace(DllStructGetData($tBits, 1), '0x|(.{6})(.{2})', '\2'), '0', '') Then
If StringRegExp(DllStructGetData($tBits, 1), '^(0x)?(.{6}(00))+\Z') Then
$Alpha = 0
EndIf
Else
$Error = 1
EndIf
Else
$Error = 1
EndIf
For $i = 4 To 5
_WinAPI_DeleteObject($aIcon[$i])
Next
If $Error Then
Return 0
EndIf
$tBIHDR = DllStructCreate($tagBITMAPINFOHEADER)
DllStructSetData($tBIHDR, 'biSize', DllStructGetSize($tBIHDR))
DllStructSetData($tBIHDR, 'biWidth', $Width)
DllStructSetData($tBIHDR, 'biHeight', $Height)
DllStructSetData($tBIHDR, 'biPlanes', 1)
DllStructSetData($tBIHDR, 'biBitCount', 32)
DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
$hDC = _WinAPI_GetDC(0)
$hDstDC = _WinAPI_CreateCompatibleDC($hDC)
$hBitmap = _WinAPI_CreateDIBSection($hDC, $tBIHDR, $DIB_RGB_COLORS, $pBits)
$hDstSv = _WinAPI_SelectObject($hDstDC, $hBitmap)
If $Alpha Then
_WinAPI_DrawIconEx($hDstDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
Else
_GDIPlus_Startup()
$hImage = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromHICON', 'ptr', $hIcon, 'ptr*', 0)
If (Not @error) And (Not $hImage[0]) Then
$hObj = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage[2])
_GDIPlus_ImageDispose($hImage[2])
Else
$hObj = 0
EndIf
_GDIPlus_Shutdown()
If $hObj Then
$hSrcDC = _WinAPI_CreateCompatibleDC($hDC)
$hSrcSv = _WinAPI_SelectObject($hSrcDC, $hObj)
_WinAPI_BitBlt($hDstDC, 0, 0, $Width, $Height, $hSrcDC, 0, 0, $SRCCOPY)
_WinAPI_SelectObject($hSrcDC, $hSrcSv)
_WinAPI_DeleteObject($hObj)
_WinAPI_DeleteDC($hSrcDC)
Else
$Error = 1
EndIf
EndIf
_WinAPI_ReleaseDC(0, $hDC)
_WinAPI_SelectObject($hDstDC, $hDstSv)
_WinAPI_DeleteDC($hDstDC)
If $fDelete Then
_WinAPI_DestroyIcon($hIcon)
EndIf
If $Error Then
_WinAPI_DeleteObject($hBitmap)
Return 0
EndIf
Return $hBitmap
EndFunc ;==>_Create32BitHBITMAP
Func _IniCreateMenu($CtrlID, $sPath, ByRef $aID, $sRoot = '', $iLevel = 0)
Static $aIco, $aIni
Local $Icon, $Item, $Menu, $Path, $Index = -1
If Not $iLevel Then
$aIni = IniReadSection($sPath, 'Menu')
If @error Then
Return 0
Else
$Item = 0
For $i = 1 To $aIni[0][0]
If ($aIni[$i][1]) And (StringRegExpReplace($aIni[$i][1], '^.*>', '') <> '*') Then
$Item += 1
EndIf
Next
If $Item Then
Dim $aID[$Item + 1][2] = [[0]]
Else
$aID = 0
Return 0
EndIf
EndIf
If _WinAPI_GetVersion() >= '6.0' Then
$aIco = IniReadSection($sPath, 'Icon')
Else
$aIco = 0
EndIf
EndIf
While 1
$aIni[0][1] += 1
If $aIni[0][1] > $aIni[0][0] Then
Return 1
EndIf
$aIni[$aIni[0][1]][1] = StringRegExpReplace(StringRegExpReplace($aIni[$aIni[0][1]][1], '\A>*|>*\Z', ''), '>+', '>')
If Not $aIni[$aIni[0][1]][1] Then
ContinueLoop
EndIf
$Path = StringRegExpReplace($aIni[$aIni[0][1]][1], '>.[^>]*\Z', '')
$Item = StringSplit($aIni[$aIni[0][1]][1], '>')
If $Item[0] = 1 Then
If $sRoot Then
$aIni[0][1] -= 1
Return 1
EndIf
Else
If $Path <> $sRoot Then
If (Not $sRoot) Or (StringInStr($Path, $sRoot) = 1) Then
If $sRoot Then
$Item = StringSplit(StringReplace($aIni[$aIni[0][1]][1], $sRoot & '>', '', 1), '>')
$Path = $sRoot & '>' & $Item[1]
Else
$Item = StringSplit($aIni[$aIni[0][1]][1], '>')
$Path = $Item[1]
EndIf
$aIni[0][1] -= 1
$Menu = GUICtrlCreateMenu($Item[1], $CtrlID)
If Not _IniCreateMenu($Menu, '', $aID, $Path, $iLevel + 1) Then
Return 0
EndIf
$Index += 1
Else
$aIni[0][1] -= 1
Return 1
EndIf
ContinueLoop
EndIf
EndIf
$Index += 1
If $Item[$Item[0]] <> '*' Then
$aID[0][0] += 1
$aID[$aID[0][0]][0] = GUICtrlCreateMenuItem($Item[$Item[0]], $CtrlID)
$aID[$aID[0][0]][1] = $aIni[$aIni[0][1]][0]
Else
GUICtrlCreateMenuItem('', $CtrlID)
EndIf
If IsArray($aIco) Then
For $i = 1 To $aIco[0][0]
If $aIco[$i][0] = $aIni[$aIni[0][1]][0] Then
$Icon = _WinAPI_PathParseIconLocation($aIco[$i][1])
If Not @error Then
_GUICtrlMenu_SetItemBmp(GUICtrlGetHandle($CtrlID), $Index, _Create32BitHBITMAP(_WinAPI_ShellExtractIcon($Icon[0], $Icon[1], 16, 16), 1))
EndIf
ExitLoop
EndIf
Next
EndIf
WEnd
Return 1
EndFunc ;==>_IniCreateMenu