Link to home
Start Free TrialLog in
Avatar of wavget
wavgetFlag for United States of America

asked on

DrawText needs LPCTSTR, have char*

I'm using Microsoft Embedded Visual C++ 4 to develop an application for Windows Mobile.

I'm programming in C, not C++. UNICODE is enabled.

I'm trying to use DrawText with text stored in a char*

char* Str = "Hello!";

DrawText(hdc, ? ,3, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);

How do I convert from char *' to 'const unsigned short *' as required by DrawText?

Thanks in advance,

D2.
Avatar of BigRat
BigRat
Flag of France image

If you were doing this properly, ie: if you had (say) an ANSI text file which you wanted to display on the screen, you'd translate the ANSI text into Unicode with MultiByteToWideChar. Normally the number of TChars needed is the string length, but if you don't know the length (might be very long), you'll have to allocate memory for that. I just do a new Byte[] of 2+twice the length of the input string and simply use a (LPTSTR) coercion.
  If you have constant text like "Hello" just write W_CHAR * helloStr = L"Hello";

 
Avatar of wavget

ASKER

BigRat,

I can't do W_CHAR * helloStr = L"Hello"; because I am using it as char* throughout other parts of my code.

I tried:

wchar_t *test = L"       ";
char *org = "Hello";

MultiByteToWideChar(CP_OEMCP,MB_PRECOMPOSED,org,5,test,5);
DrawText(hdc,test, 5, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);

but it prints nothing.... how does MultiByteToWideChar work?
ASKER CERTIFIED SOLUTION
Avatar of BigRat
BigRat
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The mbstowcs function http://msdn.microsoft.com/en-us/library/k1f9b8cy(VS.80).aspx is another option at your disposal, e.g.:
	char * Str = "Hello!";
	size_t nChars = strlen(Str);
 
	wchar_t * wStr = new wchar_t[nChars + 1];
 
	for(int i = 0; i < nChars + 1; i++) {
		wStr[i] = L'\0';
	}
 
	if(mbstowcs(wStr, Str, nChars) > 0) {
		MessageBoxW((LPCWSTR)wStr);
	}
 
	delete wStr;

Open in new window

LordOfPots: First your function is deprecated - says so on the ms page - and second it only translates according to locale, whereas the MultiByteToWideChar function translates any code page. Lastly I am still not sure whether this function actaully calls the single mbtowc function each time, which if it did would be considerably slower than MultiByte.
Well, it is deprecated in favor of the more secure version mbstowcs_s http://msdn.microsoft.com/en-us/library/eyktyxsx(VS.80).aspx available only in the latest Microsoft libraries, however you are right I should have mentioned that.

Now, you stated "I'm programming in C, not C++. UNICODE is enabled."

mbstowcs is a standard C library function versus the MultiByteToWideChar which is Microsoft API C++ function. It would be interesting to run bench mark tests however I think it is highly unlikely a standard C library function would be slower.

In the documentation it mentions that its output is similar to the output of multiple calls to mbstowc which does not mean that it actually calls mbstowc for each character.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>MultiByteToWideChar which is Microsoft API C++

Nope, it's a standard Windows API function, which I have been using for the last ten years. It has the beauty that I can translate everything into Unicode by just switching the code page parameter.
Nope to what? I did say it is Microsoft API. It is declared in Winnls.h written in C/C++. It is not part of the standard C library.
Avatar of wavget

ASKER

Both MultiByteToWideChar and mbstowcs seem to work well for me, thanks BigRat and LordOfPorts for all your input.

I would like to implement a function that I can use in different places:

wchar_t* tows(char *Str) {
      int Size = strlen(Str);
      wchar_t *buffer = malloc((Size + 1) * 2);
      MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,Str,strlen(Str),(LPWSTR)buffer,512);
      // or mbstowcs(buffer,Str,Size + 1);
      return buffer;
}

char* Name;
Name = "Hello";

DrawText(hdc,tows(Name),strlen(Name),&rect,DT_SINGLELINE | DT_CENTER | DT_NOPREFIX);

Is this the right way to implement this? Should I free the returned pointer somewhere?

Thanks,

D2.
Separating the logic for reusability is a good idea however in the code above you would no longer have a reference to the buffer which should be freed after you no longer need it, to change it you could store the tows' return value into a wchar_t * variable, then pass the variable to the DrawText function and finally once you no longer need it, call free on the variable itself, e.g.:

char * Name = "Hello";
wchar_t * wName = tows(Name);
DrawText(hdc, wName, strlen(Name), &rect, DT_SINGLELINE | DT_CENTER | DT_NOPREFIX);

// At the very end when you no longer need wName
free(wName);