none
Translate RRS feed

  • Question

  • Good...
    Could someone please help me translate this code from Visual Basic 6.0 to C #

    Option Explicit
    
    Private fod As FileOpenDialog
    
    
    Private Sub Command1_Click()
    Set fod = New FileOpenDialog
    Dim isiRes As IShellItem
    Dim lPtr As Long
    Dim FileFilter() As COMDLG_FILTERSPEC
    ReDim FileFilter(0)
    
    FileFilter(0).pszName = "All Files"
    FileFilter(0).pszSpec = "*.*"
    
    With fod
        .SetTitle "Pick any file except EXE, BAT, COM"
        .SetOptions FOS_FILEMUSTEXIST Or FOS_DONTADDTORECENT
        .SetFileTypes 1, VarPtr(FileFilter(0).pszName)
        .Show Me.hWnd
        
        .GetResult isiRes
        isiRes.GetDisplayName SIGDN_FILESYSPATH, lPtr
        Text1.Text = BStrFromLPWStr(lPtr, True)
        
    End With
    Set isiRes = Nothing
    Set fod = Nothing
        
    End Sub
    
    Private Sub Command2_Click()
    Dim sFile As String
    Dim sExt As String
    Dim nIcoIdx As Long
    Dim MII() As MENUITEMINFO
    Dim miiZ As MENUITEMINFO
    
    Dim uRec() As AssocInfo
    Dim i As Long, j As Long, k As Long
    Dim ieah As IEnumAssocHandlers
    Dim iah As IAssocHandler
    Dim hr As Long
    Dim lPtr As Long
    Dim sApp As String
    Dim sIcon As String
    Dim hIcon As Long
    Dim hBmp As Long
    Dim PT As POINTAPI
    Dim idCmd As Long
    Dim hMenu As Long
    
    Const widBase As Long = 1000
    Const sCP As String = "Choose program..."
    
    j = -1
    ReDim MII(0)
    ReDim uRec(0)
    
    sFile = Text1.Text
    sExt = Right(sFile, Len(sFile) - InStrRev(sFile, ".") + 1)
    
    'First, we use an API call to get the object that will list the handlers
    'The other flag value will show all handlers- the recommended ones are the
    'ones that show up in Explorer's right click open-with menu
    
    hr = SHAssocEnumHandlers(StrPtr(sExt), ASSOC_FILTER_RECOMMENDED, ieah)
    If hr <> S_OK Then Exit Sub
    
    'now we're ready to start enumerating the handlers, in this project
    'we're going to load them into a popup menu
    hMenu = CreatePopupMenu()
    
    'Most IEnum______ classes work exactly like this. .Next fills the IAssocHandler iface
    Do While (ieah.Next(1, iah, 0) = 0)
        If (iah Is Nothing) = False Then
            j = j + 1
            ReDim Preserve MII(j)
            ReDim Preserve uRec(j) 'in case we need the info later
            
            Call iah.GetUIName(lPtr) 'can't receive a LPWSTR As String like sending it
            sApp = BStrFromLPWStr(lPtr)
            uRec(j).sUIName = sApp
            Call iah.GetName(lPtr)
            sApp = BStrFromLPWStr(lPtr)
            uRec(j).sPath = sApp
            Call iah.GetIconLocation(lPtr, i)
            sIcon = BStrFromLPWStr(lPtr)
            uRec(j).sIcon = sIcon
            uRec(j).nIcon = i
            
            'association interface includes icon info for our menu
            Call ExtractIconEx(sIcon, i, ByVal 0&, hIcon, 1)
            
            If pvIsAlphaIcon(hIcon) Then
                hBmp = HBitmapFromHIcon(hIcon, 16, 16) 'can't use hIcon directly
            Else
                hBmp = HBitmapFromHIconNoAlpha(hIcon)
            End If
            With MII(j)
                .cbSize = Len(MII(j))
                .fMask = MIIM_ID Or MIIM_STRING Or MIIM_BITMAP
                .wID = widBase + j
                .cch = Len(uRec(j).sUIName)
                .dwTypeData = uRec(j).sUIName
                .hbmpItem = hBmp
                
                Call InsertMenuItem(hMenu, j, True, MII(j))
                
            Call DestroyIcon(hIcon)
            End With
                  
        Else
            Debug.Print "iah=Nothing"
        End If
        Set iah = Nothing
    Loop
    
    'Add separator and open with other
    miiZ.cbSize = Len(miiZ)
    miiZ.fMask = MIIM_ID Or MIIM_TYPE
    miiZ.fType = MFT_SEPARATOR
    miiZ.wID = 9999
    Call InsertMenuItem(hMenu, -1, False, miiZ)
    
    miiZ.fMask = MIIM_ID Or MIIM_STRING
    miiZ.wID = 3000
    miiZ.cch = Len(sCP)
    miiZ.dwTypeData = sCP
    Call InsertMenuItem(hMenu, -1, False, miiZ)
    
    Call GetCursorPos(PT)
    PT.y = PT.y + 5
    
    idCmd = TrackPopupMenu(hMenu, TPM_LEFTBUTTON Or TPM_RIGHTBUTTON Or TPM_LEFTALIGN Or TPM_TOPALIGN Or TPM_HORIZONTAL Or TPM_RETURNCMD, PT.x, PT.y, 0, Me.hWnd, 0)
    
    Set ieah = Nothing
    
    If idCmd Then
        If idCmd = 3000 Then
            OpenWith Text1.Text, OAIF_ALLOW_REGISTRATION Or OAIF_EXEC, Me.hWnd
        Else
            
            k = idCmd - widBase
        '    MsgBox "Handler selected: " & uRec(k).sUIName & vbCrLf & _
        '            uRec(k).sPath & vbCrLf & _
        '            "Icon=" & uRec(k).sIcon & "," & uRec(k).nIcon, _
        '            vbOKOnly, App.Title
        '
            'i know.. pidl and ishellfolder stuff is confusing, but there's no other way
            Dim isf As IShellFolder
            Dim pidl As Long, pidlFQ As Long
            Dim zc As Long
            pidlFQ = PathToPidl(sFile)
            pidl = GetPIDLParent(pidlFQ)
            Set isf = GetIShellFolder(isfDesktop, pidl)
            Dim pidlChild As Long
            pidlChild = GetItemID(pidlFQ, GIID_LAST)
            
            'Now that we have the pidl and shellfolder representing our file, we create
            'an IDataObject for it, then re-enumerate the handlers- we still have the
            'selected one stored in k. it may be possible to just have an array to avoid
            'the reenumeration
            Dim ido As oleexp.IDataObject
            Call isf.GetUIObjectOf(0, 1, pidlChild, IID_IDataObject, 0, ido)
            Dim invk As IAssocHandlerInvoker
            hr = SHAssocEnumHandlers(StrPtr(sExt), ASSOC_FILTER_RECOMMENDED, ieah)
            Do While (ieah.Next(1, iah, 0) = 0)
                If (iah Is Nothing) = False Then
                    If zc = k Then
                        'theoretically, we could take the path to the executable and
                        'run a launch command, but the actual invoke interfacer is a
                        'far better choice
                        Call iah.CreateInvoker(ido, invk)
                        invk.Invoke
                        Exit Do
                    Else
                        zc = zc + 1
                    End If
                End If
                Set iah = Nothing
            Loop
        End If
    End If
       
    If pidlFQ Then CoTaskMemFree pidlFQ
    If pidl Then CoTaskMemFree pidl
    If pidlChild Then CoTaskMemFree pidlChild
    
    Set ido = Nothing
    Set isf = Nothing
    Set invk = Nothing
    Set iah = Nothing
    Set ieah = Nothing
    
    
        
    
    End Sub


    Option Explicit
    
    'Declares required for using association handlers in any context
    
    Public Enum ASSOC_FILTER
        ASSOC_FILTER_NONE = &H0
        ASSOC_FILTER_RECOMMENDED = &H1
    End Enum
    Public Type AssocInfo
        sUIName As String
        sPath As String
        sIcon As String
        nIcon As Long
    End Type
    Public Const S_OK = 0
    
    Public Declare Function SHAssocEnumHandlers Lib "shell32" (ByVal pszExtra As Long, ByVal afFilter As ASSOC_FILTER, ppEnumHandler As IEnumAssocHandlers) As Long
    Public Declare Function ExtractIconEx Lib "shell32.dll" Alias "ExtractIconExA" (ByVal lpszFile As String, _
                                                                                    ByVal nIconIndex As Long, _
                                                                                    phiconLarge As Long, _
                                                                                    phiconSmall As Long, _
                                                                                    ByVal nIcons As Long) As Long
    
    Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal pv As Long)
    Private Declare Function SysReAllocString Lib "oleaut32" (ByVal pBSTR As Long, ByVal lpWStr As Long) As Long
    
    
    
    
    Public Function BStrFromLPWStr(lpWStr As Long, Optional ByVal CleanupLPWStr As Boolean = True) As String
    SysReAllocString VarPtr(BStrFromLPWStr), lpWStr
    If CleanupLPWStr Then CoTaskMemFree lpWStr
    End Function
    
    


    Option Explicit
    'Public Type COMDLG_FILTERSPEC
    '    pszName As String
    '    pszSpec As String
    'End Type
    Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
    Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hDC As Long, pBitmapInfo As BITMAPINFO, ByVal un As Long, ByRef lplpVoid As Any, ByVal Handle As Long, ByVal dw As Long) As Long
    Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
    Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function DrawIconEx Lib "user32" (ByVal hDC As Long, ByVal XLeft As Long, ByVal YTop As Long, ByVal hIcon As Long, ByVal CXWidth As Long, ByVal CYWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
    Private Declare Function GetFullPathName Lib "kernel32" Alias "GetFullPathNameA" (ByVal lpFileName As String, ByVal nBufferLength As Long, ByVal lpBuffer As String, ByVal lpFilePart As String) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Public Declare Function GetIconInfo Lib "user32" (ByVal hIcon As Long, pIconInfo As ICONINFO) As Long
    Public Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Long) As Long
    Private Declare Sub FillMemory Lib "kernel32" Alias "RtlFillMemory" (pDest As Any, ByVal dwLength As Long, ByVal bFill As Byte)
    Private Declare Function SHGetMalloc Lib "shell32" (ppMalloc As IMalloc) As Long
    
    Public Const GIID_FIRST = 1
    Public Const GIID_LAST = -1
    
    Private Const DI_NORMAL = 3
    Private Const DIB_RGB_COLORS        As Long = 0&
    Public Type ICONINFO
        fIcon As Long
        XHotspot As Long
        YHotspot As Long
        hBMMask As Long
        hBMColor As Long
    End Type
    Private Type BITMAPINFOHEADER
       biSize                   As Long
       biWidth                  As Long
       biHeight                 As Long
       biPlanes                 As Integer
       biBitCount               As Integer
       biCompression            As Long
       biSizeImage              As Long
       biXPelsPerMeter          As Long
       biYPelsPerMeter          As Long
       biClrUsed                As Long
       biClrImportant           As Long
    End Type
    Private Type BITMAPINFO
       bmiHeader                As BITMAPINFOHEADER
       bmiColors(3)             As Byte
    End Type
    Public Declare Function CreatePopupMenu Lib "user32" () As Long
    Public Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" (ByVal hMenu As Long, ByVal uItem As Long, ByVal fByPosition As Boolean, lpmii As MENUITEMINFO) As Boolean
    
    Public Type MENUITEMINFO
      cbSize As Long
      fMask As MII_Mask
      fType As MF_Type              ' MIIM_TYPE
      fState As MF_State             ' MIIM_STATE
      wID As Long                       ' MIIM_ID
      hSubMenu As Long            ' MIIM_SUBMENU
      hbmpChecked As Long      ' MIIM_CHECKMARKS
      hbmpUnchecked As Long  ' MIIM_CHECKMARKS
      dwItemData As Long          ' MIIM_DATA
      dwTypeData As String        ' MIIM_TYPE
      cch As Long                       ' MIIM_TYPE
      hbmpItem As Long
      
    End Type
    
    Public Enum MII_Mask
      MIIM_STATE = &H1
      MIIM_ID = &H2
      MIIM_SUBMENU = &H4
      MIIM_CHECKMARKS = &H8
      MIIM_TYPE = &H10
      MIIM_DATA = &H20
      MIIM_BITMAP = &H80
      MIIM_STRING = &H40
    End Enum
    
    ' win40  -- A lot of MF_* flags have been renamed as MFT_* and MFS_* flags
    Public Enum MenuFlags
      MF_INSERT = &H0
      MF_ENABLED = &H0
      MF_UNCHECKED = &H0
      MF_BYCOMMAND = &H0
      MF_STRING = &H0
      MF_UNHILITE = &H0
      MF_GRAYED = &H1
      MF_DISABLED = &H2
      MF_BITMAP = &H4
      MF_CHECKED = &H8
      MF_POPUP = &H10
      MF_MENUBARBREAK = &H20
      MF_MENUBREAK = &H40
      MF_HILITE = &H80
      MF_CHANGE = &H80
      MF_END = &H80                    ' Obsolete -- only used by old RES files
      MF_APPEND = &H100
      MF_OWNERDRAW = &H100
      MF_DELETE = &H200
      MF_USECHECKBITMAPS = &H200
      MF_BYPOSITION = &H400
      MF_SEPARATOR = &H800
      MF_REMOVE = &H1000
      MF_DEFAULT = &H1000
      MF_SYSMENU = &H2000
      MF_HELP = &H4000
      MF_RIGHTJUSTIFY = &H4000
      MF_MOUSESELECT = &H8000&
    End Enum
    
    Public Enum MF_Type
      MFT_STRING = MF_STRING
      MFT_BITMAP = MF_BITMAP
      MFT_MENUBARBREAK = MF_MENUBARBREAK
      MFT_MENUBREAK = MF_MENUBREAK
      MFT_OWNERDRAW = MF_OWNERDRAW
      MFT_RADIOCHECK = &H200
      MFT_SEPARATOR = MF_SEPARATOR
      MFT_RIGHTORDER = &H2000
      MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY
    End Enum
    
    Public Enum MF_State
      MFS_GRAYED = &H3
      MFS_DISABLED = MFS_GRAYED
      MFS_CHECKED = MF_CHECKED
      MFS_HILITE = MF_HILITE
      MFS_ENABLED = MF_ENABLED
      MFS_UNCHECKED = MF_UNCHECKED
      MFS_UNHILITE = MF_UNHILITE
      MFS_DEFAULT = MF_DEFAULT
    End Enum
    Public Enum TPM_wFlags
      TPM_LEFTBUTTON = &H0
      TPM_RIGHTBUTTON = &H2
      TPM_LEFTALIGN = &H0
      TPM_CENTERALIGN = &H4
      TPM_RIGHTALIGN = &H8
      TPM_TOPALIGN = &H0
      TPM_VCENTERALIGN = &H10
      TPM_BOTTOMALIGN = &H20
    
      TPM_HORIZONTAL = &H0         ' Horz alignment matters more
      TPM_VERTICAL = &H40            ' Vert alignment matters more
      TPM_NONOTIFY = &H80           ' Don't send any notification msgs
      TPM_RETURNCMD = &H100
    End Enum
    Public Type POINTAPI
        x As Long
        y As Long
    End Type
    
    Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Public Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As Long, ByVal wFlags As TPM_wFlags, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hWnd As Long, lprc As Any) As Long
    Public Declare Function SHOpenWithDialog Lib "shell32" (ByVal hWnd As Long, poainfo As OPENASINFO) As Long
    Private Declare Function SHGetDesktopFolder Lib "shell32" (ppshf As IShellFolder) As Long ' Retrieves the IShellFolder interface for the desktop folder.
    
    Public Enum OPEN_AS_INFO_FLAGS
        OAIF_ALLOW_REGISTRATION = &H1 'Enable the "always use this program" checkbox. If not passed, it will be disabled.
        OAIF_REGISTER_EXT = &H2 'Do the registration after the user hits the OK button.
        OAIF_EXEC = &H4 'Execute file after registering.
        OAIF_FORCE_REGISTRATION = &H8 'Force the Always use this program checkbox to be checked. Typically, you won't use the OAIF_ALLOW_REGISTRATION flag when you pass this value.
        OAIF_HIDE_REGISTRATION = &H20 'Introduced in Windows Vista. Hide the Always use this program checkbox. If this flag is specified, the OAIF_ALLOW_REGISTRATION and OAIF_FORCE_REGISTRATION flags will be ignored.
        OAIF_URL_PROTOCOL = &H40 'Introduced in Windows Vista. The value for the extension that is passed is actually a protocol, so the Open With dialog box should show applications that are registered as capable of handling that protocol.
        OAIF_FILE_IS_URI = &H80 'Introduced in Windows 8. The location pointed to by the pcszFile parameter is given as a URI.
    End Enum
    
    Public Type OPENASINFO
        pcszFile As Long
        pcszClass As Long 'file type description for registering the type with 'always open', if not set uses extension, as in 'XYZ File'
        oafInFlags As OPEN_AS_INFO_FLAGS
    End Type
    
    Public gInitToken As Long
    Private Const PixelFormat32bppRGB   As Long = &H22009
    Private Type GdiplusStartupInput
        GdiplusVersion           As Long
        DebugEventCallback       As Long
        SuppressBackgroundThread As Long
        SuppressExternalCodecs   As Long
    End Type
    Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
    Private Type ARGB
        Blue            As Byte
        Green           As Byte
        Red             As Byte
        Alpha           As Byte
    End Type
    Private Type BitmapData
        Width           As Long
        Height          As Long
        Stride          As Long
        PixelFormat     As Long
        Scan0           As Long
        Reserved        As Long
    End Type
    Private Enum ImageLockMode
        ImageLockModeRead = &H1
        ImageLockModeWrite = &H2
        ImageLockModeUserInputBuf = &H4
    End Enum
    Private Declare Function GdiplusStartup Lib "GdiPlus.dll" (Token As Long, gdipInput As GdiplusStartupInput, GdiplusStartupOutput As Long) As Long
    Private Declare Sub GdiplusShutdown Lib "GdiPlus.dll" (ByVal Token As Long)
    Private Declare Function GdipCreateBitmapFromHBITMAP Lib "GdiPlus.dll" (ByVal hBmp As Long, ByVal hPal As Long, GpBitmap As Long) As Long
    Private Declare Function GdipCreateBitmapFromHICON Lib "GdiPlus.dll" (ByVal hIcon As Long, GpBitmap As Long) As Long
    Private Declare Function GdipGetImagePixelFormat Lib "GDIplus" (ByVal Image As Long, ByRef PixelFormat As Long) As Long
    Private Declare Function GdipGetImageDimension Lib "GDIplus" (ByVal Image As Long, ByRef Width As Single, ByRef Height As Single) As Long
    Private Declare Function GdipBitmapLockBits Lib "GDIplus" (ByVal BITMAP As Long, ByRef RECT As RECT, ByVal Flags As ImageLockMode, ByVal PixelFormat As Long, ByRef LockedBitmapData As BitmapData) As Long
    Private Declare Function GdipBitmapUnlockBits Lib "GDIplus" (ByVal BITMAP As Long, ByRef LockedBitmapData As BitmapData) As Long
    Private Declare Function GdipDisposeImage Lib "GdiPlus.dll" (ByVal Image As Long) As Long
    Private Declare Function GdipCreateHBITMAPFromBitmap Lib "GDIplus" ( _
        ByVal BITMAP As Long, _
        ByRef hbmReturn As Long, _
        ByVal background As Long) As Long
    
    
    Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    
    
    Public Sub InitGDIP()
        Static Token    As Long
        If Token = 0 Then
            Dim gdipInit As GdiplusStartupInput
            gdipInit.GdiplusVersion = 1
            GdiplusStartup Token, gdipInit, ByVal 0&
            gInitToken = Token
        End If
    End Sub
    Public Function HBitmapFromHIconNoAlpha(hIcon As Long) As Long
    Dim himg As Long
    Dim hb As Long
    GdipCreateBitmapFromHICON hIcon, himg
    GdipCreateHBITMAPFromBitmap himg, hb, &HFF000000
    GdipDisposeImage himg
    HBitmapFromHIconNoAlpha = hb
    End Function
    Public Function pvIsAlphaIcon(ByVal IconHandle As Long) As Boolean
    
    On Error GoTo e0
    
    Dim tARGB() As ARGB
    Dim tRECT As RECT
    Dim tICONINFO As ICONINFO
    Dim tBitmapData As BitmapData
    Dim lPixelFormat As Long
    Dim lngX As Long
    Dim lngY As Long
    Dim sngWidth As Single
    Dim sngHeight As Single
    Dim lngArgbBmp As Long
    Dim lngColorBmp As Long
    Dim bolRet As Boolean
    Dim hr As Long
        
    If gInitToken = 0 Then InitGDIP
           
    hr = GetIconInfo(IconHandle, tICONINFO)
    
    If hr <> 0 Then
    
        If tICONINFO.hBMColor <> 0 Then
    
            If GdipCreateBitmapFromHBITMAP(tICONINFO.hBMColor, 0&, lngColorBmp) = 0 Then
    
                If GdipGetImagePixelFormat(lngColorBmp, lPixelFormat) = 0 Then
    
                    If lPixelFormat <> PixelFormat32bppRGB Then
    
                        bolRet = False
    
                    Else
    
                        If GdipGetImageDimension(lngColorBmp, sngWidth, sngHeight) = 0 Then
    
                            With tRECT
                                .Right = CLng(sngWidth)
                                .Bottom = CLng(sngHeight)
                            End With
    
                            ReDim tARGB(tRECT.Right - 1&, tRECT.Bottom - 1&)
    
                            With tBitmapData
                                .Scan0 = VarPtr(tARGB(0&, 0&))
                                .Stride = 4& * tRECT.Right
                            End With
    
                            If GdipBitmapLockBits(lngColorBmp, tRECT, ImageLockModeRead Or ImageLockModeUserInputBuf, lPixelFormat, tBitmapData) = 0 Then
    
                                For lngY = 0 To tBitmapData.Height - 1
                                    For lngX = 0 To tBitmapData.Width - 1
    
                                        If tARGB(lngX, lngY).Alpha > 0 Then
                                            If tARGB(lngX, lngY).Alpha < 255 Then
    
                                                bolRet = True
                                                Exit For
    
                                            End If
                                        End If
    
                                    Next lngX
    
                                    If bolRet Then Exit For
    
                                Next lngY
    
                                Call GdipDisposeImage(lngArgbBmp)
    
                                Call GdipBitmapUnlockBits(lngColorBmp, tBitmapData)
    
                            End If
    
                        End If
    
                    End If
    
                End If
    
                Call GdipDisposeImage(lngColorBmp)
    
            End If
    
            Call DeleteObject(tICONINFO.hBMColor)
    
        End If
    
        Call DeleteObject(tICONINFO.hBMMask)
    
    Else
    
        bolRet = False
    
    End If
    
    pvIsAlphaIcon = bolRet
    On Error GoTo 0
    Exit Function
    
    e0:
    Debug.Print "pvIsAlphaIcon.Error->" & Err.Description & " (" & Err.Number & ")"
        
    End Function
    Public Sub ReleaseGDIP()
    GdiplusShutdown gInitToken
    End Sub
    
    Public Function PathToPidl(sPath As String) As Long
    
    Dim Folder As IShellFolder
    Dim pidlMain As Long
    Dim cParsed As Long
    Dim afItem As Long
    Dim lFilePos As Long
    Dim lR As Long
    Dim sRet As String
    
       ' Make sure the file name is fully qualified
       sRet = String$(MAX_PATH, 0)
       lR = GetFullPathName(sPath, MAX_PATH, sRet, lFilePos)
    
          ' debug.Assert c <= cMaxPath
          sPath = Left$(sRet, lR)
       
          ' Convert the path name into a pointer to an item ID list (pidl)
          Set Folder = isfDesktop
          ' Will raise an error if path cannpt be found:
          Dim sPathConv As String
          sPathConv = StrConv(sPath, vbUnicode)
          Call Folder.ParseDisplayName(0&, 0&, StrPtr(sPath), cParsed, pidlMain, afItem)
          'If S_OK >= (Folder.ParseDisplayName(0&, 0&, StrConv(sPath, vbUnicode), cParsed, pidlMain, afItem)) Then
             PathToPidl = pidlMain
          'End If
    
        
    End Function
    Public Function GetItemIDSize(ByVal pidl As Long) As Integer
      
      ' If we try to access memory at address 0 (NULL), then it's bye-bye...
      If pidl Then CopyMemory GetItemIDSize, ByVal pidl, 2
    
    End Function
    
    ' Returns the count of item IDs in a pidl.
    
    Public Function GetItemIDCount(ByVal pidl As Long) As Integer
      Dim nItems As Integer
      
      ' If the size of an item ID is 0, then it's the zero
      ' value terminating item ID at the end of the pidl.
      Do While GetItemIDSize(pidl)
        pidl = GetNextItemID(pidl)
        nItems = nItems + 1
      Loop
      
      GetItemIDCount = nItems
    
    End Function
    Public Function isMalloc() As IMalloc
      Static im As IMalloc
      If (im Is Nothing) Then Call SHGetMalloc(im)
      Set isMalloc = im
    End Function
    
    ' Returns a pointer to the next item ID in a pidl.
    ' Returns 0 if the next item ID is the pidl's zero value terminating 2 bytes.
    
    Public Function GetNextItemID(ByVal pidl As Long) As Long
      Dim cb As Integer   ' SHITEMID.cb, 2 bytes
      
      cb = GetItemIDSize(pidl)
      ' Make sure it's not the zero value terminator.
      If cb Then GetNextItemID = pidl + cb
    
    End Function
    
    ' If successful, returns the size in bytes of the memory occcupied by a pidl,
    ' including it's 2 byte zero terminator. Returns 0 otherwise.
    
    Public Function GetPIDLSize(ByVal pidl As Long) As Integer
      Dim cb As Integer
      ' Error handle in case we get a bad pidl and overflow cb.
      ' (most item IDs are roughly 20 bytes in size, and since an item ID represents
      ' a folder, a pidl can never exceed 260 folders, or 5200 bytes).
      On Error GoTo out
      
      If pidl Then
        Do While pidl
          cb = cb + GetItemIDSize(pidl)
          pidl = GetNextItemID(pidl)
        Loop
        ' Add 2 bytes for the zero terminating item ID
        GetPIDLSize = cb + 2
      End If
      
    out:
    End Function
    Public Function GetPIDLParent(pidl As Long, Optional fReturnDesktop As Boolean = False, Optional fFreeOldPidl As Boolean = False) As Long
      Dim nCount As Integer
      Dim pidl1 As Long
      Dim i As Integer
      Dim cb As Integer
      Dim pidlNew As Long
      
      nCount = GetItemIDCount(pidl)
      If (nCount = 0) And (fReturnDesktop = False) Then Exit Function
      
      ' Get the size of all but the pidl's last item ID and zero terminator.
      ' (maintain the value of the original pidl, it's passed ByRef !!)
      pidl1 = pidl
      For i = 1 To nCount - 1
        cb = cb + GetItemIDSize(pidl1)
        pidl1 = GetNextItemID(pidl1)
      Next
      
      ' Allocate a new item ID list with a new terminating 2 bytes.
      pidlNew = isMalloc.Alloc(cb + 2)
      
      ' If the memory was allocated...
      If pidlNew Then
        ' Copy all but the last item ID from the original pidl
        ' to the new pidl and zero the terminating 2 bytes.
        CopyMemory ByVal pidlNew, ByVal pidl, cb
        FillMemory ByVal pidlNew + cb, 2, 0
        
        If fFreeOldPidl Then Call CoTaskMemFree(pidl)
        GetPIDLParent = pidlNew
      
      End If
      
    End Function
    
    Public Function GetItemID(ByVal pidl As Long, ByVal nItem As Integer) As Long
      Dim nCount As Integer
      Dim i As Integer
      Dim cb As Integer
      Dim pidlNew As Long
      
      nCount = GetItemIDCount(pidl)
      If (nItem > nCount) Or (nItem = GIID_LAST) Then nItem = nCount
      
      ' GetNextItemID returns the 2nd item ID
      For i = 1 To nItem - 1: pidl = GetNextItemID(pidl): Next
        
      ' Get the size of the specified item identifier.
      ' If cb = 0 (the zero terminator), the we'll return a desktop pidl, proceed
      cb = GetItemIDSize(pidl)
      
      ' Allocate a new item identifier list.
      pidlNew = isMalloc.Alloc(cb + 2)
      If pidlNew Then
        
        ' Copy the specified item identifier.
        ' and append the zero terminator.
        CopyMemory ByVal pidlNew, ByVal pidl, cb
        CopyMemory ByVal pidlNew + cb, 0, 2
        
        GetItemID = pidlNew
      End If
      
    End Function
    Public Sub DEFINE_UUID(Name As UUID, l As Long, w1 As Integer, w2 As Integer, B0 As Byte, b1 As Byte, b2 As Byte, B3 As Byte, b4 As Byte, b5 As Byte, b6 As Byte, b7 As Byte)
      With Name
        .Data1 = l
        .Data2 = w1
        .Data3 = w2
        .Data4(0) = B0
        .Data4(1) = b1
        .Data4(2) = b2
        .Data4(3) = B3
        .Data4(4) = b4
        .Data4(5) = b5
        .Data4(6) = b6
        .Data4(7) = b7
      End With
    End Sub
    Public Sub DEFINE_OLEGUID(Name As UUID, l As Long, w1 As Integer, w2 As Integer)
      DEFINE_UUID Name, l, w1, w2, &HC0, 0, 0, 0, 0, 0, 0, &H46
    End Sub
    
    Public Function IID_IDataObject() As UUID
    '0000010e-0000-0000-C000-000000000046
    Static IID As UUID
     If (IID.Data1 = 0) Then Call DEFINE_UUID(IID, &H10E, CInt(&H0), CInt(&H0), &HC0, &H0, &H0, &H0, &H0, &H0, &H0, &H46)
      IID_IDataObject = IID
    
    End Function
    Public Function IID_IShellFolder() As UUID
      Static IID As UUID
      If (IID.Data1 = 0) Then Call DEFINE_OLEGUID(IID, &H214E6, 0, 0)
      IID_IShellFolder = IID
    End Function
    
    Public Function isfDesktop() As IShellFolder
      Static isf As IShellFolder
      If (isf Is Nothing) Then Call SHGetDesktopFolder(isf)
      Set isfDesktop = isf
    End Function
    Public Function GetIShellFolder(isfParent As IShellFolder, pidlRel As Long) As IShellFolder
      Dim isf As IShellFolder
      On Error GoTo out
    
      Call isfParent.BindToObject(pidlRel, 0, IID_IShellFolder, isf)
    
    out:
      If Err Or (isf Is Nothing) Then
        Set GetIShellFolder = isfDesktop
      Else
        Set GetIShellFolder = isf
      End If
    
    End Function
    
    Public Function OpenWith(sFile As String, lFlags As OPEN_AS_INFO_FLAGS, Optional hWndParent As Long, Optional sClass As String) As Long
    Dim oai As OPENASINFO
    oai.pcszFile = StrPtr(sFile)
    oai.oafInFlags = lFlags
    If sClass <> "" Then oai.pcszClass = StrPtr(sClass)
    OpenWith = SHOpenWithDialog(hWndParent, oai)
    End Function
    Public Function HBitmapFromHIcon(hIcon As Long, cx As Long, cy As Long) As Long
            Dim hDC As Long
            Dim hBackDC As Long
            Dim hBitmap As Long
            Dim hBackSV As Long
    
            hDC = GetDC(0)
            hBackDC = CreateCompatibleDC(hDC)
            hBitmap = Create32BitHBITMAP(hBackDC, cx, cy)
            
            hBackSV = SelectObject(hBackDC, hBitmap)
            DrawIconEx hBackDC, 0, 0, hIcon, cx, cy, 0, 0, DI_NORMAL
            
            Call SelectObject(hBackDC, hBackSV)
            Call ReleaseDC(0, hDC)
            Call DeleteDC(hBackDC)
    HBitmapFromHIcon = hBitmap
    End Function
    Public Function Create32BitHBITMAP(hDC As Long, cx As Long, cy As Long) As Long
    Dim bmi As BITMAPINFO
    Dim hdcUsed As Long
        bmi.bmiHeader.biSize = Len(bmi.bmiHeader)
        bmi.bmiHeader.biPlanes = 1
        bmi.bmiHeader.biCompression = 0
    
        bmi.bmiHeader.biWidth = cx
        bmi.bmiHeader.biHeight = cy
        bmi.bmiHeader.biBitCount = 32
        Create32BitHBITMAP = CreateDIBSection(hDC, bmi, DIB_RGB_COLORS, ByVal 0&, 0, 0)
        
    End Function
    
    
    

    I want to reach this result.

    First of all, Thanks.


    Thursday, August 8, 2019 5:00 AM

Answers

  • Test with "E:\test.jpg" file =>

    // Global for WM_INITMENUPOPUP
    IContextMenu2 pContextMenu2 = null;
    bool bOpenWith = true;
    // bool bOpenWith = false; // set bOpenWith = false for the standard Context Menu
    IntPtr hSubmenu = IntPtr.Zero;
    
    IntPtr pItemIDL = ILCreateFromPath("E:\\test.jpg");
    IntPtr pcm = IntPtr.Zero;
    Guid IID_IContextMenu = new Guid("000214E4-0000-0000-C000-000000000046");
    HRESULT hr = SHGetUIObjectFromFullPIDL(pItemIDL, IntPtr.Zero, ref IID_IContextMenu, ref pcm);
    if (hr == HRESULT.S_OK)
    {
        IContextMenu pContextMenu = Marshal.GetObjectForIUnknown(pcm) as IContextMenu;
        IntPtr hMenu = CreatePopupMenu();
        hr = pContextMenu.QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_EXPLORE);
        if (hr == HRESULT.S_OK)
        {
            pContextMenu2 = (IContextMenu2)pContextMenu;
            if (bOpenWith)
            {
                int nNbItems = GetMenuItemCount(hMenu);
                for (int i = nNbItems - 1; i >= 0; i--)
                {
                    MENUITEMINFO mii = new MENUITEMINFO();
                    mii.cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO));
                    mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA;
                    if (GetMenuItemInfo(hMenu, i, true, ref mii))
                    {
                        if (mii.hSubMenu != IntPtr.Zero)
                        {
                            StringBuilder sbVerb = new StringBuilder(260);
                            hr = pContextMenu2.GetCommandString(mii.wID - 1, GCS_VERBW, IntPtr.Zero, sbVerb, (uint)sbVerb.Capacity);
                            if (sbVerb.ToString() == "openas")
                            {
                                hSubmenu = mii.hSubMenu;
                                break;                                          
                            }
                        }
                    }
                }
            }
            else
                hSubmenu = hMenu;
    
            int nX = Cursor.Position.X, nY = Cursor.Position.Y;
            uint nCmd = TrackPopupMenu(hSubmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, nX, nY, 0, this.Handle, IntPtr.Zero);
            if (nCmd != 0)
            {
                CMINVOKECOMMANDINFO cmi = new CMINVOKECOMMANDINFO();
                cmi.cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO));
                cmi.fMask = 0;
                cmi.hwnd = this.Handle;
                cmi.lpVerb = (IntPtr)(nCmd - 1);
                cmi.lpParameters = IntPtr.Zero;
                cmi.lpDirectory = IntPtr.Zero;
                cmi.nShow = SW_SHOWNORMAL;
                cmi.dwHotKey = 0;
                cmi.hIcon = IntPtr.Zero; ;
                hr = pContextMenu.InvokeCommand(ref cmi);
            }
            pContextMenu2 = null;                       
        }                   
        Marshal.ReleaseComObject(pContextMenu);
        DestroyMenu(hMenu);
    }
    ILFree(pItemIDL);
    
    
    // From MSDN : https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shbrowseforfolderw
    private HRESULT SHGetUIObjectFromFullPIDL(IntPtr pidl, IntPtr hwnd, ref Guid riid, ref IntPtr ppv)
    {
        IntPtr pidlChild = IntPtr.Zero;
        IShellFolder psf = null;
        ppv = IntPtr.Zero;
        Guid IID_IShellFolder = new Guid("000214E6-0000-0000-C000-000000000046");
        HRESULT hr = SHBindToParent(pidl, ref IID_IShellFolder, ref psf, ref pidlChild);
        if (hr == HRESULT.S_OK)
        {
            uint rgfReserved = 0;
            hr = psf.GetUIObjectOf(hwnd, 1, ref pidlChild, riid, ref rgfReserved, out ppv);
            Marshal.ReleaseComObject(psf);
        }        
        return hr;
    }
    
    public const int WM_INITMENUPOPUP = 0x0117;
    
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_INITMENUPOPUP)
        {
            if (pContextMenu2 != null)
                pContextMenu2.HandleMenuMsg((uint)m.Msg, (int)m.WParam, m.LParam);
    
            return;
        }
        else
            base.WndProc(ref m);
    }

    Declarations :

            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
            }   
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHBindToParent(IntPtr pidl, ref Guid riid, ref IShellFolder ppv, ref IntPtr ppidlLast);
    
            [
                ComImport,
                InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
                Guid("000214E6-0000-0000-C000-000000000046") 
            ]
            public interface IShellFolder
            {
                HRESULT ParseDisplayName(IntPtr hwnd,
                    // IBindCtx pbc,
                    IntPtr pbc,
                    [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                HRESULT BindToObject(IntPtr pidl,
                    //IBindCtx pbc,
                    IntPtr pbc,
                    [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                //HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                //    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, ref IntPtr apidl, [In] ref Guid riid, [In, Out] ref uint rgfReserved, out IntPtr ppv);
                HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
            }
    
            [Flags]
            public enum SHCONTF : ushort
            {
                SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
                SHCONTF_FOLDERS = 0x0020,
                SHCONTF_NONFOLDERS = 0x0040,
                SHCONTF_INCLUDEHIDDEN = 0x0080,
                SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
                SHCONTF_NETPRINTERSRCH = 0x0200,
                SHCONTF_SHAREABLE = 0x0400,
                SHCONTF_STORAGE = 0x0800,
                SHCONTF_NAVIGATION_ENUM = 0x1000,
                SHCONTF_FASTITEMS = 0x2000,
                SHCONTF_FLATLIST = 0x4000,
                SHCONTF_ENABLE_ASYNC = 0x8000
            }
    
            [Flags]
            public enum SFGAO : uint
            {
                CANCOPY = 0x00000001,
                CANMOVE = 0x00000002,
                CANLINK = 0x00000004,
                STORAGE = 0x00000008,
                CANRENAME = 0x00000010,
                CANDELETE = 0x00000020,
                HASPROPSHEET = 0x00000040,
                DROPTARGET = 0x00000100,
                CAPABILITYMASK = 0x00000177,
                ENCRYPTED = 0x00002000,
                ISSLOW = 0x00004000,
                GHOSTED = 0x00008000,
                LINK = 0x00010000,
                SHARE = 0x00020000,
                READONLY = 0x00040000,
                HIDDEN = 0x00080000,
                DISPLAYATTRMASK = 0x000FC000,
                STREAM = 0x00400000,
                STORAGEANCESTOR = 0x00800000,
                VALIDATE = 0x01000000,
                REMOVABLE = 0x02000000,
                COMPRESSED = 0x04000000,
                BROWSABLE = 0x08000000,
                FILESYSANCESTOR = 0x10000000,
                FOLDER = 0x20000000,
                FILESYSTEM = 0x40000000,
                HASSUBFOLDER = 0x80000000,
                CONTENTSMASK = 0x80000000,
                STORAGECAPMASK = 0x70C50008,
                PKEYSFGAOMASK = 0x81044000
            }
    
            public enum SHGDNF
            {
                SHGDN_NORMAL = 0,
                SHGDN_INFOLDER = 0x1,
                SHGDN_FOREDITING = 0x1000,
                SHGDN_FORADDRESSBAR = 0x4000,
                SHGDN_FORPARSING = 0x8000
            }
    
            [StructLayout(LayoutKind.Explicit, Size = 264)]
            public struct STRRET
            {
                [FieldOffset(0)]
                //One of the STRRET_* values
                public uint uType;
                [FieldOffset(4)]
                //must be freed by caller of GetDisplayNameOf
                public IntPtr pOleStr;
                //  <FieldOffset(4)> Public pStr As IntPtr      'NOT USED
                [FieldOffset(4)]
                //Offset into SHITEMID
                public uint uOffset;
                [FieldOffset(4)]
                //Buffer to fill in (ANSI)
                public IntPtr cString;
            }
    
            [
                ComImport,
                InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
                Guid("000214F2-0000-0000-C000-000000000046")
            ]
            public interface IEnumIDList
            {
                [PreserveSig()]
                HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
                [PreserveSig()]
                HRESULT Skip(uint celt);
                void Reset();
                [return: MarshalAs(UnmanagedType.Interface)]
                IEnumIDList Clone();
            }   
    
            [ComImport]
            [Guid("000214e4-0000-0000-c000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IContextMenu
            {
                HRESULT QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
                [PreserveSig()]
                HRESULT InvokeCommand(ref CMINVOKECOMMANDINFO pici);            
    
                [PreserveSig()]
                HRESULT GetCommandString(uint idCmd, uint uType, IntPtr pReserved, StringBuilder pszName, uint cchMax);
            }
    
            [ComImport]
            [Guid("000214f4-0000-0000-c000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IContextMenu2: IContextMenu
            {
                new HRESULT QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
                [PreserveSig()]
                new HRESULT InvokeCommand(ref CMINVOKECOMMANDINFO pici);
    
                [PreserveSig()]
                new HRESULT GetCommandString(uint idCmd, uint uType, IntPtr pReserved, StringBuilder pszName, uint cchMax);
    
                [PreserveSig()]
                HRESULT HandleMenuMsg(uint uMsg, int wParam, IntPtr lParam);
            }
    
            public const int SW_SHOWNORMAL = 1;
    
            public const int GCS_VERBA = 0x00000000;     // canonical verb
            public const int GCS_HELPTEXTA = 0x00000001;     // help text (for status bar)
            public const int GCS_VALIDATEA = 0x00000002;     // validate command exists
            public const int GCS_VERBW = 0x00000004;     // canonical verb (unicode)
            public const int GCS_HELPTEXTW = 0x00000005;     // help text (unicode version)
            public const int GCS_VALIDATEW = 0x00000006;     // validate command exists (unicode)
            public const int GCS_VERBICONW = 0x00000014;     // icon string (unicode)
            public const int GCS_UNICODE = 0x00000004;     // for bit testing - Unicode string
    
    
            public const int CMF_NORMAL = 0x00000000;
            public const int CMF_DEFAULTONLY = 0x00000001;
            public const int CMF_VERBSONLY = 0x00000002;
            public const int CMF_EXPLORE = 0x00000004;
            public const int CMF_NOVERBS = 0x00000008;
            public const int CMF_CANRENAME = 0x00000010;
            public const int CMF_NODEFAULT = 0x00000020;
            public const int CMF_INCLUDESTATIC = 0x00000040;
            public const int CMF_ITEMMENU = 0x00000080;
            public const int CMF_EXTENDEDVERBS = 0x00000100;
            public const int CMF_DISABLEDVERBS = 0x00000200;
            public const int CMF_ASYNCVERBSTATE = 0x00000400;
            public const int CMF_OPTIMIZEFORINVOKE = 0x00000800;
            public const int CMF_SYNCCASCADEMENU = 0x00001000;
            public const int CMF_DONOTPICKDEFAULT = 0x00002000;
            public const int CMF_RESERVED = unchecked((int)0xffff0000);
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct CMINVOKECOMMANDINFO
            {
                public int  cbSize;
                public int fMask;
                public IntPtr hwnd;
                public IntPtr lpVerb;
                public IntPtr lpParameters;
                public IntPtr lpDirectory;
                public int nShow;
                public int dwHotKey;
                public IntPtr hIcon;
            }
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern IntPtr CreatePopupMenu();
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int GetMenuItemCount(IntPtr hMenu);
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool DestroyMenu(IntPtr hMenu);
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern uint TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect);
    
            public const int TPM_LEFTBUTTON = 0x0000;
            public const int TPM_RIGHTBUTTON = 0x0002;
            public const int TPM_LEFTALIGN = 0x0000;
            public const int TPM_CENTERALIGN = 0x0004;
            public const int TPM_RIGHTALIGN = 0x0008;
            public const int TPM_TOPALIGN = 0x0000;
            public const int TPM_VCENTERALIGN = 0x0010;
            public const int TPM_BOTTOMALIGN = 0x0020;
            public const int TPM_HORIZONTAL = 0x0000;     /* Horz alignment matters more */
            public const int TPM_VERTICAL = 0x0040;     /* Vert alignment matters more */
            public const int TPM_NONOTIFY = 0x0080;     /* Don't send any notification msgs */
            public const int TPM_RETURNCMD = 0x0100;
            public const int TPM_RECURSE = 0x0001;
            public const int TPM_HORPOSANIMATION = 0x0400;
            public const int TPM_HORNEGANIMATION = 0x0800;
            public const int TPM_VERPOSANIMATION = 0x1000;
            public const int TPM_VERNEGANIMATION = 0x2000;
            public const int TPM_NOANIMATION = 0x4000;
            public const int TPM_LAYOUTRTL = 0x8000;
            public const int TPM_WORKAREA = 0x10000;
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool GetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, [In, Out] ref MENUITEMINFO lpmii);
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct MENUITEMINFO
            {
                public uint cbSize;
                public uint fMask;
                public uint fType;         // used if MIIM_TYPE (4.0) or MIIM_FTYPE (>4.0)
                public uint fState;        // used if MIIM_STATE
                public uint wID;           // used if MIIM_ID
                public IntPtr hSubMenu;      // used if MIIM_SUBMENU
                public IntPtr hbmpChecked;   // used if MIIM_CHECKMARKS
                public IntPtr hbmpUnchecked; // used if MIIM_CHECKMARKS
                public IntPtr dwItemData;   // used if MIIM_DATA
                [MarshalAs(UnmanagedType.LPWStr)]
                string dwTypeData;    // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0)
                public uint cch;           // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0)
                public IntPtr hbmpItem;      // used if MIIM_BITMAP
            }
    
            public const int MIIM_STATE = 0x00000001;
            public const int MIIM_ID = 0x00000002;
            public const int MIIM_SUBMENU = 0x00000004;
            public const int MIIM_CHECKMARKS = 0x00000008;
            public const int MIIM_TYPE = 0x00000010;
            public const int MIIM_DATA = 0x00000020;
    
            public const int MIIM_STRING = 0x00000040;
            public const int MIIM_BITMAP = 0x00000080;
            public const int MIIM_FTYPE = 0x00000100;
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, StringBuilder lpString, int cchMax, uint flags);
    
            public const int MF_BYCOMMAND = 0x00000000;
            public const int MF_BYPOSITION = 0x00000400;
    
            //[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            //public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern IntPtr ILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath);
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern void ILFree(IntPtr pidl);
    

    • Marked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Unmarked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Marked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Unmarked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Marked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    Wednesday, August 21, 2019 8:14 AM

All replies

  • Hi JenCarlos,

    Thank you for posting here.

    Since this thread is related to Visual Basic 6.0, we do not support it. Therefore, I suggest that you could post it in the following forum.

    http://www.vbforums.com/forumdisplay.php?1-Visual-Basic-6-and-Earlier

    The Visual C# forum discusses and asks questions about the C# programming language, IDE, libraries, samples, and tools.

    Note:This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Best Regards.

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, August 8, 2019 7:15 AM
  • It's too long to do it manually by just looking at the code. My suggestion is that you do the translation in two steps: Convert from vb6 to vb.net, and the convert from vb.net to C#.

    For the first one, you can open the vb6 project in Visual Studio, and it will offer to convert it for you. At least, old versions of Visual Studio did; I don't know if this feature has been deprecated in newer versions. Once converted, you will need to "polish" it manually. Specifically, it's probable that you will need to convert the external declarations because some types don't match between vb6 and vb.net. For instance, the Longs have to be changed into Ints. This is something that you would have needed to do anyway if you were converting directly to C#.

    Once your program works in vb.net, then you convert it to C#. There are several public translators around the 'net. Just search for "convert vb to c#" and you will find several. You copy and paste your vb.net code and the application gives you back the C# code. In most cases this works as-is, without any manual adjustments, so you would then have your converted code.

    Thursday, August 8, 2019 8:00 AM
  • This is a lot of work so you will need to offer money for this. Also you need to find someone who are both good in C# and VB  :)
    • Edited by ThisNewbie Friday, August 9, 2019 6:42 AM
    Friday, August 9, 2019 6:34 AM
  • This code rebuilds the "Open With" submenu, but it is not needed.

    You can display this submenu with IContextMenu2 and "openas" (HandleMenuMsg in WM_INITMENUPOPUP to build the menu automatically)

    Quickly tested on Windows 10, I could post a sample if you cannot do it :

    (french "Open With" menu on a .jpg file) =>

    The main interfaces I converted from C++ for my test =>

            [ComImport]
            [Guid("000214e4-0000-0000-c000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IContextMenu
            {
                HRESULT QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
                [PreserveSig()]           
                HRESULT InvokeCommand(ref CMINVOKECOMMANDINFO pici);            
    
                [PreserveSig()]
                HRESULT GetCommandString(uint idCmd, uint uType, IntPtr pReserved, StringBuilder pszName, uint cchMax);
            }
    
            [ComImport]
            [Guid("000214f4-0000-0000-c000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IContextMenu2: IContextMenu
            {
                new HRESULT QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
                [PreserveSig()]
                new HRESULT InvokeCommand(ref CMINVOKECOMMANDINFO pici);
    
                [PreserveSig()]
                new HRESULT GetCommandString(uint idCmd, uint uType, IntPtr pReserved, StringBuilder pszName, uint cchMax);
    
                [PreserveSig()]
                HRESULT HandleMenuMsg(uint uMsg, int wParam, IntPtr lParam);
            }
            
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct CMINVOKECOMMANDINFO
            {
                public int  cbSize;
                public int fMask;
                public IntPtr hwnd;
                public IntPtr lpVerb;
                public IntPtr lpParameters;
                public IntPtr lpDirectory;
                int nShow;
                public int dwHotKey;
                public IntPtr hIcon;
            }
            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
            }



    • Edited by Castorix31 Sunday, August 11, 2019 9:12 AM
    Friday, August 9, 2019 8:07 PM
  • Can you please pass me the complete code?
    Castorix31
    • Edited by JenCarlos Wednesday, August 21, 2019 12:18 AM
    Wednesday, August 21, 2019 12:16 AM
  • Test with "E:\test.jpg" file =>

    // Global for WM_INITMENUPOPUP
    IContextMenu2 pContextMenu2 = null;
    bool bOpenWith = true;
    // bool bOpenWith = false; // set bOpenWith = false for the standard Context Menu
    IntPtr hSubmenu = IntPtr.Zero;
    
    IntPtr pItemIDL = ILCreateFromPath("E:\\test.jpg");
    IntPtr pcm = IntPtr.Zero;
    Guid IID_IContextMenu = new Guid("000214E4-0000-0000-C000-000000000046");
    HRESULT hr = SHGetUIObjectFromFullPIDL(pItemIDL, IntPtr.Zero, ref IID_IContextMenu, ref pcm);
    if (hr == HRESULT.S_OK)
    {
        IContextMenu pContextMenu = Marshal.GetObjectForIUnknown(pcm) as IContextMenu;
        IntPtr hMenu = CreatePopupMenu();
        hr = pContextMenu.QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_EXPLORE);
        if (hr == HRESULT.S_OK)
        {
            pContextMenu2 = (IContextMenu2)pContextMenu;
            if (bOpenWith)
            {
                int nNbItems = GetMenuItemCount(hMenu);
                for (int i = nNbItems - 1; i >= 0; i--)
                {
                    MENUITEMINFO mii = new MENUITEMINFO();
                    mii.cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO));
                    mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA;
                    if (GetMenuItemInfo(hMenu, i, true, ref mii))
                    {
                        if (mii.hSubMenu != IntPtr.Zero)
                        {
                            StringBuilder sbVerb = new StringBuilder(260);
                            hr = pContextMenu2.GetCommandString(mii.wID - 1, GCS_VERBW, IntPtr.Zero, sbVerb, (uint)sbVerb.Capacity);
                            if (sbVerb.ToString() == "openas")
                            {
                                hSubmenu = mii.hSubMenu;
                                break;                                          
                            }
                        }
                    }
                }
            }
            else
                hSubmenu = hMenu;
    
            int nX = Cursor.Position.X, nY = Cursor.Position.Y;
            uint nCmd = TrackPopupMenu(hSubmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, nX, nY, 0, this.Handle, IntPtr.Zero);
            if (nCmd != 0)
            {
                CMINVOKECOMMANDINFO cmi = new CMINVOKECOMMANDINFO();
                cmi.cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO));
                cmi.fMask = 0;
                cmi.hwnd = this.Handle;
                cmi.lpVerb = (IntPtr)(nCmd - 1);
                cmi.lpParameters = IntPtr.Zero;
                cmi.lpDirectory = IntPtr.Zero;
                cmi.nShow = SW_SHOWNORMAL;
                cmi.dwHotKey = 0;
                cmi.hIcon = IntPtr.Zero; ;
                hr = pContextMenu.InvokeCommand(ref cmi);
            }
            pContextMenu2 = null;                       
        }                   
        Marshal.ReleaseComObject(pContextMenu);
        DestroyMenu(hMenu);
    }
    ILFree(pItemIDL);
    
    
    // From MSDN : https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shbrowseforfolderw
    private HRESULT SHGetUIObjectFromFullPIDL(IntPtr pidl, IntPtr hwnd, ref Guid riid, ref IntPtr ppv)
    {
        IntPtr pidlChild = IntPtr.Zero;
        IShellFolder psf = null;
        ppv = IntPtr.Zero;
        Guid IID_IShellFolder = new Guid("000214E6-0000-0000-C000-000000000046");
        HRESULT hr = SHBindToParent(pidl, ref IID_IShellFolder, ref psf, ref pidlChild);
        if (hr == HRESULT.S_OK)
        {
            uint rgfReserved = 0;
            hr = psf.GetUIObjectOf(hwnd, 1, ref pidlChild, riid, ref rgfReserved, out ppv);
            Marshal.ReleaseComObject(psf);
        }        
        return hr;
    }
    
    public const int WM_INITMENUPOPUP = 0x0117;
    
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_INITMENUPOPUP)
        {
            if (pContextMenu2 != null)
                pContextMenu2.HandleMenuMsg((uint)m.Msg, (int)m.WParam, m.LParam);
    
            return;
        }
        else
            base.WndProc(ref m);
    }

    Declarations :

            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
            }   
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHBindToParent(IntPtr pidl, ref Guid riid, ref IShellFolder ppv, ref IntPtr ppidlLast);
    
            [
                ComImport,
                InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
                Guid("000214E6-0000-0000-C000-000000000046") 
            ]
            public interface IShellFolder
            {
                HRESULT ParseDisplayName(IntPtr hwnd,
                    // IBindCtx pbc,
                    IntPtr pbc,
                    [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                HRESULT BindToObject(IntPtr pidl,
                    //IBindCtx pbc,
                    IntPtr pbc,
                    [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                //HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                //    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, ref IntPtr apidl, [In] ref Guid riid, [In, Out] ref uint rgfReserved, out IntPtr ppv);
                HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
            }
    
            [Flags]
            public enum SHCONTF : ushort
            {
                SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
                SHCONTF_FOLDERS = 0x0020,
                SHCONTF_NONFOLDERS = 0x0040,
                SHCONTF_INCLUDEHIDDEN = 0x0080,
                SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
                SHCONTF_NETPRINTERSRCH = 0x0200,
                SHCONTF_SHAREABLE = 0x0400,
                SHCONTF_STORAGE = 0x0800,
                SHCONTF_NAVIGATION_ENUM = 0x1000,
                SHCONTF_FASTITEMS = 0x2000,
                SHCONTF_FLATLIST = 0x4000,
                SHCONTF_ENABLE_ASYNC = 0x8000
            }
    
            [Flags]
            public enum SFGAO : uint
            {
                CANCOPY = 0x00000001,
                CANMOVE = 0x00000002,
                CANLINK = 0x00000004,
                STORAGE = 0x00000008,
                CANRENAME = 0x00000010,
                CANDELETE = 0x00000020,
                HASPROPSHEET = 0x00000040,
                DROPTARGET = 0x00000100,
                CAPABILITYMASK = 0x00000177,
                ENCRYPTED = 0x00002000,
                ISSLOW = 0x00004000,
                GHOSTED = 0x00008000,
                LINK = 0x00010000,
                SHARE = 0x00020000,
                READONLY = 0x00040000,
                HIDDEN = 0x00080000,
                DISPLAYATTRMASK = 0x000FC000,
                STREAM = 0x00400000,
                STORAGEANCESTOR = 0x00800000,
                VALIDATE = 0x01000000,
                REMOVABLE = 0x02000000,
                COMPRESSED = 0x04000000,
                BROWSABLE = 0x08000000,
                FILESYSANCESTOR = 0x10000000,
                FOLDER = 0x20000000,
                FILESYSTEM = 0x40000000,
                HASSUBFOLDER = 0x80000000,
                CONTENTSMASK = 0x80000000,
                STORAGECAPMASK = 0x70C50008,
                PKEYSFGAOMASK = 0x81044000
            }
    
            public enum SHGDNF
            {
                SHGDN_NORMAL = 0,
                SHGDN_INFOLDER = 0x1,
                SHGDN_FOREDITING = 0x1000,
                SHGDN_FORADDRESSBAR = 0x4000,
                SHGDN_FORPARSING = 0x8000
            }
    
            [StructLayout(LayoutKind.Explicit, Size = 264)]
            public struct STRRET
            {
                [FieldOffset(0)]
                //One of the STRRET_* values
                public uint uType;
                [FieldOffset(4)]
                //must be freed by caller of GetDisplayNameOf
                public IntPtr pOleStr;
                //  <FieldOffset(4)> Public pStr As IntPtr      'NOT USED
                [FieldOffset(4)]
                //Offset into SHITEMID
                public uint uOffset;
                [FieldOffset(4)]
                //Buffer to fill in (ANSI)
                public IntPtr cString;
            }
    
            [
                ComImport,
                InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
                Guid("000214F2-0000-0000-C000-000000000046")
            ]
            public interface IEnumIDList
            {
                [PreserveSig()]
                HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
                [PreserveSig()]
                HRESULT Skip(uint celt);
                void Reset();
                [return: MarshalAs(UnmanagedType.Interface)]
                IEnumIDList Clone();
            }   
    
            [ComImport]
            [Guid("000214e4-0000-0000-c000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IContextMenu
            {
                HRESULT QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
                [PreserveSig()]
                HRESULT InvokeCommand(ref CMINVOKECOMMANDINFO pici);            
    
                [PreserveSig()]
                HRESULT GetCommandString(uint idCmd, uint uType, IntPtr pReserved, StringBuilder pszName, uint cchMax);
            }
    
            [ComImport]
            [Guid("000214f4-0000-0000-c000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IContextMenu2: IContextMenu
            {
                new HRESULT QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
                [PreserveSig()]
                new HRESULT InvokeCommand(ref CMINVOKECOMMANDINFO pici);
    
                [PreserveSig()]
                new HRESULT GetCommandString(uint idCmd, uint uType, IntPtr pReserved, StringBuilder pszName, uint cchMax);
    
                [PreserveSig()]
                HRESULT HandleMenuMsg(uint uMsg, int wParam, IntPtr lParam);
            }
    
            public const int SW_SHOWNORMAL = 1;
    
            public const int GCS_VERBA = 0x00000000;     // canonical verb
            public const int GCS_HELPTEXTA = 0x00000001;     // help text (for status bar)
            public const int GCS_VALIDATEA = 0x00000002;     // validate command exists
            public const int GCS_VERBW = 0x00000004;     // canonical verb (unicode)
            public const int GCS_HELPTEXTW = 0x00000005;     // help text (unicode version)
            public const int GCS_VALIDATEW = 0x00000006;     // validate command exists (unicode)
            public const int GCS_VERBICONW = 0x00000014;     // icon string (unicode)
            public const int GCS_UNICODE = 0x00000004;     // for bit testing - Unicode string
    
    
            public const int CMF_NORMAL = 0x00000000;
            public const int CMF_DEFAULTONLY = 0x00000001;
            public const int CMF_VERBSONLY = 0x00000002;
            public const int CMF_EXPLORE = 0x00000004;
            public const int CMF_NOVERBS = 0x00000008;
            public const int CMF_CANRENAME = 0x00000010;
            public const int CMF_NODEFAULT = 0x00000020;
            public const int CMF_INCLUDESTATIC = 0x00000040;
            public const int CMF_ITEMMENU = 0x00000080;
            public const int CMF_EXTENDEDVERBS = 0x00000100;
            public const int CMF_DISABLEDVERBS = 0x00000200;
            public const int CMF_ASYNCVERBSTATE = 0x00000400;
            public const int CMF_OPTIMIZEFORINVOKE = 0x00000800;
            public const int CMF_SYNCCASCADEMENU = 0x00001000;
            public const int CMF_DONOTPICKDEFAULT = 0x00002000;
            public const int CMF_RESERVED = unchecked((int)0xffff0000);
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct CMINVOKECOMMANDINFO
            {
                public int  cbSize;
                public int fMask;
                public IntPtr hwnd;
                public IntPtr lpVerb;
                public IntPtr lpParameters;
                public IntPtr lpDirectory;
                public int nShow;
                public int dwHotKey;
                public IntPtr hIcon;
            }
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern IntPtr CreatePopupMenu();
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int GetMenuItemCount(IntPtr hMenu);
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool DestroyMenu(IntPtr hMenu);
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern uint TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect);
    
            public const int TPM_LEFTBUTTON = 0x0000;
            public const int TPM_RIGHTBUTTON = 0x0002;
            public const int TPM_LEFTALIGN = 0x0000;
            public const int TPM_CENTERALIGN = 0x0004;
            public const int TPM_RIGHTALIGN = 0x0008;
            public const int TPM_TOPALIGN = 0x0000;
            public const int TPM_VCENTERALIGN = 0x0010;
            public const int TPM_BOTTOMALIGN = 0x0020;
            public const int TPM_HORIZONTAL = 0x0000;     /* Horz alignment matters more */
            public const int TPM_VERTICAL = 0x0040;     /* Vert alignment matters more */
            public const int TPM_NONOTIFY = 0x0080;     /* Don't send any notification msgs */
            public const int TPM_RETURNCMD = 0x0100;
            public const int TPM_RECURSE = 0x0001;
            public const int TPM_HORPOSANIMATION = 0x0400;
            public const int TPM_HORNEGANIMATION = 0x0800;
            public const int TPM_VERPOSANIMATION = 0x1000;
            public const int TPM_VERNEGANIMATION = 0x2000;
            public const int TPM_NOANIMATION = 0x4000;
            public const int TPM_LAYOUTRTL = 0x8000;
            public const int TPM_WORKAREA = 0x10000;
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool GetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, [In, Out] ref MENUITEMINFO lpmii);
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct MENUITEMINFO
            {
                public uint cbSize;
                public uint fMask;
                public uint fType;         // used if MIIM_TYPE (4.0) or MIIM_FTYPE (>4.0)
                public uint fState;        // used if MIIM_STATE
                public uint wID;           // used if MIIM_ID
                public IntPtr hSubMenu;      // used if MIIM_SUBMENU
                public IntPtr hbmpChecked;   // used if MIIM_CHECKMARKS
                public IntPtr hbmpUnchecked; // used if MIIM_CHECKMARKS
                public IntPtr dwItemData;   // used if MIIM_DATA
                [MarshalAs(UnmanagedType.LPWStr)]
                string dwTypeData;    // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0)
                public uint cch;           // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0)
                public IntPtr hbmpItem;      // used if MIIM_BITMAP
            }
    
            public const int MIIM_STATE = 0x00000001;
            public const int MIIM_ID = 0x00000002;
            public const int MIIM_SUBMENU = 0x00000004;
            public const int MIIM_CHECKMARKS = 0x00000008;
            public const int MIIM_TYPE = 0x00000010;
            public const int MIIM_DATA = 0x00000020;
    
            public const int MIIM_STRING = 0x00000040;
            public const int MIIM_BITMAP = 0x00000080;
            public const int MIIM_FTYPE = 0x00000100;
    
            [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, StringBuilder lpString, int cchMax, uint flags);
    
            public const int MF_BYCOMMAND = 0x00000000;
            public const int MF_BYPOSITION = 0x00000400;
    
            //[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            //public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern IntPtr ILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath);
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern void ILFree(IntPtr pidl);
    

    • Marked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Unmarked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Marked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Unmarked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    • Marked as answer by JenCarlos Wednesday, August 21, 2019 12:18 PM
    Wednesday, August 21, 2019 8:14 AM
  • You are a genious.
    It works excellently.
    Many thanks.
    Wednesday, August 21, 2019 12:18 PM