PDA

View Full Version : Problems with Win32 compatibility in Visual Studio 2005 with MVC++ 6.0


pa1
03-07-2007, 06:30 AM
Hi.
I just got Microsoft Visual Studio 2005 and I can't make even really basic programs (Win32) to compile. I tried to compile a program that in Visual C++ 6.0 has 0 errors and 0 warnings, but in this new version that doesn't happen. The short program named 'main.cxx' is:


#include<windows.h>

long FAR PASCAL WndProc (HWND hwnd, UINT message,
UINT wParam, LONG lParam)
{
static HWND ewin;

switch (message)
{
case WM_CREATE:
{
ewin = CreateWindowEx(0,"button","Exit",
WS_CHILD | WS_VISIBLE | SS_CENTER,
0,400,400,60,
hwnd,(HMENU)2,
(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
NULL);

return 0;
}
break;
case WM_COMMAND:
{
switch (wParam)
{
case 2:
PostQuitMessage (0);
break;
}
return 0;
}
break;
case WM_DESTROY:
{
PostQuitMessage (0);
return 0;
}
break;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}


int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{
static char szAppName[] = "Win32Cone";
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;

if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.lpszMenuName = NULL;
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszClassName = szAppName;
RegisterClass (&wndclass);
}

hwnd = CreateWindowEx ( 0,szAppName,
"Draw Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
480,
NULL,
NULL,
hInstance,
NULL);

ShowWindow (hwnd, nCmdShow);
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}


and the errors are:

error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'const char [7]' to 'LPCWSTR'

error C2440: '=' : cannot convert from 'char [10]' to 'LPCWSTR', Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'char [10]' to 'LPCWSTR'

and I get some warnings like:
warning C4312: 'type cast' : conversion from 'LONG' to 'HINSTANCE' of greater size

I see that the errors are related to the way the characters are interpreted, that is when I use ' char array[] = "WindowName" ' in CreateWindow(), this function expects to receive a LPCWSTR.

Anyway, how can I set Visual Studio 2005 to compile the way Visual C++ 6.0 did it (or how can I make these character interpretation problem to be solved)?

Thank you.

dave_
03-07-2007, 07:00 AM
It is set to use unicode. I don't have 2005 on my PC but you need to turn that off.

Probably in the project settings under character set. Change it to multibyte (it works fine with single byte character sets)

Reedbeta
03-07-2007, 07:42 AM
Or you can just make all your string literals unicode, by writing L"hello" instead of "hello". The L instructs the lexer to generate a unicode string.

Kenneth Gorking
03-07-2007, 07:46 AM
Or you can use unicode strings. It's quite simple, just put an 'L' (literal) in front of your constant strings, eg. L"button", L"Exit", etc.

Note that Windows uses unicode internally, so when you provide it with ansi strings it has to waste cycles converting them to unicode. This of course isn't a big deal with window or button names, but it is good to know.

The 'LONG' to 'HINSTANCE' conversion warning is triggered because vc2005 checks for 64-bit incompatabilities. A long in native 64-bit mode is only 32-bits wide, but a HINSTANCE (a pointer) is 64-bits wide, so if you try to convert between these types you lose half of the pointer address, and eventually end up with a bad pointer and an exception is thrown when attempts to access that invalid address occurs. To correct this, just use LONG_PTR instead, its size is always the same as a pointer.

pa1
03-07-2007, 08:13 AM
Thank you guys, the UNICODE part is fixed with the 'L' s, but I still can't remove the warning about 'type cast' : conversion from 'LONG' to 'HINSTANCE' of greater size, because if I change (HINSTANCE) for (LONG_PTR) I get an error. What I have to do then?
Thanks again.

pater
03-07-2007, 08:27 AM
You'll probably have the "Detect 64Bit portability issues" (VS2003 naming, but VS2005 should be similar) flag checked in project settings. This will issue a warning whenever you try to convert a type that is 64bit on a 64bit system to 32 bit (i.e. when you try to assign a pointer to an int). Unless you're really using a 64 bit System and OS (and build target), you can set this flag to "no".

Rubicon
03-07-2007, 09:15 AM
And then at some point later, you'll probably realise that yet another shitty default setting is to build a DLL as opposed to an EXE.

Unless you are indeed going for a DLL, you'll want to link against the "multithreaded" libs instead of "multithreaded DLL" libs.

Note there are no single-threaded options in case you felt you needed them. You don't anymore.

Kenneth Gorking
03-07-2007, 10:38 AM
You were supposed to change LONG to LONG_PTR ;)

Reedbeta
03-07-2007, 10:42 AM
And then at some point later, you'll probably realise that yet another shitty default setting is to build a DLL as opposed to an EXE.

Unless you are indeed going for a DLL, you'll want to link against the "multithreaded" libs instead of "multithreaded DLL" libs.

Note there are no single-threaded options in case you felt you needed them. You don't anymore.

I don't understand what you mean. Using the DLL version of the runtime library doesn't make your program a DLL, it just means it links with msvcrt8.dll rather than linking with the runtime statically. It is certainly not a default setting to build a DLL rather than an EXE. I always use the DLL runtime library to avoid code bloat, since pretty much every Windows system has that DLL already anyway.

Rubicon
03-07-2007, 10:46 AM
That's interesting to know.

I've never got as far as that tbh, as when I make a default project with these settings then copy my stub files over, it moans like buggery with a million linker errors every time (all system looking stuff). Changing to exe as expected makes it all work.

Next time I do this, I'll look more closely what the errors are and maybe give this a whirl. Many thanks!

Reedbeta
03-07-2007, 01:34 PM
If you're using Visual Studio 2005, have you followed the instructions on this page (http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/)? If you haven't done Step 4, then you would probably get a crapload of linker errors.

Rubicon
03-07-2007, 01:41 PM
I'm using the full fat version, but it's probably the same problem.

Thanks for pointing this out. I probably won't actually use it but it's nice to know what's going on :)

pa1
03-16-2007, 10:21 AM
I found out how to disable the Unicode definition in Visual C++ 2005:

1) Place

#ifdef UNICODE
#undef UNICODE
#endif

before any references of a string, or

2) go to Project-> <project_name> properties...->Configuration Properties->C/C++ -> Preprocessor->Preprocessor Definitions->...-> and uncheck 'Inherit from parent or project defaults'.

:yes: