Thread: MSVC++ 6 and win32

  1. #1
    Grammar Police HybridM's Avatar
    Join Date
    Jan 2003
    Posts
    355

    MSVC++ 6 and win32

    Hi all,

    I have a weird problem and i'm going nuts. If I start a project (win32 app), everything goes fine until i try to assign a value to a struct variable from a function, such as this:
    Code:
    case WM_CREATE:
    {
          HFONT hfDefault;
    //...
    
         hfDefault = GetStockObject(DEFAULT_GUI_FONT); //no compile
    results in this:
    error C2440: '=' : cannot convert from 'void *' to 'struct HFONT__ *'
    Conversion from 'void*' to pointer to non-'void' requires an explicit cast


    The thing is, the example which contains this code compiles fine (with its own project file) but if i copy and paste the entire code into mine i get the error above. This is not the only example of this happening to me.

    Any help would be appreciated, thanks.
    Thor's self help tip:
    Maybe a neighbor is tossing leaf clippings on your lawn, looking at your woman, or harboring desires regarding your longboat. You enslave his children, set his house on fire. He shall not bother you again.

    OS: Windows XP
    Compiler: MSVC

  2. #2
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    Try casting the return from GetStockObject like so
    Code:
    case WM_CREATE:
    {
          HFONT hfDefault;
    //...
    
         hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    as to why the code from the book works I am unsure. Are you compiling the books source code or just running the .exe for the example?
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  3. #3
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    opps didnt read full post... create a new project and add the sample code to it (add the actual files and not just copy and paste)and try to compile it. It could be that the sample workspace has a differnt warning lvl set than what you are using in your own projects.... you can change the level of warnings that your compiler generates in the project settings under the c/c++ tab. I usually have mine set to lvl 3 which is the default I think.
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  4. #4
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    I think the problem is because GetStockObject() returns a generic HANDLE type. Compilers like to protect programmers from themselves so they add a bunch of protections against going from type to type implicitly. So you have to hard-cast the void * into HFONT *.

    Actually that seems odd. The variable was declared as HFONT, but the compiler flagged an error trying to convert to a HFONT *. Why is this?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  5. #5
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    Because GetStockObject returns a void* and it has to be cast to the type of object you require before you can use it. Void* is an unknown type so you have to tell it what type to use.
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  6. #6
    Grammar Police HybridM's Avatar
    Join Date
    Jan 2003
    Posts
    355
    Hi again,

    Thanks for your help guys, explicitly casting works, but i still don't understand why theForger's example works without it.

    Link of tut:
    http://www.winprog.org/tutorial/
    go to app 1
    Thor's self help tip:
    Maybe a neighbor is tossing leaf clippings on your lawn, looking at your woman, or harboring desires regarding your longboat. You enslave his children, set his house on fire. He shall not bother you again.

    OS: Windows XP
    Compiler: MSVC

  7. #7
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    Technote: Improved Conformance to ANSI C++

    As a result of improved C++ conformance, some constructs that used to compile will now give errors. Each error message that may result from some of these changes is flagged by "(new behavior; please see help)" at the end of the message. This doesn't mean that the error message has a new meaning; it means that the compiler may be diagnosing an error which it previously did not.
    I just ran the code from that link you posted and got the same error. If you hit F1 in the output window(assuming that you are using VC6) while on the error in question, it will take you the help files and show you even more info (sometimes) on the error. The above quote is what I found.
    So it seems that it used to work without cast but ANSI C++ changed it. This code probably worked on older compilers where casting wasn't enforced. Remember windows is programmed in c originally and the casting restrictions were almost non-existent. C++ came along and changed a lot of things and specifying a type cast was one of them. They wanted programmers to be sure that the cast is actually what they want to happen. And to make code easier to read. It is easier reading someone elses code when you don't have to deal with implicit type casts and you know they actually ment to do the cast.
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  8. #8
    Registered User Dohojar's Avatar
    Join Date
    Feb 2002
    Posts
    115
    To make it work as is, make sure you are compiling a .C file instead of a .CPP file and it compiles without complaint.
    Dohojar Moajbuj
    Time is the greatest teacher, too bad it kills all its students

  9. #9
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Originally posted by bennyandthejets
    Actually that seems odd. The variable was declared as HFONT, but the compiler flagged an error trying to convert to a HFONT *. Why is this?
    No, the compiler was trying to convert to a "struct HFONT__ *". HFONT is a typedef for a pointer to a struct called HFONT__.

    Oh, the preferred C++ way is to do this:

    hfDefault = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT ));

    not this, which is the C-way:

    hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);

    As to why one would compile: The book project compiles it as C, your project compiles it as C++. Under C, the cast is unneeded. Under C++, it is absolutely needed. C implicity converts void * to any other pointer type. C++ won't.

    Edit: Dammit, took too long, Dohojar beat me to the final answer
    Last edited by Cat; 07-07-2003 at 10:55 PM.

  10. #10
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    I've forgotten about all of this again. Why static cast instead of type cast?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  11. #11
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    Originally posted by Dohojar
    To make it work as is, make sure you are compiling a .C file instead of a .CPP file and it compiles without complaint.
    This is exactly the cause of the problem. MSVC++ compiles both C and C++, depending on the extension of the file. Most win32 tutorials that do not use classes are compiled in C, although, it would be better to compile them in C++ just by changing the filename from .C to .CPP, because everything will compile fine, with the exception of these type casts. C++'s extra type checking forces you to make explicit type casts, so you know what is going on. It's still C code after you place the type casts - but the C++ compiler will let you know when you forgot to put them, a C compiler assumes you know what you are doing, which is often a bad thing.

  12. #12
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Originally posted by bennyandthejets
    I've forgotten about all of this again. Why static cast instead of type cast?
    Well, in C there are essentially 3 different kinds of casting, and they all have the same syntax so the compiler chooses which to do.

    In C++ there are 4 different kinds of casting, you tell the compiler which type you want, and it tells you if it's legal or not. This way, you know exactly what kind of cast is happening.

    For example:

    float f = 127;
    int i = (int) f;

    does a static cast, which is the only legal kind of cast in that circumstance.

  13. #13
    Grammar Police HybridM's Avatar
    Join Date
    Jan 2003
    Posts
    355
    Thanks everyone for your replies, you've been really helpful.

Popular pages Recent additions subscribe to a feed