FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour To Antonio converte a function
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
To Antonio converte a function
Posted: Tue Jun 30, 2015 05:15 PM
When you press the right button in a picture from My Computer , Windows displays a list of installed applications associated with that type of file "OPen with..."




I found a c++ function on stackoverflow but I not Know how converte it into harbour

http://stackoverflow.com/questions/1557 ... ntext-menu
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 375
Joined: Tue Feb 10, 2015 09:48 AM
Re: To Antonio converte a function
Posted: Thu Jul 02, 2015 07:27 AM
I converted the function for fun :-)
Code (fw): Select all Collapse
#include <fivewin.ch>
#include <winapi.ch>

memvar oPreview

#define MF_BYPOSITION 1024
#define WM_INITMENUPOPUP 0x0117
#define TPM_RETURNCMD 0x0100

function main()

   local oDlg
   public oPreview
   // IMPORTANT!!
   CoInitialize()
   
   DEFINE WINDOW oDlg FROM  0,0 TO 650,650 PIXEL TITLE "Test"
   oDlg:bLClicked := {|| ApriCon(oDlg:hWnd, "C:\fwh\samples\test.jpg") }
   ACTIVATE WINDOW oDlg CENTERED 

return nil

function ApriCon(hWnd, cFileName)
   Local hMenu
   Local cmd 
   local aCoords := GetCursorPos()
   LOCAL hShell32, msg1, msg2, cmp
   LOCAL n, i
   LOCAL ContextMenu
   // crate a context menu
   ContextMenu := IContextMenu_Get(hWnd, cFileName)
   if( ContextMenu == 0 )
      return .F.
   endif
   // get localized "Open with"
   hShell32 := GetModuleHandle("shell32.dll")
   msg1 := LoadString(hShell32, 5376)
   msg2 := LoadString(hShell32, 5377)
   // create the menu
   hMenu := CreatePopupMenu()
   IContextMenu_GetMenu(ContextMenu, hMenu)
   // looking for "Open with"
   n := GetMItemCount(hMenu)
   for i:=1 To n
      cmp := GetMenuString(hMenu, i-1, MF_BYPOSITION)
      if cmp == msg1 .or. cmp == msg2 
         exit
      endif
   next
   aCoords := GetCursorPos()
   if i < n //found
      // fill the "open with" sub menu
      n := IContextMenu_HandleMenuMsg(ContextMenu, WM_INITMENUPOPUP, GetSubMenu(hMenu,i-1), 0)
      // show the menu
      cmd := TrackPopupMenuEx_n( GetSubMenu(hMenu,i-1), TPM_RETURNCMD, aCoords[1], aCoords[2], hWnd, 0)
   else
      // show the complete menu
      cmd := TrackPopupMenuEx_n( hMenu, TPM_RETURNCMD, aCoords[1], aCoords[2], hWnd, 0)
   endif
   // execute the command
   if cmd>0
      IcontextMenu_Invoke(ContextMenu, hWnd, cmd, aCoords[1], aCoords[2])
   endif
   // clean up
   DestroyMenu(hMenu)
   IcontextMenu_Release(ContextMenu)
   // return true if an application starts
return cmd>0

#pragma BEGINDUMP
#define CINTERFACE
#define COBJMACROS
#include <windows.h>
#include <hbapi.h>
#include <CommCtrl.h>
#include <ShObjIdl.h>
#include <Shlwapi.h>
#include <ShlGuid.h>
#include <ShlObj.h>

LPWSTR     AnsiToWide( LPSTR cAnsi );

void* GetUIObjectOf(HWND hWnd, LPWSTR cFileName, REFIID iid)
{
#if 1 //Debug :p
   char tmp[100];
   #define CK(msg) if(hr!=S_OK) { sprintf_s(tmp,100,msg " 0x%08X",hr); MessageBox(0,tmp,"error",MB_OK); }
#else
   #define CK(msg)
#endif
   HRESULT hr;
   LPITEMIDLIST pidl;
   SFGAOF sfgao;
   void *ppv = NULL;
   
   if (SUCCEEDED(hr = SHParseDisplayName(cFileName, NULL, &pidl, 0, &sfgao))) {
    IShellFolder *psf;
    LPCITEMIDLIST pidlChild;
    if (SUCCEEDED(hr = SHBindToParent(pidl, &IID_IShellFolder,
                                      (void**)&psf, &pidlChild))) {
      hr = IShellFolder_GetUIObjectOf(psf, hWnd, 1, &pidlChild, iid, NULL, &ppv);
      IShellFolder_Release(psf);
    }
    CoTaskMemFree(pidl);
  }
  CK("GetUIObjectOf")
  return ppv;
}


HB_FUNC( ICONTEXTMENU_GET ) // hWnd, cFileName
{
#ifndef _WIN64
   HWND hWnd = ( HWND ) hb_parnl( 1 );
#else   
   HWND hWnd = ( HWND ) hb_parnll( 1 );
#endif   
   LPWSTR cFileName = AnsiToWide(( char * ) hb_parc( 2 ));
   IContextMenu *pContextMenu = (IContextMenu*)GetUIObjectOf(hWnd, cFileName, &IID_IContextMenu);

#ifndef _WIN64
   hb_retnl( (long)pContextMenu );
#else   
   hb_retnll( (long long)pContextMenu );
#endif   

}

HB_FUNC( ICONTEXTMENU_GETMENU ) //IContextMenu, hMenu
{
#ifndef _WIN64
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnl( 1 );
   HMENU hMenu = ( HMENU ) hb_parnl( 2 );
#else   
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnll( 1 );
   HMENU hMenu = ( HMENU ) hb_parnll( 2 );
#endif
   if( pContextMenu )
   {
      hb_retnl(IContextMenu_QueryContextMenu(pContextMenu, hMenu, 0, 1,0x7FFF, 0));
   }
   
   hb_retnl(0);
}

HB_FUNC( ICONTEXTMENU_INVOKE ) //IContextMenu, hWnd, id, pt.y, pt.x
{
#ifndef _WIN64
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnl( 1 );
   HWND hWnd = ( HWND ) hb_parnl( 2 );   
#else   
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnll( 1 );
   HWND hWnd = ( HWND ) hb_parnll( 2 );
#endif
   int iCmd = hb_parni( 3 )-1;
   
   CMINVOKECOMMANDINFOEX info = { 0 };
   info.cbSize = sizeof(CMINVOKECOMMANDINFOEX);
   info.fMask = CMIC_MASK_UNICODE | CMIC_MASK_PTINVOKE;
   info.hwnd = hWnd;
   info.lpVerb  = MAKEINTRESOURCEA(iCmd);
   info.lpVerbW = MAKEINTRESOURCEW(iCmd);
   info.nShow = SW_SHOWNORMAL;
   info.ptInvoke.y = hb_parni(4);
   info.ptInvoke.x = hb_parni(5);
   hb_retnl(IContextMenu_InvokeCommand(pContextMenu, (LPCMINVOKECOMMANDINFO)&info));
}

HB_FUNC( ICONTEXTMENU_HANDLEMENUMSG ) // IContextMenu, nMsg, nWParam, nLParam)
{
#ifndef _WIN64
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnl( 1 );
#else   
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnll( 1 );
#endif
    UINT message = ( UINT ) hb_parnl( 2 );
   WPARAM wParam  = ( WPARAM ) hb_parnl( 3 );
   LPARAM lParam  = ( LPARAM ) hb_parnl( 4 );
   HRESULT hr;
   IContextMenu2 *pContextMenu2;
   IContextMenu_QueryInterface( pContextMenu, &IID_IContextMenu2, (void**)&pContextMenu2);
   hr = IContextMenu2_HandleMenuMsg(pContextMenu2, message, wParam, lParam);
   IContextMenu2_Release(pContextMenu2);
   hb_retnl(hr);
}

HB_FUNC( ICONTEXTMENU_RELEASE ) //IContextMenu
{
#ifndef _WIN64
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnl( 1 );
#else   
   IContextMenu *pContextMenu = ( IContextMenu* ) hb_parnll( 1 );
#endif
   if( pContextMenu )
   {
      IContextMenu_Release(pContextMenu);
   }
   hb_ret();
}

HB_FUNC( TRACKPOPUPMENUEX_N )
{
  hb_retnl( TrackPopupMenuEx( ( HMENU ) hb_parnl( 1 ), hb_parni( 2 ), hb_parni( 4 ),
           hb_parni( 3 ), ( HWND ) hb_parni( 5 ), NULL ) );
} 


#pragma ENDDUMP

To test:

  • Change the filename in line 18 with an existing one before compiling[/*:m]
  • Left click on the window to show the menu[/*:m][/list:u]

    PS. compile with Visual Studio 2013 Community edition

    Regards,
    Antonino
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: To Antonio converte a function
Posted: Thu Jul 02, 2015 02:09 PM
thanks but with bcc585 not run

Code (fw): Select all Collapse
Progetto: test, Ambiente: xFive_Pelles:
[1]:Harbour.Exe test.prg  /m /n0 /gc1 /es2 /iC:\Work\fwh\include /ic:\work\xHarbour\Include /jC:\Work\Errori\AN4154~1\I18n\Main.hil /iinclude;c:\work\fwh\include;c:\work\xHarbour\include /oObj\test.c
xHarbour 1.2.3 Intl. (SimpLex) (Build 20140725)
Copyright 1999-2014, http://www.xharbour.org <!-- m --><a class="postlink" href="http://www.harbour-project.org/">http://www.harbour-project.org/</a><!-- m -->
Compiling 'test.prg'...
Generating international list to 'C:\Work\Errori\AN4154~1\I18n\Main.hil'...
Generating C source output to 'Obj\test.c'...
Done.
Lines 70, Functions/Procedures 2, pCodes 275
[1]:Bcc32.Exe -M -c -O2  -tW -v- -X -DHB_FM_STATISTICS_OFF -DHB_NO_DEFAULT_API_MACROS -DHB_NO_DEFAULT_STACK_MACROS -DHB_OS_WIN_32 -IC:\Work\fwh\include -IC:\Work\bcc582\Include;c:\work\xHarbour\Include  -nC:\Work\Errori\AN4154~1\Obj test.c
Borland C++ 5.82 for Win32 Copyright (c) 1993, 2005 Borland
test.c:
Warning W8065 test.prg 106: Call to function 'sprintf_s' with no prototype in function GetUIObjectOf
Warning W8065 test.prg 140: Call to function 'IContextMenu_QueryContextMenu' with no prototype in function HB_FUN_ICONTEXTMENU_GETMENU
Warning W8065 test.prg 166: Call to function 'IContextMenu_InvokeCommand' with no prototype in function HB_FUN_ICONTEXTMENU_INVOKE
Warning W8065 test.prg 181: Call to function 'IContextMenu_QueryInterface' with no prototype in function HB_FUN_ICONTEXTMENU_HANDLEMENUMSG
Warning W8065 test.prg 182: Call to function 'IContextMenu2_HandleMenuMsg' with no prototype in function HB_FUN_ICONTEXTMENU_HANDLEMENUMSG
Warning W8065 test.prg 183: Call to function 'IContextMenu2_Release' with no prototype in function HB_FUN_ICONTEXTMENU_HANDLEMENUMSG
Warning W8065 test.prg 196: Call to function 'IContextMenu_Release' with no prototype in function HB_FUN_ICONTEXTMENU_RELEASE
[1]:iLink32.Exe -Gn -aa -Tpe -s @test.bcl
Turbo Incremental Link 5.69 Copyright (c) 1997-2005 Borland
Error: Unresolved external '_sprintf_s' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Error: Unresolved external '_IContextMenu_QueryContextMenu' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Error: Unresolved external '_IContextMenu_InvokeCommand' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Error: Unresolved external '_IContextMenu_QueryInterface' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Error: Unresolved external '_IContextMenu2_HandleMenuMsg' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Error: Unresolved external '_IContextMenu2_Release' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Error: Unresolved external '_IContextMenu_Release' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 375
Joined: Tue Feb 10, 2015 09:48 AM
Re: To Antonio converte a function
Posted: Thu Jul 02, 2015 02:25 PM
Try add this, where the ansiToWide is declared:
Code (cpp): Select all Collapse
<div class="cpp" id="{CB}" style="font-family: monospace;">#ifndef IContextMenu_QueryInterface
#define IContextMenu_QueryInterface(This,riid,ppvObject)    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
#define IContextMenu_AddRef(This)   ( (This)->lpVtbl -> AddRef(This) ) 
#define IContextMenu_Release(This)  ( (This)->lpVtbl -> Release(This) ) 
#define IContextMenu_QueryContextMenu(This,hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags) ( (This)->lpVtbl -> QueryContextMenu(This,hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags) ) 
#define IContextMenu_InvokeCommand(This,pici)   ( (This)->lpVtbl -> InvokeCommand(This,pici) ) 
#define IContextMenu_GetCommandString(This,idCmd,uType,pReserved,pszName,cchMax)    ( (This)->lpVtbl -> GetCommandString(This,idCmd,uType,pReserved,pszName,cchMax) ) 
#define IContextMenu2_Release(This) ( (This)->lpVtbl -> Release(This) ) 
#define IContextMenu2_HandleMenuMsg(This,uMsg,wParam,lParam)    ( (This)->lpVtbl -> HandleMenuMsg(This,uMsg,wParam,lParam) ) 
#endif</div>

and substitute sprintf_s with snprintf
Antonino
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: To Antonio converte a function
Posted: Thu Jul 02, 2015 02:44 PM
one error

Code (fw): Select all Collapse
Progetto: test, Ambiente: xFive_Pelles:
[1]:Harbour.Exe test.prg  /m /n0 /gc1 /es2 /iC:\Work\fwh\include /ic:\work\xHarbour\Include /jC:\Work\Errori\AN4154~1\I18n\Main.hil /iinclude;c:\work\fwh\include;c:\work\xHarbour\include /oObj\test.c
xHarbour 1.2.3 Intl. (SimpLex) (Build 20140725)
Copyright 1999-2014, http://www.xharbour.org <!-- m --><a class="postlink" href="http://www.harbour-project.org/">http://www.harbour-project.org/</a><!-- m -->
Compiling 'test.prg'...
Generating international list to 'C:\Work\Errori\AN4154~1\I18n\Main.hil'...
Generating C source output to 'Obj\test.c'...
Done.
Lines 70, Functions/Procedures 2, pCodes 275
[1]:Bcc32.Exe -M -c -O2  -tW -v- -X -DHB_FM_STATISTICS_OFF -DHB_NO_DEFAULT_API_MACROS -DHB_NO_DEFAULT_STACK_MACROS -DHB_OS_WIN_32 -IC:\Work\fwh\include -IC:\Work\bcc582\Include;c:\work\xHarbour\Include  -nC:\Work\Errori\AN4154~1\Obj test.c
Borland C++ 5.82 for Win32 Copyright (c) 1993, 2005 Borland
test.c:
Warning W8065 test.prg 131: Call to function 'sprintf_s' with no prototype in function GetUIObjectOf
[1]:iLink32.Exe -Gn -aa -Tpe -s @test.bcl
Turbo Incremental Link 5.69 Copyright (c) 1997-2005 Borland
Error: Unresolved external '_sprintf_s' referenced from C:\WORK\ERRORI\ANTONINO_APRICON\OBJ\TEST.OBJ
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 7318
Joined: Thu Oct 18, 2012 07:17 PM
Re: To Antonio converte a function
Posted: Thu Jul 02, 2015 03:11 PM
Antonino,

oDlg:bLClicked := {|| ApriCon(oDlg:hWnd, "c:\test.jpg") } run ok

oDlg:bLClicked := {|| ApriCon(oDlg:hWnd, "test.jpg") } not run

oDlg:bLClicked := {|| ApriCon(oDlg:hWnd, ".\test\test.jpg") } not run


oDlg:bLClicked := {|| ApriCon(oDlg:hWnd,CURDRIVE() + "\"+ cFile) } not run
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 375
Joined: Tue Feb 10, 2015 09:48 AM
Re: To Antonio converte a function
Posted: Thu Jul 02, 2015 03:59 PM

The file must exist and passed with absolute path.

Continue the discussion