Что нового

Добавляем иконки в меню (Vista)

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
В Windows Vista появилась возможность добавлять в меню битмапы содержащие прозрачность. При этом при наведении курсора на такой пункт меню, иконка не инверсируется как в Windows XP, а остается "красивой". И все это достигается стандартными API функциями без всяких танцев с бубном. Здесь я написал функцию _Create32BitHBITMAP() для конвертирования иконки (HICON) в 32-битный битмап (HBITMAP) для последующей вставки его в меню. В принципе, это немного измененный пример из MSDN, но вся загвоздка заключалась в том, что иконки не обязательно должны быть 32-битные (RGB+Alpha). Вообщем, вот, что у меня получилось. Для запуска этого примера вам понадобится WinAPIEx UDF.

Код:
#NoTrayIcon

#Include <Constants.au3>
#Include <GDIPlus.au3>
#Include <GUIMenu.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>

If _WinAPI_GetVersion() < '6.0' Then
	MsgBox(16, '', 'Require Windows Vista or later.')
	Exit
EndIf

_GDIPlus_Startup()

#cs

$hForm = GUICreate('MyGUI', 400, 400)

$hFile = _GUICtrlMenu_CreateMenu()
_GUICtrlMenu_InsertMenuItem($hFile, 0, 'Options')
_GUICtrlMenu_SetItemBmp($hFile, 0, _Create32BitHBITMAP(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 130, 16, 16), 1))
_GUICtrlMenu_InsertMenuItem($hFile, 1, '')
_GUICtrlMenu_InsertMenuItem($hFile, 2, 'Exit')
_GUICtrlMenu_SetItemBmp($hFile, 2, _Create32BitHBITMAP(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 131, 16, 16), 1))

$hMenu = _GUICtrlMenu_CreateMenu()
_GUICtrlMenu_InsertMenuItem($hMenu, 0, 'File', 0, $hFile)

_GUICtrlMenu_SetMenu($hForm, $hMenu)

GUISetState()

Do
Until GUIGetMsg() = -3

#ce

Opt('TrayMenuMode', 3)

$hMenu = TrayItemGetHandle(0)
$Options = TrayCreateItem('Options')
TrayCreateItem('')
$Exit  = TrayCreateItem('Exit')

_GUICtrlMenu_SetItemBmp($hMenu, 0, _Create32BitHBITMAP(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 130, 16, 16), 1))
_GUICtrlMenu_SetItemBmp($hMenu, 2, _Create32BitHBITMAP(_WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 131, 16, 16), 1))

TraySetState()

Do
Until TrayGetMsg() = $Exit

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 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


post_img_070.png
 

Ромка Пупков

Новичок
Сообщения
25
Репутация
1
Код:
P:\desktop\new3.44090374978259.au3(89,55) : WARNING: $BI_RGB: possibly used before declaration.
    DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
P:\desktop\new3.44090374978259.au3(92,71) : WARNING: $DIB_RGB_COLORS: possibly used before declaration.
    $hBitmap = _WinAPI_CreateDIBSection($hDC, $tBIHDR, $DIB_RGB_COLORS,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
P:\desktop\new3.44090374978259.au3(89,55) : ERROR: $BI_RGB: undeclared global variable.
    DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
P:\desktop\new3.44090374978259.au3(92,71) : ERROR: $DIB_RGB_COLORS: undeclared global variable.
    $hBitmap = _WinAPI_CreateDIBSection($hDC, $tBIHDR, $DIB_RGB_COLORS,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
P:\desktop\new3.44090374978259.au3 - 2 error(s), 2 warning(s)
!>19:54:31 AU3Check ended. Press F4 to jump to next error.rc:2
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Семёнычев Роман,
Добавьте
Код:
#include <APIConstants.au3>
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Семёнычев Роман
не судьба в первом сообщении пройтись по ссылке?
 
Верх