May 31, 2020, 08:47:50 PM

Author Topic: any one have modern requesters building in ng?  (Read 298 times)

Offline braxtonrivers

  • Jr. Member
  • **
  • Posts: 24
any one have modern requesters building in ng?
« on: April 30, 2020, 02:18:40 AM »
Hi,

I was wondering if anyone had any success or any conversion tips in building this nice bit of code from col, on ng

https://www.syntaxbomb.com/index.php/topic,490.msg1479.html#msg1479

I cannot for the life of me figure out the correct needed externs for CoCreateInstance, CoInitialize & CoUninitialize

I was looking at using it for multi file selecting since it is not already baked in, as it works great on original max.

Sadly my original to ng skills are pretty lacking, any help or ideas are appreciated.

Thanks in advance
Braxton

Offline DruggedBunny

  • Jr. Member
  • **
  • Posts: 60
Re: any one have modern requesters building in ng?
« Reply #1 on: April 30, 2020, 12:06:16 PM »
I had a go, but no joy. I could be wrong, but I think NG might be putting out the wrong type for LPVOID when it generates the .h intermediary code:

Code: [Select]
In file included from D:/DevTools/Blitz/BlitzMaxNG/tmp/.bmx/untitled1.bmx.gui.release.win32.x64.c:1:
D:/DevTools/Blitz/BlitzMaxNG/tmp/.bmx/untitled1.bmx.gui.release.win32.x64.h:158:24: error: conflicting types for 'CoInitialize'
 extern void __stdcall  CoInitialize(BBBYTE* bbt_pvReserved);

That's a byte pointer (what I've used in my declaration) but it wants an LPVOID, which is defined as 'void' according to Microsoft. I think that means it should be generating something like:

Code: [Select]
CoInitialize(void pvReserved);

The MINGW definition is:

Code: [Select]
D:/DevTools/Blitz/BlitzMaxNG/MinGW32x64/x86_64-w64-mingw32/include/objbase.h:80:11: note: previous declaration of 'CoInitialize' was here
 WINOLEAPI CoInitialize (LPVOID pvReserved);

One for Brucey if I'm right!

My attempted (WIP) conversion:

Code: [Select]
    SuperStrict
     
    ?Win32
     
    Import "-lole32"
    Import Pub.Win32
     
    Global Shell32Dll:Byte Ptr = LoadLibraryA("Shell32.dll")
    Global SHCreateItemFromParsingName:Int(pszPath$w,pbc:Byte Ptr,riid:Byte Ptr,ppv:IUnknown_ Var)"Win32" = GetProcAddress(Shell32Dll,"SHCreateItemFromParsingName")
     
    Global CLSID_FileOpenDialog:Int[] = [$dc1c5a9c,$4ddee88a,$f860a1a5,$f7ae202a]
    Global IID_IFileOpenDialog:Int[] = [$d57c7288,$4768d4ad,$969d02be,$60d93295]
    Global IID_IShellItem:Int[] = [$43826d1e,$42eee718,$e2a155bc,$fe7bc361]
     
     
    Extern"Win32"
            'These types are INCOMPLETE - DO NOT USE FOR ANYTHING ELSE !!!!!!
            Type IModalWindow Extends IUnknown_
                    Method Show(hWnd:Int)
            EndType
     
            Type IFileDialog Extends IModalWindow
                    Method SetFileTypes:Int()
                    Method SetFileTypeIndex:Int()
                    Method GetFileTypeIndex:Int()
                    Method Advise:Int()
                    Method Unadvise:Int()
                    Method SetOptions:Int(dwOptions:Int)
                    Method GetOptions:Int(dwOptions:Byte Ptr)
                    Method SetDefaultFolder:Int(pShellItem:Byte Ptr)
                    Method SetFolder:Int(pSI:Byte Ptr)
                    Method GetFolder:Int()
                    Method GetCurrentSelection:Int()
                    Method SetFilename:Int(pszName$w)
                    Method GetFileName:Int()
                    Method SetTitle:Int(pszName$w)
                    Method SetOKButtonLabel:Int()
                    Method SetFilenameLabel:Int()
                    Method GetResult:Int(pItem:IShellItem Var)
                    Method AddPlace:Int()
                    Method SetDefaultExtension:Int()
                    Method Close:Int()
                    Method SetClientGuid:Int()
                    Method ClearClientData:Int()
                    Method SetFilter:Int()
            EndType
           
            Type IFileOpenDialog Extends IFileDialog
                    Method GetResults:Int(ppEnum:IShellItemArray Ptr)
                    Method GetSelectedItems:Int(ppsai:IShellItemArray Ptr)
            EndType
           
            Type IShellItemArray Extends IUnknown_
                    Method BindToHandler:Int()
                    Method GetPropertyStore:Int()
                    Method GetPropertyDescriptionList:Int()
                    Method GetAttributes:Int()
                    Method GetCount:Int(pdwNumItems:Int Ptr)
                    Method GetItemAt:Int(dwIndex:Int, ppsi:IShellItem Ptr)
                    Method EnumItems:Int()
            EndType
           
            Type IShellItem Extends IUnknown_
                    Method BindToHandler:Int()
                    Method GetParent:Int()
                    Method GetDisplayName:Int(sigdnName:Int,ppszName:Short Ptr Var)
                    Method GetAttributes:Int()
                    Method Compare:Int()
            EndType
           
            'Function CoCreateInstance:Int(rclsid:Byte Ptr,pUnkOuter:Byte Ptr,dwClsContext:Int,riid:Byte Ptr,ppv:IUnknown_ Var) 'My version
            Function CoInitialize(pvReserved:Byte Ptr)
             Function CoUninitialize()
    EndExtern
     
    Function RequestFiles:String[](title:String, initialPath:String)
            Global pDialog:IFileOpenDialog
            Global pInitialPath:IShellItem
            Global pResults:IShellItemArray
            Local hr:Int
           
            CoInitialize(Null)
     
            hr = CoCreateInstance(CLSID_FileOpenDialog,Null,CLSCTX_INPROC_SERVER,IID_IFileOpenDialog,Byte Ptr (Varptr pDialog))
            If hr < 0
                    CleanUp()
                    Return Null
            EndIf
           
            Local dwOptions:Int
            pDialog.GetOptions(Varptr dwOptions)
            pDialog.SetOptions(dwOptions|$200) ' $200 = FOS_ALLOWMULTISELECT
     
            'Create an IShellItem for a default folder path
            InitialPath = Replace(InitialPath,"/","")
            SHCreateItemFromParsingName(InitialPath,Null,IID_IShellItem,pInitialPath)
           
            If pDialog.SetFolder(pInitialPath) < 0
                    CleanUp()
                    Return [RequestFile(Title,InitialPath)]
            EndIf
     
            ' show it
            pDialog.SetTitle(Title)
            pDialog.Show(0)
     
            ' get the result
            If pDialog.GetResults(Varptr pResults) < 0
                    CleanUp()
                    Return Null
            EndIf
           
            'Get the results
            Local count:Int
            If pResults.GetCount(Varptr count) < 0
                    CleanUp()
                    Return Null
            EndIf
     
            Local selectedItemNames:String[count]
            For Local i:Int = 0 Until count
                    Local pItem:IShellItem
                    If pResults.getItemAt(i, Varptr pItem) >= 0
                            Local pName:Short Ptr
                            pItem.GetDisplayName($80058000,pName)
                            selectedItemNames[i] = String.FromWString(pName)
                    EndIf
     
                    If pItem pItem.Release_()
            Next   
           
            CleanUp()
            Return selectedItemNames
           
            Function CleanUp()
                    If pDialog
                            pDialog.Release_()
                            pDialog = Null
                    EndIf
                    If pInitialPath
                            pInitialPath.Release_()
                            pInitialPath = Null
                    EndIf
                    If pResults
                            pResults.Release_()
                            pResults = Null
                    EndIf
                    CoUninitialize()
            EndFunction   
    EndFunction
     
     
    Function RequestFolder$(Title$,InitialPath$)
            Global pDialog:IFileOpenDialog
            Global pInitialPath:IShellItem
            Global pFolder:IShellItem
            Local hr:Int,ResultFolder$
     
            CoInitialize(Null)
     
            'Create Instance of the Dialog
            hr = CoCreateInstance(CLSID_FileOpenDialog,Null,CLSCTX_INPROC_SERVER,IID_IFileOpenDialog,Byte Ptr (Varptr pDialog))
     
            'Not on Vista or Win7?
            If hr < 0 CleanUp(); Return RequestDir(Title,InitialPath)
           
            'Set it to Browse Folders
            Local dwOptions:Int
            pDialog.GetOptions(Varptr dwOptions)
            pDialog.SetOptions(dwOptions|$20)
           
            'Set Title
            pDialog.SetTitle(Title)
           
            'Create an IShellItem for a default folder path
            InitialPath = Replace(InitialPath,"/","")
            SHCreateItemFromParsingName(InitialPath,Null,IID_IShellItem,pInitialPath)
           
            If pDialog.SetFolder(pInitialPath) < 0
                    CleanUp()
                    Return RequestDir(Title,InitialPath)
            EndIf
                   
            'Show the Dialog
            pDialog.Show(0)
     
            'Test the result
            If pDialog.GetResult(pFolder) < 0
                    CleanUp
                    Return ""
            EndIf
           
            'Get the result
            Local pName:Short Ptr
            pFolder.GetDisplayName($80058000,pName)
            ResultFolder = String.FromWString(pName)
           
            CleanUp()
            Return ResultFolder
           
            Function CleanUp()
                    If pDialog
                            pDialog.Release_()
                            pDialog = Null
                    EndIf
                    If pInitialPath
                            pInitialPath.Release_()
                            pInitialPath = Null
                    EndIf
                    If pFolder
                            pFolder.Release_()
                            pFolder = Null
                    EndIf
                    CoUninitialize()
            EndFunction
    EndFunction
    ?
     
    'Example Usage
    Print RequestFolder("Select a Folder...","")
    Local files:String[] = RequestFiles("Select some file(s)","")
    For Local file:String = EachIn files
            Print file
    Next

Offline braxtonrivers

  • Jr. Member
  • **
  • Posts: 24
Re: any one have modern requesters building in ng?
« Reply #2 on: April 30, 2020, 01:23:51 PM »
Hi,

Thank you so much for taking a look, I appreciate it, yes this one has me stumped, those extern definitions I don't understand well enough for proper ng translation i'm afraid, even when looking at the definitions on msdn and mingw.

I know it was originally written for blitzmax classic but ng is just so good, Brucey has done amazing enhancements, above and beyond, that I could never go back now i'm all in.

We have such awesome resources and code gems in the code archives written originally for blitzmax classic that I am discovering and trying to convert over and use in ng.

Thanks
Braxton

Offline DruggedBunny

  • Jr. Member
  • **
  • Posts: 60
Re: any one have modern requesters building in ng?
« Reply #3 on: April 30, 2020, 01:39:28 PM »
Yeah, lots of great code for both .bb (algorithmic stuff in particular) and .bmx.

I've raised a GitHub 'issue' as I think Brucey might need to look at this...

https://github.com/bmx-ng/bcc/issues/488

Offline braxtonrivers

  • Jr. Member
  • **
  • Posts: 24
Re: any one have modern requesters building in ng?
« Reply #4 on: May 01, 2020, 02:34:07 AM »
Hi DruggedBunny,

Thank you for raising an issue, yes there are so many great algorithms, it is awesome of Qube to have the code archives available here, I use them often.

Thanks
Braxton

Offline Henri

  • Full Member
  • ***
  • Posts: 236
Re: any one have modern requesters building in ng?
« Reply #5 on: May 01, 2020, 12:29:48 PM »
Hi,

here is a working version for ng:

Code: [Select]
SuperStrict

?Win32

Import Pub.Win32

Import "-lole32"
 
Global Shell32Dll:Byte Ptr = LoadLibraryA("Shell32.dll")
Global SHCreateItemFromParsingName(pszPath$w,pbc:Byte Ptr,riid:Byte Ptr,ppv:IUnknown_ Var)"Win32" = GetProcAddress(Shell32Dll,"SHCreateItemFromParsingName")
 
Global CLSID_FileOpenDialog:Int[] = [$dc1c5a9c,$4ddee88a,$f860a1a5,$f7ae202a]
Global IID_IFileOpenDialog:Int[] = [$d57c7288,$4768d4ad,$969d02be,$60d93295]
Global IID_IShellItem:Int[] = [$43826d1e,$42eee718,$e2a155bc,$fe7bc361]

Private

Global pDialog:IFileOpenDialog_
Global pInitialPath:IShellItem_
Global pResults:IShellItemArray_
Global pFolder:IShellItem_

Public
 
Extern"Win32"
'These types are INCOMPLETE - DO NOT USE FOR ANYTHING ELSE !!!!!!
Interface IModalWindow_ Extends IUnknown_
Method Show(hWnd:Byte Ptr)
EndInterface

Interface IFileDialog_ Extends IModalWindow_
Method SetFileTypes()
Method SetFileTypeIndex()
Method GetFileTypeIndex(piFileType:UInt Var)
Method Advise()
Method Unadvise()
Method SetOptions(dwOptions:Int)
Method GetOptions(dwOptions:Int Ptr)
Method SetDefaultFolder(pShellItem:IShellItem_)
Method SetFolder:Int(pSI:IShellItem_)
Method GetFolder:Int(pSI:IShellItem_ Ptr)
Method GetCurrentSelection()
Method SetFilename(pszName$w)
Method GetFileName(pszName$w)
Method SetTitle(pszName$w)
Method SetOKButtonLabel()
Method SetFilenameLabel()
Method GetResult:Int(pItem:IShellItem_ Var)
Method AddPlace()
Method SetDefaultExtension()
Method Close()
Method SetClientGuid()
Method ClearClientData()
Method SetFilter()
EndInterface
   
Interface IFileOpenDialog_ Extends IFileDialog_
Method GetResults:Int(ppEnum:IShellItemArray_ Ptr)
Method GetSelectedItems(ppsai:IShellItemArray_ Ptr)
EndInterface
   
Interface IShellItemArray_ Extends IUnknown_
Method BindToHandler()
Method GetPropertyStore()
Method GetPropertyDescriptionList()
Method GetAttributes()
Method GetCount:Int(pdwNumItems:Int Ptr)
Method GetItemAt:Int(dwIndex:Int, ppsi:IShellItem_ Ptr)
Method EnumItems()
EndInterface
   
Interface IShellItem_ Extends IUnknown_
Method BindToHandler()
Method GetParent()
Method GetDisplayName(sigdnName:Int, ppszName:Short Ptr Var)
Method GetAttributes()
Method Compare()
EndInterface
   
Function CoCreateInstance:Int(rclsid:Byte Ptr, pUnkOuter:Byte Ptr, dwClsContext:Int, riid:Byte Ptr, ppv:IUnknown_ Var) = "INT CoCreateInstance(BYTE *,BYTE *,INT,BYTE *,IUnknown_**)!"
Function CoInitialize:Int(pvReserved:Int) = "INT CoInitialize(INT)!"
Function CoUninitialize:Int() = "INT CoUninitialize()!"
EndExtern
 
Function RequestFiles:String[](title:String, initialPath:String)

Local hr:Int

CoInitialize(0)

hr = CoCreateInstance(CLSID_FileOpenDialog,Null,CLSCTX_INPROC_SERVER,IID_IFileOpenDialog,pDialog)
If hr < 0 Then
_cleanup()
Return Null
EndIf

Local dwOptions:Int
pDialog.GetOptions(Varptr dwOptions)
pDialog.SetOptions(dwOptions|$200) ' $200 = FOS_ALLOWMULTISELECT

'Create an IShellItem for a default folder path
InitialPath = InitialPath.Replace("/","")
SHCreateItemFromParsingName(InitialPath,Null,IID_IShellItem,pInitialPath)

If pDialog.SetFolder(pInitialPath) < 0 Then
_cleanup()
Return [RequestFile(Title,InitialPath)]
EndIf

' show it
pDialog.SetTitle(Title)
pDialog.Show(0)

' get the result
If pDialog.GetResults(Varptr pResults) < 0 Then
_cleanup()
Return Null
EndIf
   
'Get the results
Local count:Int
If pResults.GetCount(Varptr count) < 0 Then
_cleanup()
Return Null
EndIf

Local selectedItemNames:String[count]
For Local i:Int = 0 Until count

Local pItem:IShellItem_
If pResults.getItemAt(i, Varptr pItem) >= 0 Then
Local pName:Short Ptr
pItem.GetDisplayName($80058000,pName)
selectedItemNames[i] = String.FromWString(pName)
EndIf

If pItem Then pItem.Release_()
Next   
   
_cleanup()
Return selectedItemNames

EndFunction

Function RequestFolder$(Title$,InitialPath$)

Local hr:Int,ResultFolder$

CoInitialize(0)

'Create Instance of the Dialog
hr = CoCreateInstance(CLSID_FileOpenDialog, Null, CLSCTX_INPROC_SERVER, IID_IFileOpenDialog, pDialog)

'Not on Vista or Win7? Resort to legacy dialog
If hr < 0 Then _cleanup(); Return RequestDir(Title,InitialPath)


'Set it to Browse Folders
Local dwOptions:Int
pDialog.GetOptions(Varptr dwOptions)
pDialog.SetOptions(dwOptions|$20)

'Set Title
pDialog.SetTitle(Title)

'Create an IShellItem for a default folder path
InitialPath = Replace(InitialPath,"/","")
SHCreateItemFromParsingName(InitialPath, Null, IID_IShellItem, pInitialPath)

If pDialog.SetFolder(pInitialPath) < 0
_cleanup()
Return RequestDir(Title,InitialPath)
EndIf
   
'Show the Dialog
pDialog.Show(0)

'Test the result
If pDialog.GetResult(pFolder) < 0
_cleanup
Return ""
EndIf

'Get the result
Local pName:Short Ptr
pFolder.GetDisplayName($80058000,pName)
ResultFolder = String.FromWString(pName)

_cleanup()

Return ResultFolder

EndFunction

Private

Function _cleanup()
If pDialog
pDialog.Release_()
pDialog = Null
EndIf
If pInitialPath
pInitialPath.Release_()
pInitialPath = Null
EndIf
If pFolder
pFolder.Release_()
pFolder = Null
EndIf

CoUninitialize()

EndFunction

Public
?


'Example Usage
'--------------
Print RequestFolder("Select a Folder...", "C:\BlitzmaxNG")
Local files:String[] = RequestFiles("Select some file(s)","")
For Local file:String = EachIn files
Print file
Next


-Henri
- Got 01100011 problems, but the bit ain't 00000001

Offline braxtonrivers

  • Jr. Member
  • **
  • Posts: 24
Re: any one have modern requesters building in ng?
« Reply #6 on: May 01, 2020, 01:12:42 PM »
Hi Henri,

Thank you so much that is awesome! thank you for helping to get it to work in ng I really appreciate it.

Thanks
Braxton

I needed to cast pInitialPath to Byte Ptr to get it running in the latest ng otherwise it would cause an exception.

changing these lines:
If pDialog.SetFolder(pInitialPath) < 0 Then

to:
If pDialog.SetFolder(Byte Ptr(pInitialPath)) < 0 Then

Offline Henri

  • Full Member
  • ***
  • Posts: 236
Re: any one have modern requesters building in ng?
« Reply #7 on: May 01, 2020, 03:01:32 PM »
Good catch  8)

This was due to method expecting a byte ptr, but variable was actually an Interface.

I have corrected this now.

-Henri
- Got 01100011 problems, but the bit ain't 00000001

Offline braxtonrivers

  • Jr. Member
  • **
  • Posts: 24
Re: any one have modern requesters building in ng?
« Reply #8 on: May 01, 2020, 03:32:42 PM »
Hi Henri,

Thank you again, I am going to try and add a save dialog, hopefully with filter support just to see if I can, just reading up on setfiletypes and how to feed it the correct values, here is a list of const values in case anyone needs them for options.

Thanks
Braxton

Const FOS_OVERWRITEPROMPT:Int=$2
Const FOS_STRICTFILETYPES:Int=$4
Const FOS_NOCHANGEDIR:Int=$8
Const FOS_PICKFOLDERS:Int=$20
Const FOS_FORCEFILESYSTEM:Int=$40
Const FOS_ALLNONSTORAGEITEMS:Int=$80
Const FOS_NOVALIDATE:Int=$100
Const FOS_ALLOWMULTISELECT:Int=$200
Const FOS_PATHMUSTEXIST:Int=$800
Const FOS_FILEMUSTEXIST:Int=$1000
Const FOS_CREATEPROMPT:Int=$2000
Const FOS_SHAREAWARE:Int=$4000
Const FOS_NOREADONLYRETURN:Int=$8000
Const FOS_NOTESTFILECREATE:Int=$10000
Const FOS_HIDEMRUPLACES:Int=$20000
Const FOS_HIDEPINNEDPLACES:Int=$40000
Const FOS_NODEREFERENCELINKS:Int=$100000
Const FOS_DONTADDTORECENT:Int=$2000000
Const FOS_FORCESHOWHIDDEN:Int=$10000000
Const FOS_DEFAULTNOMINIMODE:Int=$20000000
Const FOS_FORCEPREVIEWPANEON:Int=$40000000

Offline DruggedBunny

  • Jr. Member
  • **
  • Posts: 60
Re: any one have modern requesters building in ng?
« Reply #9 on: May 01, 2020, 07:26:12 PM »
Nice work! Will have to study this...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal