Spetial folders
BlitzMax Forums/BlitzMax Programming/Spetial folders
| ||
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' |
| ||
shell32 http://www.mentalis.org/apilist/SHGetSpecialFolderLocation.shtml |
| ||
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? |
| ||
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.'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" |
| ||
No matter what code i use for this i keep getting this 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: 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: 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? |
| ||
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? |
| ||
"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... |
| ||
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 :) |