How to use a variable inside a _T wrapper? - c++

I want to make the hostname part of this string to be variable..
Currently, it is only fix to this URL:
_T(" --url=http://www.myurl.com/ --out=c:\\current.png");
I want to make something like this, so the URL is changeable..
_T(" --url=http://www." + myurl + "/ --out=c:\\current.png");
update. Below is my latest attempt:
CString one = _T(" --url=http://www.");
CString two(url->bstrVal);
CString three = _T("/ --out=c:\\current.png");
CString full = one + two + three;
ShellExecute(0,
_T("open"), // Operation to perform
_T("c:\\IECapt"), // Application name
_T(full),// Additional parameters
0, // Default directory
SW_HIDE);
The error is : Error 1 error C2065: 'Lfull' : undeclared identifier c:\test.cpp

It doesn't work because the _T() macro works only with constant string literals. The definition for _T() looks something like this:
#ifdef UNICODE
#define _T(str) L##str
#else
#define _T(str) str
Since you're apparently compiling in Unicode mode, _T(full) expands to Lfull, which is obviously not what you want.
In your case, just pass in full without the _T() macro since CString defines a conversion operator to a const wchar_t* in Unicode mode, and const char* in non-Unicode mode.
ShellExecute(0, _T("open"), _T("c:\\IECapt"), full, 0, SW_HIDE);
Note that standard C++ also provides a std::string type and a std::wstring type which does pretty much what CString does, so MFC isn't actually required for string manipulation. std::string does not provide a conversion operator, but does provide access to the underlying C-style string via c_str().

Your latest attempt will work if you lose _T() from around "full" in the call to ShellExecute. The CString will return the correct pointer. Job done.
In addition though... You should just lose the _T() stuff completely. If you're going to do things like reference url->bstrVal directly (which is Unicode, no matter what you're compiling for) then your code will only work as Unicode.
There's very little reason anymore to compile the same project for both Unicode and ANSI these days. The _T() stuff was created to address both modes "easily". But unless you're targeting Win95/98/ME, you can just go Unicode and clean up your code. Unicode is faster too, because the Windows API and the Kernel is Unicode internally. All ANSI APIs start by converting string parameters to Unicode first, and then calling their wide-char counterpart.
So no _T, TCHAR, etc. Use things like this instead:
PWSTR psz = L"my unicode string";
CString s = L"my other string, yay!";

In addition to what In silico said, CString::Format makes this code a lot more readable:
CString full;
full.Format(_T(" --url=http://www.%s/ --out=c:\\current.png"), url->bstrVal));

Related

creating a LPCTSTR pointer to a string in VS2010

I have to feed a LPCTSTR in to CreateProcess.
The short question is how do I convert a std::string into a LPCTSTR?
( LPCTSTR lpApplicationName = (LPCTSTR)FilePath.c_str(); does not work, CreateProcess simply ignores it, I know the path etc. I'm using is right because it works perfectly if I put in LPCTSTR lpApplicationName = L"a//test//path//and//file";).
The long question (why I need to do this) is: This LPCTSTR has to contain the path to, and name of, a file I wish to run.
The process is:
To get the path into the right format for CreateProcess I am having
to perform character replace (replacing single \ with double \ ) on
the output from GetModuleFileName. This output starts off as a
WCHAR buffer and I then convert into a std::string.
I then also need to concatenate this string with the final file name
which could be in any variable type (I define it in the program).
The finished string goes into the CreateProcess LPCTSTR.
I have tried using other sorts of string, but so far I haven't found any that the concatenate and character replace will work on.
Every solution I have seen does not work in Visual Studio 2010, which is what I'm using. All advice gratefully received.
LPCTSTR is a pointer to a const TCHAR*, not a const char*. Depending on your UNICODE and _UNICODE settings you will need either a std::wstring or a std::string. If you are stuck with std::string then you need to convert the char* returned by c_str() to a wchar_t* string (or not depending on UNICODE).
To make life a little easier on yourself I recommend:
#ifdef _UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif

Differences using std::string in C++ Builder and VC++

since I can get hands on the new RAD Studio Xe4 I thought I'd give it a try.
Unfortunatly, I am not so experienced with C++ and therefore I was wondering why the Code that works perfectly fine in VC++ doesn't work at all in C++ Builder.
Most of the problems are converting different var-types.
For example :
std::string Test = " ";
GetFileAttributes(Test.c_str());
works in VC++ but in C++ Builder it won't compile, telling me "E2034 Cannot convert 'const char *' to 'wchar_t *'.
Am I missing something? What is the reason that doesn't work the same on all compilers the same?
Thanks
Welcome to Windows Unicode/ASCII hell.
The function
GetFileAttributes
is actually a macro defined to either GetFileAttributesA or GetFileAttributesW depending on if you have _UNICODE (or was it UNICODE, or both?) defined when you include the Windows headers. The *A variants take char* and related arguments, the *W functions take wchar_t* and related arguments.
I suggest calling only the wide *W variants directly in new code. This would mean switching to std::wstring for Windows only code and some well-thought out design choices for a cross-platform application.
Your C++ Builder config is set to use UNICODE character set, which means that Win32 APIs are resolved to their wide character versions. Therefore you need to use wide char strings in your C++ code. If you would set your VS config to use UNICODE, you would get the same error.
You can try this:
// wstring = basic_string<wchar_t>
// _T macro ensures that the specified literal is a wide char literal
std::wstring Test = _T(" ");
GetFileAttributes(Test.c_str()); // c_str now returns const wchar_t*, not const char*
See more details about _T/_TEXT macros here: http://docwiki.embarcadero.com/RADStudio/XE3/en/TCHAR_Mapping
You have defined _UNICODE and/or UNICODE in Builder and not defined it in VC.
Most Windows APIs come in 2 flavours the ANSI flavour and the UNICODE flavour.
For, when you call SetWindowText, there really is no SetWindowText functions. Instead there are 2 different functions
- SetWindowTextA which takes an ANSI string
and
- SetWindowTextW which takes a UNICODE string.
If your program is compiled with /DUNICODE /D_UNICODE, SetWindowText maps to SetWindowTextWwhich expects aconst wchar_t *`.
If your program is compiled without these macros defined, it maps to SetWindowTextA which takes a const char *.
The windows headers typically do something like this to make this happen.
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif
Likewise, there are 2 GetFileAttributes.
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName);
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName);
In VC, you haven't defined UNICODE/_UNICODE & hence you are able to pass string::c_str() which returns a char *.
In Builder, you probably have defined UNICODE/_UNICODE & it expects a wchar_t *.
You may not have done this UNICODE/_UNICODE thing explicitly - may be the IDE is doing it for you - so check the options in the IDE.
You have many ways of fixing this
find the UNICODE/_UNICODE option in the IDE and disable it.
or
use std::w_string - then c_str() will return a wchar_t *
or
Call GetFileAttributesA directly instead of GetFileAttributes - you will need to do this for every other Windows API which comes with these 2 variants.

Set console title in C++ using a string

I would like to know how to change the console title in C++ using a string as the new parameter.
I know you can use the SetConsoleTitle function of the Win32 API but that does not take a string parameter.
I need this because I am doing a Java native interface project with console effects and commands.
I am using windows and it only has to be compatible with Windows.
The SetConsoleTitle function does indeed take a string argument. It's just that the kind of string depends on the use of UNICODE or not.
You have to use e.g. the T macro to make sure the literal string is of the correct format (wide character or single byte):
SetConsoleTitle(T("Some title"));
If you are using e.g. std::string things get a little more complicated, as you might have to convert between std::string and std::wstring depending on the UNICODE macro.
One way of not having to do that conversion is to always use only std::string if UNICODE is not defined, or only std::wstring if it is defined. This can be done by adding a typedef in the "stdafx.h" header file:
#ifdef UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif
If your problem is that SetConsoleTitle doesn't take a std::string (or std::wstring) it's because it has to be compatible with C programs which doesn't have the string classes (or classes at all). In that case you use the c_str of the string classes to get a pointer to the string to be used with function that require old-style C strings:
tstring title = T("Some title");
SetConsoleTitle(title.c_str());
There's also another solution, and that is to use the explicit narrow-character "ASCII" version of the function, which have an A suffix:
SetConsoleTitleA("Some title");
There's of course also a wide-character variant, with a W suffix:
SetConsoleTitleW(L"Some title");
string str(L"Console title");
SetConsoleTitle(str.c_str());
The comment is old but you can do it with the system method...
#include <iostream>
int main(){
system("title This is a title");
}

How to do type conversion for the following Scenario?

I am using
TCHAR buffer[MAX_SIZE];
after some set of steps i am gettig the relative path of folder say for ex:
c:\Microsoft.NET\Framework\v1.0.037\
Since the above path is in buffer of type TCHAR and i am trying to concatenate"RegAsm.exe"
After Appending i need to convert the path to the LPCTSTR since i need to pass it to
CreateProcess() which takes LPCTSTR type as argument
then the compiler giving error.I have tried but vexed.
can any one help me in this aspect....
_tcscat_s
is the related method for TCHAR. It depends like TCHAR on the _UNICODE & _MBCS preprocessor swithch and will be resolved to strcat_s or wcscat_s.
TCHAR buffer[MAX_SIZE] = _T("c:\Microsoft.NET\Framework\v1.0.037\");
_tcscat_s(buffer, MAX_SIZE, _T("RegAsm.exe"));
but this is very good old C style. So while you are using TCHAR I would suggest that
you also use MFC stuff. So using CString which also is affected by _UNICODE & _MBCS would also solve your issue.
CString buffer;
buffer = _T("c:\Microsoft.NET\Framework\v1.0.037\");
buffer += _T("RegAsm.exe");
CreateProcess(buffer, ..
std::string or std::wstring will not help because they do not change their behavior related to the preprocessor switched but if you use CreateProcessA or CreateProcessW you can also use std::string or std::wstring.
The problem is TCHAR and CreateProcess are macros that expand differently depending on whether you compile for Unicode or not. The caveat is that GetCORSystemDirectory() will only accept a Unicode buffer. To get rid of these ANSI/Unicode problems write this code part explicitly for Unicode.
Instead of TCHAR use WCHAR for the buffer. Instead of CreateProcess() use CreateProcessW() - it will happily accept the Unicode buffer. Use wcscat() for strings concatenation.
Something like this (error handling omitted):
WCHAR buffer[MAX_PATH + 1];
DWORD realLength;
GetCORSystemDirectory( buffer, MAX_PATH, &realLength );
*( buffer + realLength ) = 0;// Don't forget to null-terminate the string
wcscat( buffer, L"regasm.exe" );
CreateProcessW( /*pass buffer here*/ );
I assume from the fact that you get an error that you're working with Unicode... In which case you may want to look at the mbstowcs and wcstombs functions.
More information is really needed to be able to answer properly.
If you want to make your life easier I would always suggest using std::string, then when calling the CreateProcess() function just do:
std::string myPath = "somePath";
LPCTSTR lpBuf = reinterpret_cast<LPCTSTR>(myPath.c_str());
Not tested but that should probably work, if you are still getting an error, well posting the code would be beneficial.
Note that it may be more complicated if you are using Unicode.
When you do buffer + "RegAsm.exe", it will be like adding two pointers (as arrays decay into pointers and "RegAsm.exe" will be const TCHAR*) hence you get the compiler error. What you want is string concatanation. Use _tcscat or or the secure version (as claimed in MSDN) _tcscat_s function for doing the concatanation.

CFileImageLoader(LPCTSTR lpszFileName);

I have a class which expects a LPCTSTR.
When i call :
new CFileImageLoader(_T("Splash02.png"))
OR
new CFileImageLoader("Splash02.png")
both don't work.
Why ?
I'm new to cpp...
Thanks
Jonathan d.
This issue is a combination of C++ issues and Windows specific issues.
C++ defines two types of strings, regular and wide. A regular string looks like:
const char *str = "regular string";
while a wide string looks like:
const wchar_t *wstr = L"wide string";
With just standard C++, you have to decide when you write your library whether to use regular or wide strings.
Windows has defined a pseudo type called tchar. With tchar you write something like:
LPCTSTR tstr = _T("regular or wide string");
Whether this is actually a regular (char *) or a wide (wchar_t *) string depends on whether you compile your code for Unicode or not.
Since the function is specified as taking an LPCTSTR, it needs to be called with the appropriate type for how you are compiling.
If you know you are only going to be building with or without Unicode support, you can skip all the TCHAR stuff and directly use either wchar_t or char respectively.
Since CFileImageLoader("Splash02.png") is not working, you must be compiling with Unicode support enabled. You can change that to CFileImageLoader(L"Splash02.png") and commit to always using Unicode or you can change it to CFileImageLoader(_T("Splash02.png")) and let the macro magic do the work.
"both don't work" - could you maybe be a tiny, tiny little bit more specific?
If you compile with _UNICODE defined, then the second shouldn't even compile.
You're also just passing a filename, not a full path. Maybe your image loader class can't find the file because it uses a differen CWD path as you expect. Try passing the full path instead.
Maybe your image library can't support to open PNG format file.
Try passing the full path instead.
Maybe you need to call some initialization functions which provide by your image library