Jump to content
Sign in to follow this  
Rawox

_CreateBitmapFromIcon

Recommended Posts

Rawox

Hi there,

I found this topic and Yashied posted a way to add an icon to a menu without using an UDF.

I want to implement this part into my script because the UDF isn't fully compatible with Windows 7 and 64bit systems (exactly where I am on...)

So I tried this:

_GUICtrlMenu_SetItemBmp ($hMenu, 0, _CreateBitmapFromIcon(_WinAPI_GetSysColor($COLOR_MENU), @ScriptDir & '\favicon.ico', 43, 16, 16))
Func _CreateBitmapFromIcon($iBackground, $sIcon, $iIndex, $iWidth, $iHeight)

    Local $hDC, $hBackDC, $hBackSv, $hIcon, $hBitmap

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    $hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hBitmap)
    $hIcon = $sIcon;_WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)
    If Not @error Then
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
    _WinAPI_DestroyIcon($hIcon)
    EndIf
    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteDC($hBackDC)
    Return $hBitmap
EndFunc ;==>_CreateBitmapFromIcon

Func _WinAPI_PrivateExtractIcon($sIcon, $iIndex, $iWidth, $iHeight)

    Local $hIcon, $tIcon = DllStructCreate('hwnd'), $tID = DllStructCreate('hwnd')
    Local $Ret = DllCall('user32.dll', 'int', 'PrivateExtractIcons', 'str', $sIcon, 'int', $iIndex, 'int', $iWidth, 'int', $iHeight, 'ptr', DllStructGetPtr($tIcon), 'ptr', DllStructGetPtr($tID), 'int', 1, 'int', 0)

    If (@error) Or ($Ret[0] = 0) Then
    Return SetError(1, 0, 0)
    EndIf
    $hIcon = DllStructGetData($tIcon, 1)
    If ($hIcon = Ptr(0)) Or (Not IsPtr($hIcon)) Then
    Return SetError(1, 0, 0)
    EndIf
    Return $hIcon
EndFunc
But it doesn't display the icon... How come, and how to fix it?

Thanks in advance,

Rawox

favicon.ico

Share this post


Link to post
Share on other sites
UEZ

This works on my Win7 x64 VM!

#include <GDIPlus.au3>
#include <GuiMenu.au3>
#include <GuiConstantsEx.au3>
#include <WinAPI.au3>

Global $iMemo


$file = FileOpenDialog("Select ICO file", @ScriptDir, ("Icons (*.ico)"))

If @error Then Exit

$Ret = DllCall("shell32", "long", "ExtractAssociatedIcon", "int", 0, "str", $file, "int*", 0)
$hIcon = $Ret[0]

_GDIPlus_Startup()
$hBitmap = DllCall($ghGDIPDll,"int", "GdipCreateBitmapFromHICON", "ptr", $hIcon, "int*", 0)
$hBitmap = $hBitmap[2]
_WinAPI_DestroyIcon($hIcon)

_Main()

_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()

Exit

Func _Main()
    Local $hGUI, $hFile, $hEdit, $hHelp, $hMain
    Local Enum $idNew = 1000, $idOpen, $idSave, $idExit, $idCut, $idCopy, $idPaste, $idAbout

    ; Create GUI
    $hGUI = GUICreate("Menu", 400, 300)

    ; Create File menu
    $hFile = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hFile, 0, "&New", $idNew)
    _GUICtrlMenu_InsertMenuItem ($hFile, 1, "&Open", $idOpen)
    _GUICtrlMenu_InsertMenuItem ($hFile, 2, "&Save", $idSave)
    _GUICtrlMenu_InsertMenuItem ($hFile, 3, "", 0)
    _GUICtrlMenu_InsertMenuItem ($hFile, 4, "E&xit", $idExit)

    ; Create Edit menu
    $hEdit = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hEdit, 0, "&Cut", $idCut)
    _GUICtrlMenu_InsertMenuItem ($hEdit, 1, "C&opy", $idCopy)
    _GUICtrlMenu_InsertMenuItem ($hEdit, 2, "&Paste", $idPaste)

    ; Create Help menu
    $hHelp = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hHelp, 0, "&About", $idAbout)

    ; Create Main menu
    $hMain = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hMain, 0, "&File", 0, $hFile)
    _GUICtrlMenu_InsertMenuItem ($hMain, 1, "&Edit", 0, $hEdit)
    _GUICtrlMenu_InsertMenuItem ($hMain, 2, "&Help", 0, $hHelp)

    ; Set window menu
    _GUICtrlMenu_SetMenu ($hGUI, $hMain)

    ; Create memo control
    $iMemo = GUICtrlCreateEdit("", 2, 2, 396, 276, 0)
    GUICtrlSetFont($iMemo, 9, 400, 0, "Courier New")
    GUISetState()

    ; Set New menu item to have a bitmap
    _GUICtrlMenu_SetItemBmp ($hFile, 0, _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap))
    MemoWrite("Item bitmap handle: 0x" & Hex(_GUICtrlMenu_GetItemBmp ($hFile, 0)))

    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc ;==>_Main

; Write message to memo
Func MemoWrite($sMessage)
    GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
EndFunc ;==>MemoWrite

After selecting an icon press file and you should see the icon for item new.

BR,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Rawox

Ok thanks! And how could I make it 16x16?? :mellow:

Edited by Rawox

Share this post


Link to post
Share on other sites
UEZ

Here a fast and inelegant solution:

#AutoIt3Wrapper_Icon=c:\_Downloads\popup.au3.ico
#include <GDIPlus.au3>
#include <GuiMenu.au3>
#include <GuiConstantsEx.au3>
#include <WinAPI.au3>

Global $iMemo


$file = FileOpenDialog("Select ICO file", @ScriptDir, ("Icons (*.ico)"))

If @error Then Exit

$Ret = DllCall("shell32", "long", "ExtractAssociatedIcon", "int", 0, "str", $file, "int*", 0)
$hIcon = $Ret[0]

_GDIPlus_Startup()
$hImage = DllCall($ghGDIPDll,"int", "GdipCreateBitmapFromHICON", "ptr", $hIcon, "int*", 0)
$hImage = $hImage[2]
_WinAPI_DestroyIcon($hIcon)

$dest_x = 16
$dest_y = 16
$iX = _GDIPlus_ImageGetWidth($hImage)
$iY = _GDIPlus_ImageGetHeight($hImage)
$hGUI = GUICreate("", $iX, $iY)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($dest_x, $dest_y, $hGraphics)
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsDrawImageRect($hBuffer, $hImage, 0, 0, $dest_x, $dest_y)
GUIDelete($hGUI)

_Main()

_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_GraphicsDispose($hBuffer)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

Exit

Func _Main()
    Local $hGUI, $hFile, $hEdit, $hHelp, $hMain
    Local Enum $idNew = 1000, $idOpen, $idSave, $idExit, $idCut, $idCopy, $idPaste, $idAbout

    ; Create GUI
    $hGUI = GUICreate("Menu", 400, 300)

    ; Create File menu
    $hFile = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hFile, 0, "&New", $idNew)
    _GUICtrlMenu_InsertMenuItem ($hFile, 1, "&Open", $idOpen)
    _GUICtrlMenu_InsertMenuItem ($hFile, 2, "&Save", $idSave)
    _GUICtrlMenu_InsertMenuItem ($hFile, 3, "", 0)
    _GUICtrlMenu_InsertMenuItem ($hFile, 4, "E&xit", $idExit)

    ; Create Edit menu
    $hEdit = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hEdit, 0, "&Cut", $idCut)
    _GUICtrlMenu_InsertMenuItem ($hEdit, 1, "C&opy", $idCopy)
    _GUICtrlMenu_InsertMenuItem ($hEdit, 2, "&Paste", $idPaste)

    ; Create Help menu
    $hHelp = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hHelp, 0, "&About", $idAbout)

    ; Create Main menu
    $hMain = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hMain, 0, "&File", 0, $hFile)
    _GUICtrlMenu_InsertMenuItem ($hMain, 1, "&Edit", 0, $hEdit)
    _GUICtrlMenu_InsertMenuItem ($hMain, 2, "&Help", 0, $hHelp)

    ; Set window menu
    _GUICtrlMenu_SetMenu ($hGUI, $hMain)

    ; Create memo control
    $iMemo = GUICtrlCreateEdit("", 2, 2, 396, 276, 0)
    GUICtrlSetFont($iMemo, 9, 400, 0, "Courier New")
    GUISetState()

    ; Set New menu item to have a bitmap
    _GUICtrlMenu_SetItemBmp ($hFile, 0, _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap))
    MemoWrite("Item bitmap handle: 0x" & Hex(_GUICtrlMenu_GetItemBmp ($hFile, 0)))

    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc ;==>_Main

; Write message to memo
Func MemoWrite($sMessage)
    GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
EndFunc ;==>MemoWrite

When I find a better way I will post it!

BR,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Authenticity

Even though UEZ's method should work flawlessly, Yashied's function works as well. You've just used it incorrectly:

_GUICtrlMenu_SetItemBmp ($hMenu, 0, _CreateBitmapFromIcon(_WinAPI_GetSysColor($COLOR_MENU), @ScriptDir & '\favicon.ico', 0, 16, 16))

You've specified 43 as the index, but it should be 0 for .ico files.

Share this post


Link to post
Share on other sites
Rawox

Thanks both for the information =]

Share this post


Link to post
Share on other sites
UEZ

This version is more elegant than from post #4:

#include <GDIPlus.au3>
#include <GuiMenu.au3>
#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WinAPIEx.au3>
#include <WindowsConstants.au3>
#Include <Constants.au3>
Global $iMemo


$file = FileOpenDialog("Select ICO file", @ScriptDir, ("Icons (*.ico)"))

If @error Then Exit

$Ret = DllCall("shell32", "long", "ExtractAssociatedIcon", "int", 0, "str", $file, "int*", 0)
$hIcon = $Ret[0]

_GDIPlus_Startup()
$hImage = DllCall($ghGDIPDll,"int", "GdipCreateBitmapFromHICON", "ptr", $hIcon, "int*", 0)
$hImage = $hImage[2]
_WinAPI_DestroyIcon($hIcon)

$dest_x = 16
$dest_y = 16

$hBitmap = _GDIPlus_BitmapCreateFromScan0($dest_x, $dest_y)
$hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsDrawImageRect($hContext, $hImage, 0, 0, $dest_x, $dest_y)
$hIcon = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)

_Main()

_GDIPlus_GraphicsDispose($hContext)
_WinAPI_DeleteObject($hIcon)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()

Exit


Func _Main()
    Local $hGUI, $hFile, $hEdit, $hHelp, $hMain
    Local Enum $idNew = 1000, $idOpen, $idSave, $idExit, $idCut, $idCopy, $idPaste, $idAbout

    ; Create GUI
    $hGUI = GUICreate("Menu", 400, 300)

    ; Create File menu
    $hFile = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hFile, 0, "&New", $idNew)
    _GUICtrlMenu_InsertMenuItem ($hFile, 1, "&Open", $idOpen)
    _GUICtrlMenu_InsertMenuItem ($hFile, 2, "&Save", $idSave)
    _GUICtrlMenu_InsertMenuItem ($hFile, 3, "", 0)
    _GUICtrlMenu_InsertMenuItem ($hFile, 4, "E&xit", $idExit)

    ; Create Edit menu
    $hEdit = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hEdit, 0, "&Cut", $idCut)
    _GUICtrlMenu_InsertMenuItem ($hEdit, 1, "C&opy", $idCopy)
    _GUICtrlMenu_InsertMenuItem ($hEdit, 2, "&Paste", $idPaste)

    ; Create Help menu
    $hHelp = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hHelp, 0, "&About", $idAbout)

    ; Create Main menu
    $hMain = _GUICtrlMenu_CreateMenu ()
    _GUICtrlMenu_InsertMenuItem ($hMain, 0, "&File", 0, $hFile)
    _GUICtrlMenu_InsertMenuItem ($hMain, 1, "&Edit", 0, $hEdit)
    _GUICtrlMenu_InsertMenuItem ($hMain, 2, "&Help", 0, $hHelp)

    ; Set window menu
    _GUICtrlMenu_SetMenu ($hGUI, $hMain)

    ; Create memo control
    $iMemo = GUICtrlCreateEdit("", 2, 2, 396, 276, 0)
    GUICtrlSetFont($iMemo, 9, 400, 0, "Courier New")
    GUISetState()

    ; Set New menu item to have a bitmap
    _GUICtrlMenu_SetItemBmp ($hFile, 0, $hIcon)
    MemoWrite("Item bitmap handle: 0x" & Hex(_GUICtrlMenu_GetItemBmp ($hFile, 0)))

    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc ;==>_Main

; Write message to memo
Func MemoWrite($sMessage)
    GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
EndFunc ;==>MemoWrite

Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[6]
EndFunc ;==>_GDIPlus_BitmapCreateFromScan0

BR,

UEZ

PS: transparent icons are not supported with this method!

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×