Does enybody know who the get the path of a spectial folder of windows from BlitzMax? I need to get the path of the program files folder, 'cause I'm making an installation program in BlitzMax as a separated complement to BLIde, but I need to read the 'programs folder' to get the 'default installation path'
Spetial folders
BlitzMax Forums/BlitzMax Programming/Spetial folders This is the API declaration I need:
Function SHGetSpecialFolderLocation:Long(hwndOwner:Long, nFolder:Long, pidl:ITEMIDLIST)
The fact is that I need to pass a structure called ITEMIDLIST which is formed by a INT and a BYTE. how can this be done in BlitzMax?
I would preffer no to use C code in the app I'm developing 'cause I want it to be open source and BlitzProgramers friendly.
Any suggestion?
Function SHGetSpecialFolderLocation:Long(hwndOwner:Long, nFolder:Long, pidl:ITEMIDLIST)
The fact is that I need to pass a structure called ITEMIDLIST which is formed by a INT and a BYTE. how can this be done in BlitzMax?
I would preffer no to use C code in the app I'm developing 'cause I want it to be open source and BlitzProgramers friendly.
Any suggestion?
Ziggy this code is not complete yet, the text comes out encrypted, so i am going now. But i will try and finish it tommorow, but if you want to try it out.
Good Luck.
'Folders Const CSIDL_PROGRAMS = 9 'Program Files 'Types Type SHITEMID Field cb:Long End Type Type ITEMIDLIST Field mkid:SHITEMID = New SHITEMID End Type 'WinApi Commands Extern "Win32" Function SHGetSpecialFolderLocation(hwndOwner, nFolder, pidl:ITEMIDLIST) Function SHGetPathFromIDList( pidl ,pszPath:String ) End Extern 'Print Print GetSpecialfolder() 'GetSpecialFolder Function Function GetSpecialfolder() Local idlist:ITEMIDLIST= New ITEMIDLIST r=SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, idlist) Local path$=Chr(256) r = SHGetPathFromIDList(idlist.mkid.cb, path$) dir$ = Trim(path$) Print dir$ End Function
Good Luck.
This is for Blitz3D/Blitz+, see if it works in BlitzMax
.lib "shell32.dll" SHGetSpecialFolderLocation%(hwndOwner%,nFolder%,pIdl*):"SHGetSpecialFolderLocation" SHGetPathFromIDList(pidList, lpBuffer$):"SHGetPathFromIDListA"
Const CSIDL_DESKTOP = $0000 ; <desktop> Const CSIDL_INTERNET = $0001 ; Internet Explorer (icon on desktop) Const CSIDL_PROGRAMS = $0002 ; Start Menu\Programs Const CSIDL_CONTROLS = $0003 ; My Computer\Control Panel Const CSIDL_PRINTERS = $0004 ; My Computer\Printers Const CSIDL_PERSONAL = $0005 ; My Documents Const CSIDL_FAVORITES = $0006 ; <user name>\Favorites Const CSIDL_STARTUP = $0007 ; Start Menu\Programs\Startup Const CSIDL_RECENT = $0008 ; <user name>\Recent Const CSIDL_SENDTO = $0009 ; <user name>\SendTo Const CSIDL_BITBUCKET = $000a ; <desktop>\Recycle Bin Const CSIDL_STARTMENU = $000b ; <user name>\Start Menu Const CSIDL_MYDOCUMENTS = $000c ; logical "My Documents" desktop icon Const CSIDL_MYMUSIC = $000d ; "My Music" folder Const CSIDL_MYVIDEO = $000e ; "My Videos" folder Const CSIDL_DESKTOPDIRECTORY = $0010 ; <user name>\Desktop Const CSIDL_DRIVES = $0011 ; My Computer Const CSIDL_NETWORK = $0012 ; Network Neighborhood Const CSIDL_NETHOOD = $0013 ; <user name>\nethood Const CSIDL_FONTS = $0014 ; windows\fonts Const CSIDL_TEMPLATES = $0015 Const CSIDL_COMMON_STARTMENU = $0016 ; All Users\Start Menu Const CSIDL_COMMON_PROGRAMS = $0017 ; All Users\Programs Const CSIDL_COMMON_STARTUP = $0018 ; All Users\Startup Const CSIDL_COMMON_DESKTOPDIRECTORY = $0019 ; All Users\Desktop Const CSIDL_APPDATA = $001a ; <user name>\Application Data Const CSIDL_PRINTHOOD = $001b ; <user name>\PrintHood Const CSIDL_LOCAL_APPDATA = $001c ; <user name>\Local Settings\Application Data (non roaming) Const CSIDL_ALTSTARTUP = $001d ; non localized startup Const CSIDL_COMMON_ALTSTARTUP = $001e ; non localized common startup Const CSIDL_COMMON_FAVORITES = $001f Const CSIDL_INTERNET_CACHE = $0020 Const CSIDL_COOKIES = $0021 Const CSIDL_HISTORY = $0022 Const CSIDL_COMMON_APPDATA = $0023 ; All Users\Application Data Const CSIDL_WINDOWS = $0024 ; GetWindowsDirectory() Const CSIDL_SYSTEM = $0025 ; GetSystemDirectory() Const CSIDL_PROGRAM_FILES = $0026 ; C:\Program Files Const CSIDL_MYPICTURES = $0027 ; C:\Program Files\My Pictures Const CSIDL_PROFILE = $0028 ; USERPROFILE Const CSIDL_SYSTEMX86 = $0029 ; x86 system directory on RISC Const CSIDL_PROGRAM_FILESX86 = $002a ; x86 C:\Program Files on RISC Const CSIDL_PROGRAM_FILES_COMMON = $002b ; C:\Program Files\Common Const CSIDL_PROGRAM_FILES_COMMONX86 = $002c ; x86 Program Files\Common on RISC Const CSIDL_COMMON_TEMPLATES = $002d ; All Users\Templates Const CSIDL_COMMON_DOCUMENTS = $002e ; All Users\Documents Const CSIDL_COMMON_ADMINTOOLS = $002f ; All Users\Start Menu\Programs\Administrative Tools Const CSIDL_ADMINTOOLS = $0030 ; <user name>\Start Menu\Programs\Administrative Tools Const CSIDL_CONNECTIONS = $0031 ; Network and Dial-up Connections Const CSIDL_COMMON_MUSIC = $0035 ; All Users\My Music Const CSIDL_COMMON_PICTURES = $0036 ; All Users\My Pictures Const CSIDL_COMMON_VIDEO = $0037 ; All Users\My Video Const CSIDL_RESOURCES = $0038 ; Resource Direcotry Function GetSpecialFolder$(folder_id) Local idl% = CreateBank (8) Local spath$ = String(0 ,260 ) Local nPos If SHGetSpecialFolderLocation(0,folder_id,idl) = 0 SHGetPathFromIDList PeekInt( IDL,0), spath$ nPos = Instr( spath, Chr$(0)) If nPos > 0 Then spath = Left(spath, nPos - 1) End If spath = spath + "" EndIf FreeBank idl Return spath End Function
No matter what code i use for this i keep getting this error
Unhandled Exepcetion: "Unhandled Memory Exepcetion Error"
Unhandled Exepcetion: "Unhandled Memory Exepcetion Error"
I think the TYPE SHITEMID is formed by a LONG followed by a INT. in addition, I'm not sure if you haved to pass the TYPE or a pointer to the TYPE. I've been testing it, and it seems the code is passing a wrong buffer addres, that's should be the reason why we get garbage, or errors.
Is there any documentation about using windows API in Blitzmax?
Here is a working BlitzMax version. I'm sure it can be "Maxified" a bit more to take out legacy commands.
'WinApi Commands Extern "Win32" Function SHGetSpecialFolderLocation(hwndOwner, nFolder, pIdl:Byte Ptr) Function SHGetPathFromIDList( pidList ,lpBuffer:Byte Ptr) End Extern Print GetSpecialFolder(CSIDL_PROGRAMS) Function GetSpecialFolder:String(folder_id) Local idl% = CreateBank (8) Local pathbank% = CreateBank (260) Local n% Local sp$ If SHGetSpecialFolderLocation(0,folder_id,BankBuf(idl)) = 0 SHGetPathFromIDList PeekInt( idl,0), BankBuf(pathbank) For n= 0 To 259 sp$ = sp$ + Chr(PeekByte(pathbank,n)) Next EndIf Return Trim(sp$) + "" End Function
Thanks peter! It was the address of the buffer... ufff, well done :)
Peter, your code isn't taking in cosideration the 0 end string returned by the API.
If function works fine like this:
If function works fine like this:
Function GetSpecialFolder:String(folder_id) Local idl:TBank = CreateBank (8) Local pathbank:TBank = CreateBank (260) Local n% Local sp$ If SHGetSpecialFolderLocation(0,folder_id,BankBuf(idl)) = 0 SHGetPathFromIDList PeekInt( idl,0), BankBuf(pathbank) For n= 0 To 259 local BufByte:byte =PeekByte(pathbank,n) if bufbyte <>0 then sp$ = sp$ + Chr(bufbyte) else exit endif Next EndIf return (trim(sp$) + "") End Function
You are right. (but wont trim$() fix that ? )
no, trim just removes chr(32) with is blank spaces, not chr(0) with means end of string in a C string. and keep in mind that after the chr(0) char, there will be garbage, so you have to read the buffer only untill you find a byte 0.
As instance:
This code will output: Hello this is garbageEND
As instance:
Local MyVar:String = "Hello" + chr(0) + "this is garbage " Print trim(MyVar) + "END"
This code will output: Hello this is garbageEND
Ok, but I still thought that banks where initialized with 0's (resulting in a terminated string)
I'm not arguing, you way is correct, but I'd like to know.
BTW: Do you know how to trim() the BlitzMax way?
I'm not arguing, you way is correct, but I'd like to know.
BTW: Do you know how to trim() the BlitzMax way?
You're right :), and you code has helped me A LOT!
but you have to considerate that the buffer is initialized to zero, but you pass a pointer when calling the api, and this pointer can be changed to any other memory address by the API (this new address can be a different one, not initialized to zero). in fact, I did get garbage sometimes untill making the change mentioned. Anyway, you don't need to do this if you're not using API, just your own functions, or if you know the buffer won't be modified by the API.
What do you mean how to trim() the BlitzMax way?
but you have to considerate that the buffer is initialized to zero, but you pass a pointer when calling the api, and this pointer can be changed to any other memory address by the API (this new address can be a different one, not initialized to zero). in fact, I did get garbage sometimes untill making the change mentioned. Anyway, you don't need to do this if you're not using API, just your own functions, or if you know the buffer won't be modified by the API.
What do you mean how to trim() the BlitzMax way?
"and this pointer can be changed to any other memory address by the API", - Well no, that would make it unsuable, - but the API can copy any data it wants into the buffer (the bank) that the pointer is pointing to.
Abaut Trim(), the docs say that is's only there for backwards compability, and that you should use "string slicing" or something like that. The docs does not link to or show the new way though...
Abaut Trim(), the docs say that is's only there for backwards compability, and that you should use "string slicing" or something like that. The docs does not link to or show the new way though...
good to know. :) Anyway, BlitzMax doesn't use zero terminated strings (as long as I know). It uses strings in format pointer +lenght, so if there are zeros in the buffer, there will be zeros in the string, even if you trim it. so, the better choice, trim and stop reading when a zero occurs. I'm not shure if the method ToCString of strings will make a sort of zero based trim over the function, or just creates a zero based string and a pointer to it. I've passed ToCString to apis that were specting a CString, but in the declaration of the API, I have had to declare it as a INT... don't ask me why, but it works fine.
Learning from the "string to buffer" topic, here is a new BlitzMax version that seems to be ok.
'WinApi Commands Extern "Win32" Function SHGetSpecialFolderLocation(hwndOwner, nFolder, pIdl:Byte Ptr) Function SHGetPathFromIDList( pidList ,lpBuffer:Byte Ptr) End Extern Print GetSpecialFolder(CSIDL_PROGRAMS) Function GetSpecialFolder:String(folder_id) Local idl% = CreateBank (8) Local pathbank:TBank = CreateBank (260) If SHGetSpecialFolderLocation(0,folder_id,BankBuf(idl)) = 0 SHGetPathFromIDList PeekInt( idl,0), BankBuf(pathbank) Return String.FromCString(pathbank.Buf()) + "" EndIf End Function
Great! Easily solved :)