Jump to content

Disabled Context Items Look Odd


Recommended Posts

Hello all,

I've been working on a script that has many dynamically created context menus with icons for specific listview items. Depending on the listview item that was right-clicked, different menu choices are displayed. The best way to do this that I found was to use the "_GUICtrlMenu" UDF functions with WM_NOTIFY and UEZ's awesome _GUICtrlMenu_CreateBitmap function. All in all, things work great until I disable an item that also has an icon. The icon turns all black or discolored instead of having that "disabled" look of being grayed out.

I've put together a simple reproducer to show what I'm talking about as well as a pic that displays the disabled icon from my main script

Is there any way to make the disabled menu item's icon look grayed out and not black/discolored?

Thanks!!

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <GUIMenu.au3>
#include <WindowsConstants.au3>

Global $cDummy
Global $hList

$hGUI = GUICreate("Disabled Menu Item Test", 500, 300)
$cDummy = GUICtrlCreateDummy()
$idList = GUICtrlCreateListView("Col1|Col2|Col3", 10, 10, 480, 280)
$hList = GUICtrlGetHandle(-1)
GUICtrlCreateListViewItem("Test1|Test2|Test3", $idList)

GUISetState(@SW_SHOW, $hGUI)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $cDummy
            _ShowContext($idList)
    EndSwitch
WEnd

Func _ShowContext($hWnd)
    Local Enum $idTest1 = 1000, $idTest2
    Local $sIconPath = @ProgramFilesDir & "\AutoIt3\Icons\au3.ico"
    Local $hMenu = _GUICtrlMenu_CreatePopup()
    _GUICtrlMenu_AddMenuItem($hMenu, "Test1" & @TAB & "Ctrl+1", $idTest1)
    _GUICtrlMenu_SetIcon($hMenu, 0, $sIconPath)
    _GUICtrlMenu_AddMenuItem($hMenu, "Test2" & @TAB & "Ctrl+2", $idTest2)
    _GUICtrlMenu_SetIcon($hMenu, 1, $sIconPath); <<<<<<< Any way to make this work with transparency?
    _GUICtrlMenu_SetItemDisabled($hMenu, 1)
    
    Local $idMsg = _GUICtrlMenu_TrackPopupMenu($hMenu, GUICtrlGetHandle($hWnd), -1, -1, 1, 1, 2)
    
    Switch $idMsg
        Case $idTest1
            ConsoleWrite(">> Test1" & @CRLF)
        Case $idTest2
            ConsoleWrite(">> Test2" & @CRLF)
    EndSwitch
    
    _GUICtrlMenu_DestroyMenu($hMenu)
EndFunc

Func _GUICtrlMenu_SetIcon($hWnd, $iIndex, $sIconPath)
    Local $hBMP_File_New = _GUICtrlMenu_CreateBitmap($sIconPath, 0, 16, 16)
    Return _GUICtrlMenu_SetItemBmp($hWnd, $iIndex, $hBMP_File_New)
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    
    Local $iItem
    Local $tNMHDR =   DllStructCreate($tagNMHDR, $lParam)
    Local $HwndFrom = DllStructGetData($tNMHDR, "HwndFrom")
    Local $iCode =    DllStructGetData($tNMHDR, "Code")
    
    Switch $HwndFrom
        Case $hList
            Switch $iCode
                Case $NM_RCLICK
                    $iItem = DllStructGetData(DllStructCreate($tagNMITEMACTIVATE, $lParam), "Index")
                    If $iItem <> -1 Then GUICtrlSendToDummy($cDummy)
            EndSwitch
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

; #FUNCTION# ============================================================================================================
; Name...................:  _GUICtrlMenu_CreateBitmap
; Description .......:      Extracts the icon from $sFile and converts it to a HBitmap format
; Syntax................:   _GUICtrlMenu_CreateBitmap($sFile, $iIndex = 0, $iX = 18, $iY = 18)
; Parameters ......:        $sFile      - file name where the icon should be extracted from or an image should be loaded (*.dll, *.ico, *.exe, *.jpg, *.png, *.bmp, *.gif, *.tif)
;                                       $iIndex - index of the icon from $sFile
;                                       $iX         - set the width of the extracted icon
;                                       $iY         - set the height of the extracted icon
; Return values .:          Success - handle to a HBITMAP
;                           Failure     - Returns 0 and sets error to 1-7
; Author ..............:    UEZ
; Version .............:    v0.70 Build 2012-10-13 beta
; Remarks ...........:      Don't forget to use _WinAPI_DeleteObject($<handle to the HBITMAP>) when closing to to release the resources
; =======================================================================================================================
Func _GUICtrlMenu_CreateBitmap($sFile, $iIndex = 0, $iW = 18, $iH = 18)
    Local $hIcon, $Ret, $hBitmap, $hContext, $bBinary = False
    Local $aChk = _GDIPlus_ImageGetFlags($sFile)
    If Not @error Then $bBinary = True
    If FileExists($sFile)  Or $bBinary Then
        Local Const $iStride = 0, $iPixelFormat = $GDIP_PXF32ARGB, $pScan0 = 0
        Local $fext = StringMid($sFile, StringLen($sFile) - 3)
        If $bBinary Then $fext = "0815"
        Switch $fext
            Case ".dll", ".exe", ".ico"
                Return _WinAPI_GetFileIcon($sFile, $iIndex, $iW, $iH)
            Case ".jpg", ".png", ".bmp", ".gif", ".tif", "0815"
                Local $hImage
                If Not $bBinary Then
                    $hImage = _GDIPlus_ImageLoadFromFile($sFile)
                    If @error Then Return SetError(4, @extended, 0)
                Else
                    $hImage = $sFile
                EndIf
                Local $hBitmap = _GDIPlus_BitmapCreateFromHICON32($hImage)
;~                 $Ret = DllCall($__g_hGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iW, "int", $iH, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
;~                 If @error Then Return SetError(5, @extended, 0)
;~                 $hBitmap = $Ret[6]
                $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
                DllCall($__g_hGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hContext, "int", 7)
                _GDIPlus_GraphicsDrawImageRect($hContext, $hImage, 0, 0, $iW, $iH)
                $hIcon =  _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
                _GDIPlus_GraphicsDispose($hContext)
                _GDIPlus_BitmapDispose($hBitmap)
                _GDIPlus_BitmapDispose($hImage)
                If Not $hIcon Then Return SetError(6, 0, 0)
            Case Else
                Return SetError(7, 0, 0)
        EndSwitch
        Return $hIcon
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>_GUICtrlMenu_CreateBitmap

Func _WinAPI_GetFileIcon($sFile, $iIndex = 0, $iW = 18, $iH = 18, $iColor = -1)
    Local $aRet, $hIcon, $hHBitmap
    Local $hDC, $hBackDC, $hBackSv

    $aRet = DllCall('shell32.dll', 'int', 'SHExtractIconsW', 'wstr', $sFile, 'int', $iIndex, 'int', $iW, 'int', $iH, 'ptr*', 0, 'ptr*', 0, 'int', 1, 'int', 0)
    If @error Then Return SetError(6, @extended, 0)
    $hIcon = $aRet[5]

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    If $iColor = -1 Then $iColor = _WinAPI_GetSysColor($COLOR_MENU)
    $hHBitmap = _WinAPI_CreateSolidBitmap(0, $iColor, $iW, $iH)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hHBitmap)
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, $iW, $iH)
    _WinAPI_DestroyIcon($hIcon)

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteDC($hBackDC)
    Return $hHBitmap
EndFunc   ;==>_GUICtrlMenu_CreateBitmap

 

ExampleIcon.png

Link to comment
Share on other sites

Does this help?

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <GUIMenu.au3>
#include <WinAPIShellEx.au3>
#include <WindowsConstants.au3>

_GDIPlus_Startup()
Global $cDummy
Global $hList, $hMenu

$hGUI = GUICreate("Disabled Menu Item Test", 500, 300)
$cDummy = GUICtrlCreateDummy()
$idList = GUICtrlCreateListView("Col1|Col2|Col3", 10, 10, 480, 280)
$hList = GUICtrlGetHandle(-1)
GUICtrlCreateListViewItem("Test1|Test2|Test3", $idList)

GUISetState(@SW_SHOW, $hGUI)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_Shutdown()
            ExitLoop
        Case $cDummy
            _ShowContext($idList)
    EndSwitch
WEnd

Func _ShowContext($hWnd)
    Local Enum $idTest1 = 1000, $idTest2
    Local $sIconPath = @ProgramFilesDir & "\AutoIt3\Icons\au3.ico"

    $hMenu = _GUICtrlMenu_CreatePopup()
    _GUICtrlMenu_AddMenuItem($hMenu, "Test1" & @TAB & "Ctrl+1", $idTest1)
    _GUICtrlMenu_SetIcon($hMenu, 0, $sIconPath)
    _GUICtrlMenu_AddMenuItem($hMenu, "Test2" & @TAB & "Ctrl+2", $idTest2)
    Local $bDisabled = 1
    If $bDisabled Then
        _GUICtrlMenu_SetIcon($hMenu, 1, $sIconPath, 0); <<<<<<< Any way to make this work with transparency?
        _GUICtrlMenu_SetItemDisabled($hMenu, 1)
    Else
        _GUICtrlMenu_SetIcon($hMenu, 1, $sIconPath)
    EndIf

    Local $idMsg = _GUICtrlMenu_TrackPopupMenu($hMenu, GUICtrlGetHandle($hWnd), -1, -1, 1, 1, 2)

    Switch $idMsg
        Case $idTest1
            ConsoleWrite(">> Test1" & @CRLF)
        Case $idTest2
            ConsoleWrite(">> Test2" & @CRLF)
    EndSwitch

    _GUICtrlMenu_DestroyMenu($hMenu)
EndFunc

Func _GUICtrlMenu_SetIcon($hWnd, $iIndex, $sIconPath, $iColor = -1)
    Local $hBMP_File_New = _GUICtrlMenu_CreateBitmap($sIconPath, 0, 16, 16, $iColor)
    Return _GUICtrlMenu_SetItemBmp($hWnd, $iIndex, $hBMP_File_New)
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam

    Local $iItem
    Local $tNMHDR =   DllStructCreate($tagNMHDR, $lParam)
    Local $HwndFrom = DllStructGetData($tNMHDR, "HwndFrom")
    Local $iCode =    DllStructGetData($tNMHDR, "Code")

    Switch $HwndFrom
        Case $hList
            Switch $iCode
                Case $NM_RCLICK
                    $iItem = DllStructGetData(DllStructCreate($tagNMITEMACTIVATE, $lParam), "Index")
                    If $iItem <> -1 Then GUICtrlSendToDummy($cDummy)
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc

; #FUNCTION# ============================================================================================================
; Name...................:  _GUICtrlMenu_CreateBitmap
; Description .......:      Extracts the icon from $sFile and converts it to a HBitmap format
; Syntax................:   _GUICtrlMenu_CreateBitmap($sFile, $iIndex = 0, $iX = 16, $iY = 16)
; Parameters ......:        $sFile      - file name where the icon should be extracted from or an image should be loaded (*.dll, *.ico, *.exe, *.jpg, *.png, *.bmp, *.gif, *.tif)
;                           $iIndex     - index of the icon from $sFile
;                           $iW         - set the width of the extracted icon
;                           $iH         - set the height of the extracted icon
;                           $iBgColor   - set background color from _WinAPI_GetSysColor($COLOR_MENU) if $iBgColor = -1
; Return values .:          Success     - handle to a HBITMAP
;                           Failure     - Returns 0 and sets error to 1-7
; Author ..............:    UEZ
; Version .............:    v0.71 Build 2018-08-17 beta
; Remarks ...........:      Don't forget to use _WinAPI_DeleteObject($<handle to the HBITMAP>) when closing to to release the resources
; =======================================================================================================================
Func _GUICtrlMenu_CreateBitmap($sFile, $iIndex = 0, $iW = 16, $iH = 16, $iBgColor = -1)
    Local $hIcon, $Ret, $hBitmap, $hContext, $bBinary = False
    Local $aChk = _GDIPlus_ImageGetFlags($sFile)
    If Not @error Then $bBinary = True
    If FileExists($sFile) Or $bBinary Then
        Local $sExt = StringMid($sFile, StringLen($sFile) - 3)
        If $bBinary Then $sExt = "0815"
        Switch $sExt
            Case ".dll", ".exe", ".ico"
                Return _WinAPI_GetFileIcon($sFile, $iIndex, $iW, $iH, $iBgColor)
            Case ".jpg", ".png", ".bmp", ".gif", ".tif", "0815"
                Local $hImage
                If Not $bBinary Then
                    $hImage = _GDIPlus_ImageLoadFromFile($sFile)
                    If @error Then Return SetError(4, @extended, 0)
                Else
                    $hImage = $sFile
                EndIf
                $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
                If @error Then Return SetError(5, @extended, 0)
                $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
                _GDIPlus_GraphicsSetInterpolationMode($hContext, $GDIP_INTERPOLATIONMODE_HIGHQUALITY)
                _GDIPlus_GraphicsDrawImageRect($hContext, $hImage, 0, 0, $iW, $iH)
                $hIcon =  _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
                _GDIPlus_GraphicsDispose($hContext)
                _GDIPlus_BitmapDispose($hBitmap)
                _GDIPlus_BitmapDispose($hImage)
                If Not $hIcon Then Return SetError(6, 0, 0)
            Case Else
                Return SetError(7, 0, 0)
        EndSwitch
        Return $hIcon
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>_GUICtrlMenu_CreateBitmap

Func _WinAPI_GetFileIcon($sFile, $iIndex, $iW, $iH, $iColor)
    Local $aRet, $hIcon, $hHBitmap
    Local $hDC, $hBackDC, $hBackSv

    $hIcon = _WinAPI_ShellExtractIcon($sFile, $iIndex, $iW, $iH)
    If @error Then Return SetError(6, @extended, 0)

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    If $iColor = -1 Then $iColor = _WinAPI_GetSysColor($COLOR_MENU)
    $hHBitmap = _WinAPI_CreateSolidBitmap(0, $iColor, $iW, $iH)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hHBitmap)
    _WinAPI_DrawIconEx($hBackDC, 0, 0, $hIcon, $iW, $iH)
    _WinAPI_DestroyIcon($hIcon)

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_DeleteDC($hBackDC)
    Return $hHBitmap
EndFunc   ;==>_GUICtrlMenu_CreateBitmap

 

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...