MFC CString Format gives weird behaviour - c++

I am having a weird problem with CString I have the following code which gives an unexpected result:
CString sourcePath = _T("C:\\some\\path\\file.ext");
CString log;
log.Format(_T("Path = %s"), sourcePath);
the result string shows Path = (null).
I am not sure what is going on under the hood there, I have tried casting the sourcePath to an LPCTSTR and got a valid pointer and when viewing the content of that memory address in the memory view window of MSVC everything seems valid.
this annoys me as I have tried the same method in previous projects and it worked pretty well.
Thanks.
P.S. Please, before people start commenting here asking about what is a CString, as it happened in an earlier post of mine, please check here first: MSDN CString
Edit: sorry about the slash thingy.. and yes the original code does have double slashes..

As your MSDN CString link also mentions, you cannot pass the CString itself to the Format function.
Use:
log.Format(_T("Path = %s"), sourcePath.GetString());

The string "C:\some\path\file.ext" should be "C:\some\path\file.ext" - otherwise you will read control characters (\s \p \f) instead.

Depending on the MFC version and whether your app is built for win32 or x64, you might have to cast the CString:
log.Format(_T("Path = %s"), (LPCTSTR)sourcePath);

There is a problem in your sourcePath initialization.
The character \ is a special character in C/C++. You should replace it with \ (double )
So the first line of code should be: CString sourcePath = _T("C:\\some\\path\\file.ext");
Hope this helps.

Related

CString results in ? when trying to assign _variant_t.bstrVal which contains russian chars

I am working on a desktop application.
I am facing this problem.
As you can see in the screenshot when this code runs it assigns Russian string to CString but its value gets corrupted.
CString csField = vField.bstrVal;
The bstrVal contains Створное O^Л.
When I assign it to CString it becomes ??s.
*Remember: When this problem occurs, first check the current culture or locale.
The answer to the problem is:
There was a line in my code which was setting current culture to
Invariant culture.
The strange thing I could not understand is when I get the current locale by setLocale(LC_ALL, NULL) it was returning the same thing irrespective of my current culture was Russian or Invariant.
To solve this problem I removed that code and now it's working fine.
//Thread::CurrentThread->CurrentCulture = gcnew CultureInfo("");

Why is OPENFILENAME lpstrFileTitle param a LPSTR and not LPCSTR?

I am creating some file open dialog and stumbled across something inconsistent in the WinAPI (hehe).
I fully understand why lpstrFile is a LPSTR as the path is written into this variable.
Fine, but why is lpstrFileTitle not LPCSTR? I've read the docs at MSDN and googled around and found no satisfying explanation as it doesn't look like it is modified in any way.
Is this a compatibility remnant or something?
Causes annoying workarounds when passing a std::string as I cannot use c_str() and resort to &str[0].
lpstrFileTitle is also an output buffer. It contains the name and extension without path information of the selected file.
Related side-note: You must set lpstrFileTitle to a valid buffer for non-Unicode builds.
The docs for OPENFILENAME state that field is ignored if the pointer is null. However, since at least VS2008 the MFC CFileDialog code has included this code:
VC\atlmfc\src\mfc\dlgfile.cpp
void CFileDialog::UpdateOFNFromShellDialog()
{
...
#ifdef UNICODE
...
#else
::WideCharToMultiByte(CP_ACP, 0, wcPathName + offset,-1, m_ofn.lpstrFileTitle, m_ofn.nMaxFileTitle, NULL, NULL);
m_ofn.lpstrFileTitle[m_ofn.nMaxFileTitle - 1] = _T('\0');
#endif
...
The Unicode support correctly handles a NULL lpstrFileTitle and the WideCharToMultiByte basically does nothing. However, the added code to safely terminate the buffer does not check for a null pointer or a nMaxFileTitle==0. The result is an access violation.
Better of course to kill multibyte apps, but if you must compile that way, you have to supply that buffer.

Having trouble converting from string to LPCTSTR

I am trying to put some text in a Static Text widget, like this:
m_StartupTime.SetWindowText(someStringVariable);
And get an error:
'CWnd::SetWindowTextA' : cannot convert parameter 1 from 'std::string' to 'LPCTSTR'
I have tried using the c.str() method, but when I do, the program compiles fine, but crashes at run-time, throwing an error:
So I'm figuring out if the problem is related to the conversion, or anything other than that?
Using CString doesn't solve the problem, and I have tried switching from Unicode charcter set to Multi-Byte, with no success. Oh, I am developing in MFC.
EDIT: Found a solution! I used the CString class.
string a = "smth";
CString str(a.c_str());
The Assert dialog shows you where the assertion is happening: file winocc.cpp, line 246.
Looking through the code, this is the line in that file:
ENSURE(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL));
It seems your assertion has nothing to do with the string, but the control isn't there (yet?), i.e. the control window isn't valid or does not exist.
CA2T str( someStringVariable.c_str() );
m_StartupTime.SetWindowText(str);
Assuming that someStringVariable has std::string type. Include AtlBase.h to compile this.

CEdit::GetLine() windows 7

I have the following segment of code where m_edit is a CEdit control:
TCHAR lpsz[MAX_PATH+1];
// get the edit box text
m_edit.GetLine(0,lpsz, MAX_PATH);
This works perfectly on computers running Windows XP and earlier. I have not tested this in Vista, but on Windows 7, lpsz gets junk unicode characters inserted into it (as well as the actual text sometimes). Any idea as to what is going on here?
Since you're using MFC, why aren't you taking advantage of its CString class? That's one of the reasons many programmers were drawn to MFC, because it makes working with strings so much easier.
For example, you could simply write:
int len = m_edit.LineLength(m_edit.LineIndex(0));
CString path;
LPTSTR p = path.GetBuffer(len);
m_edit.GetLine(0, p, len);
path.ReleaseBuffer();
(The above code is tested to work fine on Windows 7.)
Note that the copied line does not contain a null-termination character (see the "Remarks" section in the documentation). That could explain the nonsense characters you're seeing in later versions of Windows.
It's not null terminated. You need to do this:
int count = m_edit.GetLine(0, lpsz, MAX_PATH);
lpsz[count] = 0;

How to delete folder into recycle bin

I am programing under C++, MFC, windows.
I want to delete a folder into recycle bin.
How can I do this?
CString filePath = directorytoBeDeletePath;
TCHAR ToBuf[MAX_PATH + 10];
TCHAR FromBuf[MAX_PATH + 10];
ZeroMemory(ToBuf, sizeof(ToBuf));
ZeroMemory(FromBuf, sizeof(FromBuf));
lstrcpy(FromBuf, filePath);
SHFILEOPSTRUCT FileOp;
FileOp.hwnd = NULL
FileOp.wFunc=FO_DELETE;
FileOp.pFrom=FromBuf;
FileOp.pTo = NULL;
FileOp.fFlags=FOF_ALLOWUNDO|FOF_NOCONFIRMATION;
FileOp.hNameMappings=NULL;
bRet=SHFileOperation(&FileOp);
Any thing wrong with the code above?
It always failed.
I found the problem:
filePath should be : "c:\abc" not "c:\abc\"
The return value from SHFileOperation is an int, and should specify the error code. What do you get?
i know it is not the right way but if you cant find a solution you can try this..
download file nircmd.exe or another exe that can empty recycle bin.
then you call these functions by system("nircmd.exe emptybin")
You have found a solution that works, however it's only by accident. The actual problem here is that the pFrom parameter is in a special format. According to the MSDN docs for SHFILEOPTS, it stores a list of file paths, each one null-terminated, and an extra null after the last one.
In your case this happens to work because the FromBuf array is longer than the filename and all the entries are initialised to zero. The more general solution is to create a buffer that is long enough for the filename and then add two nul characters after it. Note that Windows filenames can be longer than _MAX_PATH, eg see https://learn.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation