How does one convert LPTSTR to LPCTSTR? - c++

I need to convert:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
lpstrFileTitle
Type: LPTSTR
The file name and extension (without path information) of the selected file. This member can be NULL.
Even though in MSVC++ 2012 Express it says its LPSTR.
To
http://msdn.microsoft.com/en-us/library/windows/desktop/bb172802(v=vs.85).aspx
pSrcFile [in]
Type: LPCTSTR
Pointer to a string that specifies the filename. If the compiler settings require Unicode, the data type LPCTSTR resolves to LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See Remarks.
I would very much appreciate this. :)
char szFileName[MAX_PATH] = {0};
char szFileTitleName[MAX_PATH] = {0};
HRESULT hr = S_OK;
RtlZeroMemory(&gc.ofn, sizeof(gc.ofn));
gc.ofn.lStructSize = sizeof(gc.ofn);
gc.ofn.hwndOwner = hWnd;
gc.ofn.lpstrFilter = "All Image Files\0" "*.bmp;*.dib;*.wdp;*.mdp;*.hdp;*.gif;*.png;*.jpg;*.jpeg;*.tif;*.ico\0"
"Windows Bitmap\0" "*.bmp;*.dib\0"
"High Definition Photo\0" "*.wdp;*.mdp;*.hdp\0"
"Graphics Interchange Format\0" "*.gif\0"
"Portable Network Graphics\0" "*.png\0"
"JPEG File Interchange Format\0" "*.jpg;*.jpeg\0"
"Tiff File\0" "*.tif\0"
"Icon\0" "*.ico\0"
"All Files\0" "*.*\0"
"\0";
gc.ofn.nMaxFileTitle = MAX_PATH;
gc.ofn.lpstrFileTitle = gc.szFileTitleName; // its a char
gc.ofn.lpstrFile = szFileName;
gc.ofn.nMaxFile = MAX_PATH;
gc.ofn.lpstrTitle = "Open Image";
gc.ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if(GetOpenFileName(&gc.ofn)) {
gc.render_on = true;
}
.
D3DXCreateTextureFromFileEx (d3dDevice, gc.szFileTitleName , D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
colorkey, &init_map->image_info, NULL, &init_map->texture_buffer)
This will have a blank image. I have tested this with a messagebox right after GetOpenFile, and it returns great.
MessageBoxA ( NULL , gc.ofn.lpstrFileTitle , "" , 0 );
But before the D3DXCreateTextureFromFileEx, its messed up.
Just storing the the char into gc.szFileTitleName. No idea why the other way was going out of scope ...

LPCTSTR is just a const version of LPTSTR. That type of conversion is a standard conversion, so you shouldn't need to do anything explicitly to get what you want. Your error must be somewhere else.
Unless you are somehow compiling a piece of your code with UNICODE set and some without it...

GetOpenFileName(), D3DXCreateTextureFromFileEx(), and MessageBox() all deal with TCHAR-based strings, but you are not actually utilizing TCHAR in your code. Try this instead:
TCHAR szFileName[MAX_PATH] = {0};
TCHAR szFileTitleName[MAX_PATH] = {0};
HRESULT hr = S_OK;
RtlZeroMemory(&gc.ofn, sizeof(gc.ofn));
gc.ofn.lStructSize = sizeof(gc.ofn);
gc.ofn.hwndOwner = hWnd;
gc.ofn.lpstrFilter = TEXT("All Image Files\0") TEXT("*.bmp;*.dib;*.wdp;*.mdp;*.hdp;*.gif;*.png;*.jpg;*.jpeg;*.tif;*.ico\0")
TEXT("Windows Bitmap\0") TEXT("*.bmp;*.dib\0")
TEXT("High Definition Photo\0") TEXT("*.wdp;*.mdp;*.hdp\0")
TEXT("Graphics Interchange Format\0") TEXT("*.gif\0")
TEXT("Portable Network Graphics\0") TEXT("*.png\0")
TEXT("JPEG File Interchange Format\0") TEXT("*.jpg;*.jpeg\0")
TEXT("Tiff File\0") TEXT("*.tif\0")
TEXT("Icon\0") TEXT("*.ico\0")
TEXT("All Files\0") TEXT("*.*\0")
TEXT("\0");
gc.ofn.nMaxFileTitle = MAX_PATH;
gc.ofn.lpstrFileTitle = gc.szFileTitleName;
gc.ofn.lpstrFile = szFileName;
gc.ofn.nMaxFile = MAX_PATH;
gc.ofn.lpstrTitle = TEXT("Open Image");
gc.ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if(GetOpenFileName(&gc.ofn)) {
gc.render_on = true;
}
.
D3DXCreateTextureFromFileEx (d3dDevice, gc.szFileTitleName , D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, colorkey, &init_map->image_info, NULL, &init_map->texture_buffer)
.
MessageBox(NULL, gc.ofn.lpstrFileTitle, TEXT(""), 0);

Related

C++ Save Bitmap file

I'm working on an application that captures the user's screen and saved in bitmap.
I'm having problems when creating the file
HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
I am getting the following error in filename:
argument of type "LPCSTR" is incompatible with parameter of type "LPCWSTR"
below is the code:
#include <olectl.h>
bool saveBitmap(LPCSTR filename, HBITMAP bmp, HPALETTE pal)
{
bool result = false;
PICTDESC pd;
pd.cbSizeofstruct = sizeof(PICTDESC);
pd.picType = PICTYPE_BITMAP;
pd.bmp.hbitmap = bmp;
pd.bmp.hpal = pal;
LPPICTURE picture;
HRESULT res = OleCreatePictureIndirect(&pd, IID_IPicture, false,
reinterpret_cast<void**>(&picture));
if (!SUCCEEDED(res))
return false;
LPSTREAM stream;
res = CreateStreamOnHGlobal(0, true, &stream);
if (!SUCCEEDED(res))
{
picture->Release();
return false;
}
LONG bytes_streamed;
res = picture->SaveAsFile(stream, true, &bytes_streamed);
HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (!SUCCEEDED(res) || !file)
{
stream->Release();
picture->Release();
return false;
}
HGLOBAL mem = 0;
GetHGlobalFromStream(stream, &mem);
LPVOID data = GlobalLock(mem);
DWORD bytes_written;
result = !!WriteFile(file, data, bytes_streamed, &bytes_written, 0);
result &= (bytes_written == static_cast<DWORD>(bytes_streamed));
GlobalUnlock(mem);
CloseHandle(file);
stream->Release();
picture->Release();
return result;
}
void CaptureScreen()
{
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
HWND hDesktopWnd = GetDesktopWindow();
HDC hDesktopDC = GetDC(hDesktopWnd);
HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC,
nScreenWidth, nScreenHeight);
SelectObject(hCaptureDC, hCaptureBitmap);
BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight,
hDesktopDC, 0, 0, SRCCOPY | CAPTUREBLT);
LPCSTR fname = "c:\\Users\\hom3r\\Downloads\\image.bmp";
HPALETTE hpal = NULL;
saveBitmap(fname, hCaptureBitmap, hpal);
ReleaseDC(hDesktopWnd, hDesktopDC);
DeleteDC(hCaptureDC);
DeleteObject(hCaptureBitmap);
}
You have UNICODE defined in your project, meaning that you are using the wide-character version of the Windows API. LPC[W]STR is Long Pointer to C [Wide] String.
You can either remove the UNICODE define to use the 8-bit ASCII interface, or better, use wide characters throughout your application.
You have to convert file_name from LPCSTR to LPCWSTR using ATL (Active Template Library).
Hence, replace
HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
with
HANDLE file = CreateFile(A2W(filename), GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
A2W (ANSI to wide) is defined in <atlbase.h>.
Try to use TCHAR or wchar_t type. See similar questions at StackOverflow and MSDN.net

Windows API: Unicode variable metamorphasis

I created a function that reads from a file, and fills a data structure based on that file. The function works well alone, so I decided to build an GUI around its function. I have a function that calls the Windows GUI and returns a LPOPENFILENAME structure, to which I copy the LPOPENFILENAME.lpstrFile over to a LPCWSTR.
Next, I initialize a wstring to hold the LPCWSTR value. Here's where things get a bit strange.
LPCWSTR File = FileOpenOBJ(hWnd, hInst).lpstrFile;
MessageBox(hWnd, File, L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
wstring Fileformatting(File);
Which does a runtime display of something like this:
Which is fine, since LPCWSTR File now holds the value from the LPOPENFILENAME structure, but when a wstring is initialized with the value of File, both variables seemingly go out of range or pull from a pointer location that is no longer accurate and their values appear to be something like:
The goal is to hold the file name in a string so that I can (PHP-like) escape the "\" characters to insert into my function. As such:
C:\Users\InfinityMachine\Documents\Test.obj -> C:\\Users\\InfinityMachine\\Documents\\Test.obj
In which I:
while (Fileformatting.find(L"\\") != wstring::npos){
Fileformatting.replace(Fileformatting.find(L"\\"), 2, L"\\\\");
}
How can I get the correct value of LPCWSTR File into wstring Fileformatting?
You have probably initialized lpstrFile to a variable that is local to the FileOpenOBJ function, and when that function returns you get undefined behavior when you try to use it. It appears to work the first time because the stack hasn't been exercised yet, but that changes when you make the call to MessageBox.
Moving the initialization of the wstring would mask the problem but wouldn't fix it, you're still relying on undefined behavior. The fix would be to have the structure contain a pointer that doesn't go out of scope.
In addition to what others have said about dangling pointers and such, for this kind of situation, you are better off simply having FileOpenOBJ() return a wstring instead of a copy of the original OPENFILENAME struct:
wstring FileOpenOBJ(HWND hWnd, HINSTANCE hInst)
{
WCHAR szFileName[MAX_PATH+1] = {0};
OPENFILENAME ofn = {0};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = hInst;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
...
GetOpenFileName(&ofn);
return szFileName;
}
wstring File = FileOpenOBJ(hWnd, hInst);
MessageBoxW(hWnd, File.c_str(), L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
If you need to return other values from the OPENFILENAME, you should define your own struct to hold what you need, for example:
struct FileInfo
{
wstring FullPath;
wstring FileName;
wstring Ext;
int FilterIndex;
...
};
FileInfo FileOpenOBJ(HWND hWnd, HINSTANCE hInst)
{
WCHAR szFileName[MAX_PATH+1] = {0};
OPENFILENAME ofn = {0};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = hInst;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
...
GetOpenFileName(&ofn);
FileInfo fi;
fi.FullPath = szFileName;
fi.FileName = &szFileName[ofn.nFileOffset];
if (ofn.nFileExtension != 0)
fi.Ext = &szFileName[ofn.nFileExtension];
fi.FilterIndex = ofn.nFilterIndex;
...
return fi;
}
FileInfo fi = FileOpenOBJ(hWnd, hInst);
MessageBoxW(hWnd, fi.FullPath.c_str(), L"Warning 1: File/lpstrFile assignment ", MB_ICONEXCLAMATION | MB_OK);
Don't expose direct access to the OPENFILENAME struct. It should be left as a private implementation detail of FileOpenOBJ()'s internal logic.

WriteFile writes incorrectly

I'm trying to copy a file from resources to %localappdata%. I've something like this:
HINSTANCE hInstance = GetModuleHandle(NULL);
HANDLE hFile = INVALID_HANDLE_VALUE;
HRSRC hrsrc = FindResource(hInstance, MAKEINTRESOURCE(MSIE), RT_RCDATA);
HGLOBAL exeRes = LoadResource(hInstance, hrsrc);
DWORD size = SizeofResource(hInstance, hrsrc);
TCHAR szPath[MAX_PATH];
HANDLE hfile;
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) {
PathAppend(szPath, TEXT("test.exe"));
hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
LPVOID exePtr = LockResource(hrsrc);
DWORD exeWritten = 0;
BOOL writeResult = WriteFile(hFile, exePtr, size, &exeWritten, NULL);
cout << GetLastError() << endl;
BOOL closed = CloseHandle(hFile);
system("PAUSE");
return 0;
I'm able to locate the HRSRC and confirm the size using SizeofResource() just fine. CreateFile is in fact creating the file and returning the handle. GetLastError() reports that there are no errors. The amount of bytes written to disk is exactly right.
The output exe however is corrupted (the version of this file is incompatible with the version of Windows... blah blah) - it's lost its icon and everything. Looking at the original and the output file side-by-side in a hex editor it appears there's random data at the start of file.
What am I missing here?
Your LockResource is not correct. It should be passed the HGLOBAL exeRes you loaded previously.
LockResource(hrsrc);
should be
LockResource(exeRes);
From the MS documentation on LockResource() :
Do not try to lock a resource by using the handle returned by the FindResource or FindResourceEx function. Such a handle points to random data.
And as a side note, you may want to try cleaning up that loaded-and-locked resource when you're through with it.

Converting a PIDL to file path with SHGetPathFromIDList

My application receives a PIDL as a string:
QString pidl = "::{20D04FE1-3AEA-1069-A2D8-08002B30309B}";
In this case it corresponds to My Computer. I need to convert it to My Computer.
Theres a WINAPI function SHGetPathFromIDList which requires the LPCITEMIDLIST as the first parameter and converts it to a string.
How can I build that LPCITEMIDLIST?
UPDATE
This is what I got so far:
LPCWSTR csPath = (LPCWSTR)"::{20D04FE1-3AEA-1069-A2D8-08002B30309B}";
LPITEMIDLIST stId = 0;
SFGAOF stSFGAOFIn = 0;
SFGAOF stSFGAOFOut = 0;
if(!FAILED(SHParseDisplayName(csPath, 0, stId, stSFGAOFIn, &stSFGAOFOut)))
msgBox("not failed")
Unfortunately this code crashes.
Your code crashes because you are not setting up the 1st and 3rd parameters of SHParseDisplayName() correctly. Try this instead:
LPCWSTR csPath = L"::{20D04FE1-3AEA-1069-A2D8-08002B30309B}";
PIDLIST_ABSOLUTE stId = NULL;
SFGAOF stSFGAOFIn = 0;
SFGAOF stSFGAOFOut = 0;
if (!FAILED(SHParseDisplayName(csPath, NULL, &stId, stSFGAOFIn, &stSFGAOFOut)))
msgBox("not failed")
The function you need is not SHGetPathFromIDList, because there is no path for "My Computer".
To convert your QString pidl to an PIDLIST_ABSOLUTE you need to use SHParseDisplayName.
To convert the PIDLIST_ABSOLUTE to a localised string like "My Computer" you need SHGetNameFromIDList.
I think may be:
SHParseDisplayName(csPath, 0, &stId, stSFGAOFIn, &stSFGAOFOut)
Declaration of SHParseDisplayName from MSDN:
HRESULT SHParseDisplayName(
__in LPCWSTR pszName,
__in_opt IBindCtx *pbc,
__out PIDLIST_ABSOLUTE *ppidl,
__in SFGAOF sfgaoIn,
__out_opt SFGAOF *psfgaoOut
);

Very strange GetOpenFileName problem

I seem to be having a very strange problem with GetOpenFileName.
It errors for no apparent reason, however, if I call CommDlgExtendedError() in the error check, the error never happens in the first place.
Here is my code:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
OPENFILENAME fm;
char flnm[MAX_PATH];
ZeroMemory(&fm, sizeof(fm));
fm.lStructSize = sizeof(OPENFILENAME);
fm.hwndOwner = NULL;
fm.lpstrFilter = "Text Files (*.txt)\0*.txt\0";
fm.lpstrFile = flnm;
fm.nMaxFile = MAX_PATH;
fm.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
fm.lpstrDefExt = "";
if(!GetOpenFileNameA(&fm))
{
MessageBoxA(NULL, "failed! :(", NULL, NULL);
}
return 0;
}
What's shown? "failed! :("
If I remove this check, I do see a file dialog. However, it doesn't work, and the filename box is pre-filled with random junk.
If I change to:
if(!GetOpenFileNameA(&fm))
{
DWORD dwErr = CommDlgExtendedError();
MessageBoxA(NULL, "failed! :(", NULL, NULL);
}
"failed! :(" is NOT shown. The file dialog shows and performs without issue.
What is going on!?!?
OPENFILENAME fm;
char flnm[MAX_PATH]; // nobody initialized me ...
ZeroMemory(&fm, sizeof(fm));
fm.lStructSize = sizeof(OPENFILENAME);
fm.hwndOwner = NULL;
fm.lpstrFilter = "Text Files (*.txt)\0*.txt\0";
fm.lpstrFile = flnm; // ... who knows what I am?
fm.nMaxFile = MAX_PATH;
fm.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
fm.lpstrDefExt = "";
if(!GetOpenFileNameA(&fm))
{
MessageBoxA(NULL, "failed! :(", NULL, NULL);
}
The documentation for lpstrFile states:
The file name used to initialize the File Name edit control. The first character of this buffer must be NULL if initialization is not necessary. When the GetOpenFileName or GetSaveFileName function returns successfully, this buffer contains the drive designator, path, file name, and extension of the selected file.
You are not initializing flnm and therein lies the problem. You can solve the problem by writing flnm[0] = '\0' before you call GetOpenFileName.