Why #define UNICODE has no effect in windows - c++

I have the following code:
#define UNICODE
// so strange??
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
But the compiler still report error like this:
error C2664: “DWORD K32GetModuleBaseNameA(HANDLE,HMODULE,LPSTR,DWORD)”: 无法将参数 3 从“wchar_t [260]”转换为“LPSTR” [E:\source\mh-gui\build\src\mhgui.vcxproj]
Which means cant convert param 3 from wchar_t[260] to LPSTR. It's look's like that still looking for A version api?

You must put
#define UNICODE
#define _UNICODE
BEFORE
#include <Windows.h>
The Windows header uses #ifdef UNICODE (et al), so if you want to make the distinction count, the #defines must occur before the #include.
edit: Because these #defines are functionally global, the most reliable place to add them is in your compiler options, so the ordering doesn't matter then.

Since you are using visual studio, instead of defining UNICODE yourself you should enable the W version by right clicking the project in the solution explorer -> properties -> Advanced -> Change the "Character Set" option to "Use Unicode Character Set"

Related

How to write a portable c++ code with unicode support?

I have the below program, which tries to print Unicode characters on a console by enabling the _O_U16TEXT mode for the console:
#include <iostream>
#include <fcntl.h>
#include <io.h>
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"test\n \x263a\x263b Hello from C/C++\n");
return 0;
}
What is unclear to me is that, I have seen many C++ projects (with the same code running on Windows and Linux) and using a macro called _UNICODE. I have the following questions:
Under what circumstance do I need to define the _UNICODE macro?
Does enabling the _UNICODE macro mean I need to separate the ASCII related code by using #ifdef _UNICODE? In case of the above program, do I need to put any #ifdef UNICODE and the ASCII code processing in #else?
What extra do I need to enable the code to have Unicode support in C/C++? Do I need to link to any specific libraries on Windows and Linux?
Why does my sample program above not need to define the _UNICODE macro?
When I define the _UNICODE macro, how does the code know whether it uses UTF-8, UTF-16 or UTF-32? How do I decide between these Unicode types?

using unicode dlls in MBCS projects or vice versa

I have a vc++ dll that is compiled with charset set to 'Use Unicode Character Set'.
Now i want to use this dll in my vc++ exe whose charset is 'Use Multi-Byte Character Set'. I know that theoretically nothing stops me from doing this as after compiling the vc++ dll, all the function signatures would be either wchar_t or LPCWSTRs .. And in my vc++ exe i just create strings of that format and call the exported functions. But, The problem i am facing is , The header in unicode dll takes TCHAR parameters like for ex:
class MYLIBRARY_EXPORT PrintableInt
{
public:
PrintableInt(int value);
...
void PrintString(TCHAR* somestr);
private:
int m_val;
};
Now i want to use this PrintString() in my exe. So, I included the header and used it like below:
#include "unicodeDllHeaders.h"
PrintableInt p(2);
wchar_t* someStr = L"Some str";
p.PrintString(someStr);
This as expected gives me a compiler error :
error C2664: 'PrintableInt::PrintString' : cannot convert parameter 1 from 'wchar_t *' to 'TCHAR *'
As the exe is built with MBCS TCHAR is defined to char . So, what i thought would solve this issue is :
#define _UNICODE
#include "unicodeDllHeaders.h"
#undef _UNICODE
But after defining _UNICODE also i still get the compilation error. So, my next guess was that probably TCHAR.h was already included before the #include "unicodeDllHeaders.h" , when i searched for the inclusion of TCHAR.h it was there else where in the project. So, I moved the inclusion to after definition of _UNICODE , This solved the compilation error here but it is failing in the other places where TCHAR is expected to be made char . So, My question is :
Can i somehow make TCHAR resolve to char and wchar_t in the same project ? I tried #define TCHAR char, #undef TCHAR , #define TCHAR wchar_t but its failing in the c headers like xutils
You can not retroactively change the binary interface of your DLL, regardless of what do to your header file by using macros. The typical solution is to firstly dump the whole legacy MBCS stuff. This stopped being interesting 10 years ago, nowadays all targets supporting the win32 API support the wide character interface with full Unicode support.
If you want that retro feeling of the nineties, you can also compile your DLL twice, once with CHAR and once with WCHAR. The latter then typically get a "u" suffix (for Unicode). In your header, you then check the charset and delegate to the according DLL using #pragma comment lib...

Where to find definition of window message WM_UAHDRAWMENUITEM (0x92)

I'm writing a hook dll, which handles window drawing messages.
I found for Vista and above, some unknown message id are received by the hook dll, specifically 0x90 ~ 0x95.
I did some googling and found an msdn link and this, which told me what message they're:
#define WM_UAHDESTROYWINDOW 0x0090
#define WM_UAHDRAWMENU 0x0091
#define WM_UAHDRAWMENUITEM 0x0092
#define WM_UAHINITMENU 0x0093
#define WM_UAHMEASUREMENUITEM 0x0094
#define WM_UAHNCPAINTMENUPOPUP 0x0095
But I can't find definition of macro WM_UAHDRAWMENUITEM in any header files, the compiler complains about "undefined symbols". I did a global search on "WM_UAHDRAWMENUITEM" but found nothing.
At present I'm using 0x92 to handle this message.
My question is: how to nicely replace hard-coded 0x92 with a Windows-defined macro?
how to nicely replace hard-coded 0x92 with a Windows-defined macro?
Obviously, your installed version of the Win32 SDK does not have the macros, so you can't use them. But you have the #define values, so just copy/paste them directly into your own code. If you want, you can wrap them in an #ifdef so that if you ever upgrade to an SDK version that has them natively, the native macros will be used, otherwise the compiler will keep using your manual ones.
#ifndef WM_UAHDRAWMENUITEM
#define WM_UAHDRAWMENUITEM 0x0092
#endif

How can I conditionally include a nonexistent file in Visual C++?

I'm using Visual C++ to build and test a project, but I'll also be using it on other platforms. I started the code initially on a different platform.
In some of my class headers I need to include a file which is specific to the other platform, however, this file doesn't exist in the Visual C++ workspace.
I've tried using code like this:
#if TARGET == OTHERPLATFORM
#include "themissingfile.h"
#endif
where TARGET is defined elsewhere as WINDOWS
#define TARGET WINDOWS
However, I still get a compiler error stating that "themissingfile.h" cannot be found. It appears like the precompiler is processing the include before the if. What's the best way to get around this? I suppose I could just create a blank "themissingfile.h" in the Visual C++ source folder, but it seems to me like there should be a better solution.
#define TARGET WINDOWS does not set TARGET to the string WINDOWS: it sets it to whatever WINDOWS is defined to. Most likely this happens:
#define WINDOWS // Sets WINDOWS to 0
#define OTHERPLATFORM // Sets OTHERPLATFORM to 0
#define TARGET WINDOWS // Sets TARGET to 0
#if TARGET == OTHERPLATFORM // Evaluates to 0==0, so true
Use _WIN32 macro instead:
#ifndef _WIN32
#include "themissingfile.h"
#endif
_WIN32 is defined for both 32-bit and 64-bit builds. See C/C++ Predefined Macros.

problems in migrating 32bit application on 64 bit

I am trying to migrate existing c++ 32 code to 64 code on windows7 with visual studio 2010.i never did 64bit compilation before. with the help of internet references i did the setup for 64 bit compilation. like VS2010 with 64 bit compiler etc and other configuration changes.
In the preprocessor i removed WIN32 and added WIN64. i have some other pre-processors like OS_WIN_32 and some other which are specific in my code.
In the code wherever WIN32 was getting used i added extra condition as || WIN64 this is just to ensure that application should get compiled with win32 as well as win64.
When i am trying to compile the code i am getting the compilation error saying
fatal error C1189: #error : Only one of the WIN32 and WIN64 symbols should be defined
this error is coming from the local code where we have a check whether both WIN32 and WIN64 are defined. that code is as shown below.
#if defined WIN32 && defined WIN64
# error Only one of the WIN32 and WIN64 symbols should be defined
#endif
in VS2010 if macros are not enabled then the code inside the macro gets greyed out. in my code also the above error is greyed out. but still i am getting that error.
The code where i added WIN64 is including windows.h. for reference givine it below.
#if defined WIN32 || defined WIN64
#include <windows.h>
#include <process.h>
#endif
So my question is why i am getting this error? shouldnt we add windows.h for 64bit compilation.? i tried by commenting this inclusion but i am getting other errors wrt HANDLE which are used in the code.
If i go to WIN32 definition VS2010 is pointing to a definition in windef.h file. This file is present in Microsoft SDKs\windows\v7.0A\include folder i.e. not my local code.
for referance that definition is given below.
#ifndef WIN32
#define WIN32
#endif
So i want to know why compiler is getting both pre-processors WIN32 and WIN64.
Thanks in advance for your help.
You shouldn't define either yourself. The macro's that should be used to check this are
_WIN32 // always defined for Windows apps
_WIN64 // only defined for x64 compilation
These are defined by the compiler (see here).
Often, the IDE adds the unprefixed macros to the commandline to not let legacy projects which use the non-documented unprefixed versions fail to build. The fact that they work is not a reason to use them, when documented alternatives are present.
It boils down to this:
#ifdef _WIN32
// We're on Windows, yay!
#ifdef _WIN64
// We're on x64! Yay!
#else // _WIN64
// We're on x86 (or perhaps IA64, but that one doesn't matter anymore). Yay!
#endif // _WIN64
#else // _WIN32
// We're not on Windows, maybe WindowsCE or WindowsPhone stuff, otherwise some other platform
#endif