Reputation: 1104
UPDATED: after Cody Gray's reply
I want to find a way to save a file to a desktop. Since every user has different user name, I found following code will help me find the path to someone else’s desktop. But how can I save the following to desktop?
#include <iostream>
#include <windows.h>
#include <fstream>
#include <direct.h>
#include <shlobj.h>
using namespace std;
int main ()
{
ofstream file;
TCHAR appData[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_DESKTOPDIRECTORY | CSIDL_FLAG_CREATE,
NULL,
SHGFP_TYPE_CURRENT,
appData)))
wcout << appData << endl; //This will printout the desktop path correctly, but
file.open(appData +"/.txt"); //how can I open the desktop path here??
file<<"hello\n";
file.close();
return 0;
}
Microsoft Visual Studio 2010, Windows 7, C++ console
Upvotes: 2
Views: 8903
Reputation: 1
Böyle Olması Gerekiyor
TCHAR path[_MAX_PATH] = _T("");
if (SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_DESKTOP
0,
NULL,
path)))
strcat(path,"\\Test.txt");
ofstream out;
out.open(path);
Upvotes: 0
Reputation: 244722
The problem is that you're compiling the application with UNICODE
defined (as you well should be), meaning that C-style strings are not stored in char
arrays (as they would be for ANSI strings), but rather wchar_t
arrays.
That's why you can't convert from char*
to LPWSTR
(which is typedef
ed in the Windows headers as wchar_t*
).
The solution is to change the type of your string buffer. You can either use wchar_t
explicitly:
wchar_t appData[MAX_PATH];
or take advantage of the TCHAR
macro that will automatically #define
to the appropriate type, depending on whether you compile with UNICODE
defined:
TCHAR appData[MAX_PATH];
That's not the only problem though. A couple of other things to note:
You should strongly consider using the TRUE
and FALSE
symbols instead of the literals 0
and 1
when writing Win32 code. When the function's documentation indicates that it accepts values of type BOOL
, take advantage of the symbols that are already defined for that type. It makes your code much clearer and easier to read, even if you can reasonably assume that these symbols will never change their definitions in the headers.
CSIDL_LOCAL_APPDATA
is not the correct constant to use if you want the desktop folder. That will return a folder that is associated with the current user and intended to be used by applications for storing data that should not roam with the user (it should be stored and available on the local machine only). All things considered, this is probably a better choice than the desktop anyway, as apps should really have a darn good reason before spilling junk out on a user's desktop.
If you need the data to roam with the application, you should use CSIDL_APPDATA
instead. I provide a brief run-down of what all these different folders are, what they mean, and when you should use them in my answer here.
Do note, however, that the SHGetSpecialFolderPath
function limits you to a particular subset of the special folders. Which brings me to...
As of Windows 2000 (and I honestly don't think there's anyone out there still writing apps targeting versions of Windows prior to 2000), the SHGetSpecialFolderPath
function is obsolete.
The preferred replacement for those targeting Windows 2000 and XP is SHGetFolderPath
, which you would use in a similar fashion:
TCHAR appData[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE,
NULL,
SHGFP_TYPE_CURRENT,
appData)))
{
wcout << appData << endl;
}
And the newest member of the family is SHGetKnownFolderPath
for new applications targeting only Windows Vista and later.
Upvotes: 6