Solved

DrawText needs LPCTSTR, have char*

Posted on 2008-10-14
11
830 Views
Last Modified: 2008-10-22
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.
0
Comment
Question by:wavget
  • 5
  • 4
  • 2
11 Comments
 
LVL 27

Expert Comment

by:BigRat
ID: 22712018
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";

 
0
 
LVL 1

Author Comment

by:wavget
ID: 22712756
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?
0
 
LVL 27

Accepted Solution

by:
BigRat earned 70 total points
ID: 22713075
iint MultiByteToWideChar(
  UINT CodePage,         // code page
  DWORD dwFlags,         // character-type options
  LPCSTR lpMultiByteStr, // string to map
  int cbMultiByte,       // number of bytes in string
  LPWSTR lpWideCharStr,  // wide-character buffer
  int cchWideChar        // size of buffer
);

so it would go :-
   char buffer[1024]    // 512 WideChar byte buffer

   int res = MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,org,strlen(org),(LPWSTR)buffer,512);
   if(!res) {
        // some error message with getlasterror
   } else {
       DrawText();
   }

You must check the result of the call, you ought not use a string literal as buffer (writable strings problem). I'd be surprised if your text was OEM and not ANSI.

     
0
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
LVL 19

Expert Comment

by:LordOfPorts
ID: 22713903
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

0
 
LVL 27

Expert Comment

by:BigRat
ID: 22719354
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.
0
 
LVL 19

Expert Comment

by:LordOfPorts
ID: 22722148
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.
0
 
LVL 19

Assisted Solution

by:LordOfPorts
LordOfPorts earned 55 total points
ID: 22722344
BigRat, I thought your comment was by the author so it should of course be the author stated "I'm programming in C, not C++...." so again mbstowcs is a standard C library function unlike MultiByteToWideChar.

wavget is using eMbedded Visual C++ 4.0 http://www.microsoft.com/downloads/details.aspx?FamilyID=1dacdb3d-50d1-41b2-a107-fa75ae960856&displaylang=en published on 12/29/2003 which I believe does not yet have the mbstowcs_s function.

wavget, try the following when calling DrawText:
	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) {
		DrawText(hdc, (LPCWSTR)wStr, wcslen(wStr), &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);
	}
 
	delete wStr;

Open in new window

0
 
LVL 27

Expert Comment

by:BigRat
ID: 22722388
>>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.
0
 
LVL 19

Expert Comment

by:LordOfPorts
ID: 22723197
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.
0
 
LVL 1

Author Comment

by:wavget
ID: 22748502
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.
0
 
LVL 19

Expert Comment

by:LordOfPorts
ID: 22753001
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);
0

Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Unresolved External Symbols 3 109
What is atomic operation? 6 65
C++ Code Issue 4 26
Finding Divisors 5 21
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question