Hi,
I'm trying to translate this piece of c or c++ code to aurora to set the initial select folder in the dialog
#include <windows.h>
#include <shlobj.h>
int CALLBACK BrowseForFolderCallback(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)
{
char szPath[MAX_PATH];
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
break;
case BFFM_SELCHANGED:
if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szPath))
{
SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,(LPARAM)szPath);
}
break;
}
return 0;
}
BOOL BrowseFolders(HWND hwnd, LPSTR lpszFolder, LPSTR lpszTitle)
{
BROWSEINFO bi;
char szPath[MAX_PATH + 1];
LPITEMIDLIST pidl;
BOOL bResult = FALSE;
LPMALLOC pMalloc;
if (SUCCEEDED(SHGetMalloc(&pMalloc)))
{
bi.hwndOwner = hwnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = lpszTitle;
bi.ulFlags = BIF_STATUSTEXT; //BIF_EDITBOX
bi.lpfn = BrowseForFolderCallback;
bi.lParam = (LPARAM)lpszFolder;
pidl = SHBrowseForFolder(&bi);
if (pidl)
{
if (SHGetPathFromIDList(pidl,szPath))
{
bResult = TRUE;
strcpy(lpszFolder, szPath);
}
pMalloc->Free(pidl);
pMalloc->Release();
}
}
return bResult;
}
Here is mine that crash when i use the callback...
//extern string BrowseFolders(CWindow *win, STRING title, opt Pointer lpszFolder, opt INT newfolder , opt STRING root);
#include "windows.inc"
#include "shlwapi.inc"
#include "shlobj.inc"
#DEFINE BIF_RETURNONLYFSDIRS 0x0001
#DEFINE BIF_DONTGOBELOWDOMAIN 0x0002
#DEFINE BIF_STATUSTEXT 0x0004
#DEFINE BIF_RETURNFSANCESTORS 0x0008
#DEFINE BIF_EDITBOX 0x0010
#DEFINE BIF_VALIDATE 0x0020
#DEFINE BIF_NEWDIALOGSTYLE 0x0040
#DEFINE BIF_USENEWUI (BIF_NEWDIALOGSTYLE | BIF_EDITBOX)
#DEFINE BIF_BROWSEINCLUDEURLS 0x0080
#DEFINE BIF_UAHINT 0x0100
#DEFINE BIF_NONEWFOLDERBUTTON 0x0200
#DEFINE BIF_NOTRANSLATETARGETS 0x0400
#DEFINE BIF_BROWSEFORCOMPUTER 0x1000
#DEFINE BIF_BROWSEFORPRINTER 0x2000
#DEFINE BIF_BROWSEINCLUDEFILES 0x4000
#DEFINE BIF_SHAREABLE 0x8000
#DEFINE BFFM_INITIALIZED 1
#DEFINE BFFM_SELCHANGED 2
#DEFINE BFFM_VALIDATEFAILEDA 3
#DEFINE BFFM_VALIDATEFAILEDW 4
#DEFINE BFFM_IUNKNOWN 5
//Open Browse for folder dialog, return folder path
GLOBAL SUB BrowseFolders(CWindow *win, STRING title, opt Pointer lpszFolder, opt INT newfolder , opt STRING root),STRING
{
DSTRING path[260];
BROWSEINFO bi;
WORD szPath[MAX_PATH + 1];
pointer lpIDList;
POINTER pidl;
STRING Buffer;
//Make sure COM is active
CoInitialize(NULL);
//initialize variables
path[0] = 0;
RtlZeroMemory(bi,LEN(bi));
if root <> ""
{
bi.pidlRoot = GetPIDLfromPATH(win, s2w(root));
}
else
{
bi.pidlRoot = null;
}
bi.hwndOwner = win->GetHandle();
bi.pszDisplayName = Buffer;
bi.lpszTitle = Title;
bi.lpfn = /**(BFFCALLBACK)*/&BrowseForFolderCallback;
bi.lParam = *(LPARAM)lpszFolder;
IF newfolder = true
{
bi.ulFlags = 0x00000001|BIF_NEWDIALOGSTYLE;
}
ELSE
{
if newfolder = false | newfolder = null
{
bi.ulFlags = 0x00000001;
}
}
//messagebox(0, "", "");
lpIDList = SHBrowseForFolder(&bi);
if (lpIDList)
{
pszPath = SHGetPathFromIDList(lpIDList,path);
if (pszPath)
{
strcpy(*(string)lpszFolder, path);
}
CoTaskMemFree(lpIDList);
CoUninitialize();
}
RETURN path;
}
SUB BrowseForFolderCallback(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData), LPARAM
{
WORD szPath[MAX_PATH];
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
return;
case BFFM_SELCHANGED:
if (SHGetPathFromIDList( lp ,szPath))
{
SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,szPath);
}
return;
}
return 0;
}
// Use by BrowseForFolder
Global SUB GetPIDLfromPATH(Cwindow *win, POINTER *path),ITEMIDLIST*
{
return SHSimpleIDListFromPath(*(wstring)Path);
}
Anyone can see the problem?
does it compile?
If not, what error messages do you get?
Yes it compile but the app crash when calling it...
I have never used Aurora myself, but in my version there is an example called folder_browser.src that compiles just fine and does not crash. The source also contains suggestions for modifications.
What is wrong with it?
Hi,
I don’t have check in my examples folder before seeing your post, but what i want to do is use the UINT lpfn; in BrowseInfo
This parameter is used to select the folder specified... and it use CallBack...
That’s where it crashes... you can isolate the call with the messagebox commented to see
I have done a lot of pirouettes with the code, can't find a way.
to run, just put the extern call at the top in an src file in a project and add the src file to your project
As I mentioned before, I do not have any experience with Aurora.
To use the value of lpfn you have to return it in some way for use outside the particular suboutine where it is retreived.
But when inspecting your code with my IWB eyes, the only value returned from your code is path, defined as string.
The folder_browser.src also use the BrowseInfo structure, so suggest you inspect that code closely to see what element(s) that differs from your code,
and see to that a variable holding the value of lpfn is returned.
Sorry for not being able to give you a more more specific answer. But hopefully some of the other forum users, with Aurora experience, will see this and guide you into the right path...
Good Luck!
QuoteTo use the value of lpfn you have to return it in some way for use outside the particular suboutine where it is retreived.
But when inspecting your code with my IWB eyes, the only value returned from your code is path, defined as string.
yep browse for folder dialog return a path ;)
the callback is retreived by sub "BrowseForFolderCallback" which must return 0 as the example in c or c++ above
QuoteThe folder_browser.src also use the BrowseInfo structure, so suggest you inspect that code closely to see what element(s) that differs from your code,
and see to that a variable holding the value of lpfn is returned.
BrowseInfo structure is declare in the one of the #define .inc file at the top of the code... :)
Thanks anyway sir
Well, this was written by the man who wrote the Aurora compiler, so give it a go:
SUB main()
{
string folder = GetFolder(null,"Select a folder");
print(folder);
While GetKey() == "";
}
/* subroutine to open the system folder browser */
struct BROWSEINFO
{
UINT hOwner;
UINT pidlRoot;
POINTER pszDisplayName;
POINTER lpszTitle;
UINT ulFlags;
UINT lpfn;
INT lParam;
INT iImage;
}
DECLARE IMPORT,SHGetPathFromIDList(int pidl,string pszPath),INT;
DECLARE IMPORT,SHBrowseForFolder(BROWSEINFO lpbi),INT;
DECLARE IMPORT,CoTaskMemFree(int pidl);
DECLARE IMPORT,ZeroMemory ALIAS RtlZeroMemory(pData as POINTER,length as INT);
declare import,SHParseDisplayName(WSTRING pszName,UINT *pbc,UINT *ppidl,UINT sfgaoIn,UINT *psfgaoOut),INT;
declare import,SHGetSpecialFolderLocation(UINT hwnd,int nFoloder,UINT *ppidl),int;
SUB GetFolder(UINT hwnd,string title),STRING
{
DSTRING path[260];
BROWSEINFO bi;
UINT lpIDList;
UINT pRoot,pTemp;
//initialize variables
path[0] = 0;
ZeroMemory(bi,LEN(bi));
//for Windows XP and above we can use SHParseDisplayName which can take a file path
//such as "c:\\progs" or a CLSID. The CLSID being used is for the My Computer folder.
SHParseDisplayName(s2w("::{20d04fe0-3aea-1069-a2d8-08002b30309d}"),NULL,pRoot,0,pTemp);
//for all Windows version this gets the pidl of the My Computer folder.
//So if you are targeting Windows 9x and above use this instead
//SHGetSpecialFolderLocation(null,0x0011,pRoot);
bi.pidlRoot = pRoot;
bi.hOwner = hwnd;
bi.pszDisplayName = path;
bi.lpszTitle = title;
bi.ulFlags = 0x00000041;
lpIDList = SHBrowseForFolder(bi);
if lpIDList <> 0
{
SHGetPathFromIDList(lpIDList,path);
CoTaskMemFree(lpIDList);
}
RETURN path;
}
/* other common CLSID's for use with SHParseDisplayName:
My Documents ::{450d8fba-ad25-11d0-98a8-0800361b1103}
Programs Folder ::{7be9d83c-a729-4d97-b5a7-1b7313c39e0a}
Start Menu Folder ::{48e7caab-b918-4e58-a94d-505519c795dc}
Temporary Internet Files ::{7bd29e00-76c1-11cf-9dd0-00a0c9034933}
My Network Places ::{208d2c60-3aea-1069-a2d7-08002b30309d}
*/
Brian
That is the same example I tried to direct his attention to, Brian.
It is found in the examples folder that came with Aurora, and the filename is folder_browser.src .
He stated himself he had not checked it before starting converting from C.
Bought Aurora just to support the site, and never used it. Had to install it last night to find that example.
The problem is that the subroutines he calls only return string values, and he want to use a structure member called lpfn which is defined as an UINT.
So whatever programming language he uses, he somehow has to retreive and return the value of lpfn before he can use it.
Egil,
Well, I'm not doing anything much at the moment, so I might load my Aurora up and have a go!
Brian
Update: Well, loaded up Aurora. Didn't bother with the extra headers, and compiled
Got it - compile as a Console exe and not a Windows exe
It then displays the folder selected. "print (folder);" is the line that does that
Thats good Brian!
You have way more experience with Windows than me, so let's hope you are able to help him.
Compile folder_browser.src as a Console exe, not a Windows exe
Brian
Here it does not matter if I choose Console.exe or windows.exe. Both compile fine.
Guess the browse for folder dialog is the same for both methods.
well
interesting ...when i try to compile Ebasic(old freeware v1.62) program i receive
message from win7 that i don't have permission to do that and linker cannot link exe to
program files , but when i move eba example to folder C\user then
compile file and exe work. :)
also i dont get it why he need to return
longPointer...
lpIDList = SHBrowseForFolder(bi)
Hi guys,
Like i said the folder_browser.src example work well as my code if you remove the bi.lpfn call, just comment it and it works...
My problem is the Callback that don't work... i need it so the last selected folder should be selected in the dialog when you open it ;)
Hi. You are using lpszFolder as optional inside your BrowseFolders function, I think you should check its value before using it as a pointer
if lpszFolder { bi.lParam = *(LPARAM)lpszFolder; }
.....
if lpszFolder { strcpy(*(string)lpszFolder, path); }
And the SHGetPathFromIDList method from your BrowseForFolderCallback function should require a structure, not a pointer, in the first parameter
if (SHGetPathFromIDList( *(ITEMIDLIST) lp , szPath) )
Thanks fasecero,
I have done lots of pirouettes with the code and i think i had tryed that... but i will give it another go with your suggestions later today
thank you :)
look this Ebasic program work properly and return last open folder:
/*
EBASIC example program
Shows how to use the system directory browser
Compile as a WINDOWS target
*/
DEF mywin:WINDOW
DEF result:INT
DEF Buffer:STRING
DEF sf:INT
OPENWINDOW mywin,0,0,400,300,@MINBOX,0,"Browse for Folder",&mysub
print mywin,GetFolder()
run = 1
WAITUNTIL run = 0
CLOSEWINDOW mywin
END
SUB mysub
SELECT @CLASS
CASE @IDCLOSEWINDOW
run = 0
CASE @IDCREATE
CENTERWINDOW mywin
ENDSELECT
RETURN
ENDSUB
/* subroutine to open the system folder browser */
TYPE BROWSEINFO
DEF hOwner:UINT
DEF pidlRoot:UINT
DEF pszDisplayName:POINTER
DEF lpszTitle:POINTER
DEF ulFlags:UINT
DEF lpfn:UINT
DEF lParam:INT
DEF iImage:INT
ENDTYPE
DECLARE IMPORT,SHGetPathFromIDList(pidl:INT,pszPath:STRING),INT
DECLARE IMPORT,SHBrowseForFolder(lpbi:BROWSEINFO),INT
DECLARE IMPORT,CoTaskMemFree(pidl:int)
DECLARE IMPORT,ZeroMemory ALIAS RtlZeroMemory(pData as POINTER,length as INT)
SUB GetFolder(),STRING
DEF path[260] as ISTRING
DEF bi:BROWSEINFO
DEF lpIDList:INT
'initialize variables
path[0] = 0
ZeroMemory(bi,LEN(bi))
bi.hOwner = mywin.hwnd
bi.pszDisplayName = Buffer
bi.lpszTitle = "Select Directory:"
bi.ulFlags = 0x00000001
lpIDList = SHBrowseForFolder(bi)
if lpIDList <> 0
pszPath = SHGetPathFromIDList(lpIDList,path)
CoTaskMemFree(lpIDList)
ENDIF
RETURN path
ENDSUB
Thanks Aurel
but its the same as folder_browser.src that was shown in a post above... yes it return the path but dont select the last folder selected ;)
Quoteyes it return the path but dont select the last folder selected
::)
well i dont get it what you mean exactly but if you mean
that browser dialog is not visible after path is presented in output window
then you need different type of program with lot more code
or maybe you can force dialog to be
always on top
hehe .. lol
Aurel what i want to do is when you open the browsefolder dialog, i want the last folder that the user use to be selected in the dialog...
So he can know the folder he selected before...
in vb.net its just a question of pass a string...
in wn32 you have to use a callback function ;)
Quote from: StormAce on March 02, 2016, 04:09:00 PM
... i want the last folder that the user use to be selected in the dialog...
So he can know the folder he selected before...
Hi StormAce,
Below is the code needed for MiniBASIC to do exactly that.
It contains all the defines you need for such a function, and should not be too difficult to convert to Aurora.
The included zip archive also contains an exe file made by compiling the code shown.
(The code is part of a program for bulk renaming mp3 files)
'
' folder_browse.mba
'
##NOCONSOLE
const BIF_RETURNONLYFSDIRS = 1
const BIF_NEWDIALOGSTYLE = 0x00000040
const BIF_UAHINT = 0x00000100
@API SHBrowseForFolderA(lpbi As pointer),int
@API SHGetPathFromIDList(pidList As int,lpBuffer As String),int
@API CoTaskMemFree(hMem As int)
Type BrowseInfo
int hWndOwner
int pIDLRoot
pointer pszDisplayName
pointer lpszTitle
int ulFlags
int lpfnCallback
int lParam
int iImage
End Type
WINDOW win
win.Open(0,0,800,480,WS_SYSMENU|WS_VISIBLE|BUFFERED|CENTERED,0," Mp3Rename",NULL,&handler)
' Select directory to convert
BrowseInfo bi
int ret
string Path,name
bi.lpszTitle = "Choose Folder"
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE|BIF_UAHINT
bi.pszDisplayName = name
ret = SHBrowseForFolderA(bi)
SHGetPathFromIDList(ret,Path)
CoTaskMemFree(ret)
win.WriteText(10,20,"Selected Directory: "+Path)
DO:ProcessMessages():UNTIL win.GetHandle()=NULL:END
' Main loop
FUNC handler(WINDOW wnd),int
SELECT wnd.Message
CASE ID_CLOSE
wnd.Close()
ENDSELECT
RETURN 0
ENDF
thanks Egil,
Ill tryed it later today :)
Quotei want the last folder that the user use to be selected in the dialog...
So he can know the folder he selected before...
Well i get it now ,but you dont say that first time.
So you need something like listbox to store each selected folder name
but this require more coding....
yes, well, its already coded ;)
I take it from registry in fact
Was much easier to convert MiniBASIC code to Aurora than I first thought. Here is the code needed to print selected browser to a console screen:
// folder_browse.src
// Compile as console
SUB main()
{
dstring folder = GetFolder(null,"Select a folder");
print ("Selected directory:");
print(folder);
int run = 1;
do
{
wait();
}
until run = 0;
}
struct BROWSEINFO
{
UINT hOwner;
UINT pidlRoot;
POINTER pszDisplayName;
POINTER lpszTitle;
UINT ulFlags;
UINT lpfn;
INT lParam;
INT iImage;
}
DECLARE IMPORT,SHGetPathFromIDList(int pidl,string pszPath),INT;
DECLARE IMPORT,SHBrowseForFolder(BROWSEINFO lpbi),INT;
DECLARE IMPORT,CoTaskMemFree(int pidl);
DECLARE IMPORT,ZeroMemory ALIAS RtlZeroMemory(pData as POINTER,length as INT);
declare import,SHParseDisplayName(WSTRING pszName,UINT *pbc,UINT *ppidl,UINT sfgaoIn,UINT *psfgaoOut),INT;
declare import,SHGetSpecialFolderLocation(UINT hwnd,int nFoloder,UINT *ppidl),int;
/* subroutine to open the system folder browser */
SUB GetFolder(UINT hwnd,string title),STRING
{
DSTRING path[260];
BROWSEINFO bi;
UINT lpIDList;
UINT pRoot,pTemp;
//initialize variables
path[0] = 0;
ZeroMemory(bi,LEN(bi));
//for Windows XP and above we can use SHParseDisplayName which can take a file path
//such as "c:\\progs" or a CLSID. The CLSID being used is for the My Computer folder.
SHParseDisplayName(s2w("::{20d04fe0-3aea-1069-a2d8-08002b30309d}"),NULL,pRoot,0,pTemp);
//for all Windows version this gets the pidl of the My Computer folder.
//So if you are targeting Windows 9x and above use this instead
//SHGetSpecialFolderLocation(null,0x0011,pRoot);
bi.pidlRoot = pRoot;
bi.hOwner = hwnd;
bi.pszDisplayName = path;
bi.lpszTitle = title;
bi.ulFlags = 0x00000041;
lpIDList = SHBrowseForFolder(bi);
if lpIDList <> 0
{
SHGetPathFromIDList(lpIDList,path);
CoTaskMemFree(lpIDList);
}
RETURN path;
}
/* other common CLSID's for use with SHParseDisplayName:
My Documents ::{450d8fba-ad25-11d0-98a8-0800361b1103}
Programs Folder ::{7be9d83c-a729-4d97-b5a7-1b7313c39e0a}
Start Menu Folder ::{48e7caab-b918-4e58-a94d-505519c795dc}
Temporary Internet Files ::{7bd29e00-76c1-11cf-9dd0-00a0c9034933}
My Network Places ::{208d2c60-3aea-1069-a2d7-08002b30309d}
*/
EDIT: Code updated to make the program terminate properly when compiled in Aurora.
The attached zip contains a source file in iwbasic and an exe file.
The exe demonstrates what I think he he is wanting to do.
It opens the folder browser
if you select a folder it closes the browser
(as part of demo) it immediately reopens browser with the last selected folder
you can keep repeating the process as long as desired
select CANCEL to exit demo loop.
demonstrates that all you have to do is save selection and reload it to make it work.
Thanks Larry :)
Hi,
still stuck on this one... i'm trying to translate larry's example but i want to return the string from the sub
i got invalid assigment for the line "lpIDList = SHBrowseForFolder(&bi);"
anyone see it ?
//Open Browse for folder dialog, return folder path
GLOBAL SUB BrowseFolders(CWindow *win, Pointer title, opt Pointer lpszFolder, opt INT newfolder , opt STRING root),STRING
{
BROWSEINFO bi;
//Make sure COM is active
CoInitialize(NULL);
RtlZeroMemory(&bi,LEN(bi));
//initialize variables
string returndir;
Unsigned int lpIDList;
//set the root folder
if root <> ""
{
bi.pidlRoot = GetPIDLfromPATH(win, s2w(root));
}
else
{
bi.pidlRoot = null;
}
bi.hwndOwner = win->GetHandle();
bi.lpszTitle = Title;
bi.lpfn = /**(BFFCALLBACK)*/&BrowseForFolderCallback;
bi.lParam = *(unsigned int)lpszFolder;
//newfolder button
IF (newfolder)
{
bi.ulFlags = 0x00000001|BIF_NEWDIALOGSTYLE;
}
ELSE
{
if !newfolder | newfolder = null
{
bi.ulFlags = 0x00000001;
}
}
lpIDList = SHBrowseForFolder(&bi);
if (lpIDList)
{
if (SHGetPathFromIDList(lpIDList,&returndir))
{
RETURN returndir + "\\";
}
CoTaskMemFree(lpIDList);
}
returndir = "";
RETURN returndir;
}
SUB BrowseForFolderCallback(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData), LPARAM
{
Unsigned Int dwStyle;
string szPath;
Select(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
//Remove the ? from the caption - optional
dwStyle = GetWindowLongA(hWnd, GWL_EXSTYLE);
IF (dwStyle & WS_EX_CONTEXTHELP)
{
SetWindowLongA(hWnd, GWL_EXSTYLE, dwStyle || WS_EX_CONTEXTHELP);
}
case BFFM_SELCHANGED:
if (SHGetPathFromIDList( lp ,szPath))
{
//Set the window text to the path
szPath= "\x0";
SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,szPath);
SetWindowTextA(hWnd, szPath);
}
Case BFFM_VALIDATEFAILED:
Return 1;
}
return 0;
}
here's is the file i use for my software...
if it can help... good sub in it too ;)
you have to add the file to your project and declare the extern at the top in the file you need the function
you have also to install windows headers that i found somewhere on the forum for aurora
//////////////////////////////////////////////////////////////
// subroutine to play with files
//////////////////////////////////////////////////////////////
//extern string BrowseFolders(CWindow *win, STRING title, opt Pointer lpszFolder, opt INT newfolder , opt STRING root);
//extern void StartApp(String AppPath,String Command, INT ShowConsole, INT Wait);
//extern string ParseFile(string pfull);
//extern string ExtractExtension(string Filepath);
//extern string GetFolderLocation(Cwindow *win,INT nFolder);
#ifndef FileAPI
#define FileAPI
#include "windows.inc"
#include "shlwapi.inc"
#include "shlobj.inc"
struct SHELLEXECUTEINFO,1
{
INT cbSize;
INT fMask;
INT hwnd;
Pointer lpVerb;
Pointer lpFile;
Pointer lpParameters;
Pointer lpDirectory;
int nShow;
INT hInstApp;
// Optional fields
INT lpIDList;
Pointer lpClass;
INT hkeyClass;
INT dwHotKey;
union {
INT hIcon;
INT hMonitor;
}
INT hProcess;
}
#define SEE_MASK_NOCLOSEPROCESS 0x40
#define WAIT_TIMEOUT 258
/*
struct BROWSEINFO
{
Unsigned INT hOwner;
Unsigned INT pidlRoot;
POINTER pszDisplayName;
POINTER lpszTitle;
Unsigned INT ulFlags;
Unsigned INT lpfn;
Unsigned INT lParam;
Unsigned INT iImage;
}
*/
#DEFINE BIF_RETURNONLYFSDIRS 0x0001
#DEFINE BIF_DONTGOBELOWDOMAIN 0x0002
#DEFINE BIF_STATUSTEXT 0x0004
#DEFINE BIF_RETURNFSANCESTORS 0x0008
#DEFINE BIF_EDITBOX 0x0010
#DEFINE BIF_VALIDATE 0x0020
#DEFINE BIF_NEWDIALOGSTYLE 0x0040
#DEFINE BIF_USENEWUI (BIF_NEWDIALOGSTYLE | BIF_EDITBOX)
#DEFINE BIF_BROWSEINCLUDEURLS 0x0080
#DEFINE BIF_UAHINT 0x0100
#DEFINE BIF_NONEWFOLDERBUTTON 0x0200
#DEFINE BIF_NOTRANSLATETARGETS 0x0400
#DEFINE BIF_BROWSEFORCOMPUTER 0x1000
#DEFINE BIF_BROWSEFORPRINTER 0x2000
#DEFINE BIF_BROWSEINCLUDEFILES 0x4000
#DEFINE BIF_SHAREABLE 0x8000
#DEFINE BFFM_INITIALIZED 1
#DEFINE BFFM_SELCHANGED 2
#DEFINE BFFM_VALIDATEFAILEDA 3
#DEFINE BFFM_VALIDATEFAILEDW 4
#DEFINE BFFM_IUNKNOWN 5
#DEFINE WM_USER 0x400
#DEFINE BFFM_SETSTATUSTEXTA (WM_USER + 100)
#DEFINE BFFM_ENABLEOK (WM_USER + 101)
#DEFINE BFFM_SETSELECTIONA (WM_USER + 102)
#DEFINE BFFM_SETSELECTIONW (WM_USER + 103)
#DEFINE BFFM_SETSTATUSTEXTW (WM_USER + 104)
#DEFINE BFFM_SETOKTEXT (WM_USER + 105)
#DEFINE BFFM_SETEXPANDED (WM_USER + 106)
DECLARE IMPORT,RtlZeroMemory(POINTER pData, unsigned INT length);
DECLARE IMPORT,GetPathFromIDList alias SHGetPathFromIDList(int pidl,string pszPath),INT;
#ENDIF
//Open Browse for folder dialog, return folder path
GLOBAL SUB BrowseFolders(CWindow *win, Pointer title, opt Pointer lpszFolder, opt INT newfolder , opt STRING root),STRING
{
BROWSEINFO bi;
//Make sure COM is active
CoInitialize(NULL);
RtlZeroMemory(&bi,LEN(bi));
//initialize variables
string returndir;
Unsigned int lpIDList;
//set the root folder
if root <> ""
{
bi.pidlRoot = GetPIDLfromPATH(win, s2w(root));
}
else
{
bi.pidlRoot = null;
}
bi.hwndOwner = win->GetHandle();
bi.lpszTitle = Title;
bi.lpfn = /**(BFFCALLBACK)*/&BrowseForFolderCallback;
bi.lParam = *(unsigned int)lpszFolder;
//newfolder button
IF (newfolder)
{
bi.ulFlags = 0x00000001|BIF_NEWDIALOGSTYLE;
}
ELSE
{
if !newfolder | newfolder = null
{
bi.ulFlags = 0x00000001;
}
}
lpIDList = SHBrowseForFolder(&bi);
if (lpIDList)
{
if (SHGetPathFromIDList(lpIDList,&returndir))
{
CoTaskMemFree(lpIDList);
RETURN returndir + "\\";
}
CoTaskMemFree(lpIDList);
}
returndir = "";
RETURN returndir;
}
SUB BrowseForFolderCallback(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData), LPARAM
{
Unsigned Int dwStyle;
string szPath;
Select(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
//Remove the ? from the caption - optional
dwStyle = GetWindowLongA(hWnd, GWL_EXSTYLE);
IF (dwStyle & WS_EX_CONTEXTHELP)
{
SetWindowLongA(hWnd, GWL_EXSTYLE, dwStyle || WS_EX_CONTEXTHELP);
}
case BFFM_SELCHANGED:
if (SHGetPathFromIDList( lp ,szPath))
{
//Set the window text to the path
szPath= "\x0";
//SendMessage(hwnd, BFFM_SETSTATUSTEXT,0,szPath);
SetWindowTextA(hWnd, szPath);
}
Case BFFM_VALIDATEFAILED:
Return 1;
}
return 0;
}
//get filename from full path
GLOBAL SUB ParseFile(string pfull),string
{
INT done = 0;
string ppath = pfull ;
IF (STRFIND(ppath,"\\")) | (STRFIND(ppath,"/"))
{
WHILE done = 0
{
IF(RIGHT$(ppath,1) <> "\\") & (RIGHT$(ppath,1) <> "/")
{
ppath = LEFT$(ppath,LEN(ppath)-1);
}
ELSE
{
done = 1 ;
}
}
string pfile = MID$(pfull,LEN(ppath)+1);
}
RETURN pfile;
}
//Start a Commandline Application
GLOBAL SUB StartApp(String AppPath,String Command, INT ShowConsole, INT Wait)
{
SHELLEXECUTEINFO info;
info.cbSize = 15 * 4;
info.fMask = SEE_MASK_NOCLOSEPROCESS;
info.hwnd = 0;
info.lpVerb = "Open";
info.lpFile = AppPath;
info.lpParameters = Command;
info.lpDirectory = "";
If (ShowConsole)
{
info.nShow = SWRestore;
}
Else
{
info.nShow = SWHide;
}
info.hInstApp = 0;
ShellExecuteExA(info);
if (wait)
{
do
{
Int ret = WaitForSingleObject(info.hprocess,0);
wait(1);
}until(ret <> WAIT_TIMEOUT);
}
return;
}
//return the extension from a path or filename (bypass multiple dot in string)
GLOBAL SUB ExtractExtension(string Filepath),string
{
string extension = "";
int pos = 0;
do
{
unsigned int Dotpos = STRFIND(Filepath, ".", pos+1);
pos = dotpos;
if dotpos <> 0
{
extension = STRRIGHT(Filepath, len(filepath)-DotPos);
}
}
until DotPos < 1;
return extension;
}
////////////////////////////////////////////////////////////////////////////////
// return the path to special folders
Global SUB GetFolderLocation(Cwindow *win,INT nFolder),STRING
{
STRING path;
INT pidl;
POINTER ppidl;
ppidl = pidl;
SHGetSpecialFolderLocation(win->m_hwnd,nFolder,ppidl);
GetPathFromIDList(pidl,path);
CoTaskMemFree(pidl);
RETURN path;
}
// Use by BrowseForFolder
Global SUB GetPIDLfromPATH(Cwindow *win, POINTER path),ITEMIDLIST*
{
return SHSimpleIDListFromPath(Path);
}
lpIDList = SHBrowseForFolder(bi);
and not
lpIDList = SHBrowseForFolder(&bi);