Thread: WM_NCCREATE problem...

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    WM_NCCREATE problem...

    I need to process this message. Problem is, when I introduce the handler, the window never shows, and I must kill with ctl+alt+del. Even this hangs the window! :

    case WM_NCREATE:
    break;


    I am still processing the WM_CREATE message, but even ommitting it doesn't change things.

    Any ideas would be appreciated...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    In order to continue window creation you must return TRUE from WM_NCCREATE handler; returning FALSE results in creation failure (CreateWindowEx returns NULL).
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Thanks. That clarified things a bit. A moment ago I was thinking, maybe this is MS's sick way of saying, "ok, you want to handle it, go ahead, but do the rest of the creation yourself!". This was reinforced by the fact that when I added this:


    case WM_NCCREATE:

    return DefWindowProc(hwnd, message, wParam, lParam);

    break;

    The window created. But when I read your post, it became clear that it was more an issue of my return value. Still, there is something remaining: simply returning TRUE makes the window appear without the title! So would you suggest I handle the message then return DefWinProc() as above? (Because that seems to work... because Windows gets to handle the message too, in that case...)
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    The WM_NCCREATE or Non-Client create msg does for the non-client area what the WM_CREATE does for the client area.

    The non-client area is the caption (including min/max/close buttons and small icon, borders ( if any).

    If you want default behaviour then calling DefWindowProc somewhere in your handler as you have suggested is the best way.

    If you need to manually draw the non-client area there is the WM_NCPAINT message. There are a bunch of API functions such as DrawCaption, DrawEdge, DrawFrameControl, DrawState that you may wish to take a look at in this regard, although most of these are for drawing controls rather than 'main' windows.

    Hope that helps some.

    edit: typos.
    Last edited by Ken Fitlike; 08-25-2002 at 07:39 PM.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Thank you. Er, one more Q, tho: Is there a way to allow all child windows(buttons, edits, etc.) to share one WindProc? I believe that buttons, for instance, share one with other system buttons, ie, classname is matched with WindProc. Correct?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>I believe that buttons, for instance, share one with other system buttons, ie, classname is matched with WindProc. Correct?<<

    Yes.

    >>Is there a way to allow all child windows(buttons, edits, etc.) to share one WindProc?<<

    Yes this can also be done. For controls use window subclassing to replace the wndproc. Use SetWindowLong - (GWL_WNDPROC index/flag ) to set the new wndproc retaining the returned value from that api function call as the original wndproc. For default, system msg processing use CallWindowProc with the original wndproc as described above. When you're done with the control/window, use SetWindowLong to restore the original window procedure.

    I think there have been a number of subclassing examples posted in the windows board which may be of some interest to you in this regard.

    A typical c++ strategy for a generic callback involves attaching this to the window as the last parameter in the call to CreateWindowEx. Have a static wndproc that handles WM_NCCREATE/WM_CREATE, gets the CREATESTRUCT from either msg and from it this. Use SetWindowLong - (GWL_USERDATA flag) to attach this to the window (remember these and a few other msgs are sent during system processing of CreateWindowEx). Subsequent messages retrieve this with GetWindowLong - (GWL_USERDATA flag), casting the return value to your class object. If you have a virtual c++ class wndproc you can forward the messages to it and handle messages normally within the body of your c++ class. You can use this same static procedure for any subclassed controls. In this case you only need use GetWindowLong to retrieve this; since the control is not subclassed until after it's created the msgs sent during processing of CreateWindowEx are not available eg. no WM_CREATE.

    However I believe the preferred c++ way would be to use function pointers. http://www.function-pointer.org/ provides an interesting discussion that you might find useful.

    Sorry, if you know all this stuff anyway; hopefully some of it might be useful.

    Good luck.

    edit: Apparently GetWindowLong & SetWindowLong are obsolete (Aug2001 PSDK) so you should use SetWindowLongPtr and GetWindowLongPtr. The original functions work fine and I think that for 32bit systems the newer functions just call the originals anyway (but don't quote me on that).
    Last edited by Ken Fitlike; 08-25-2002 at 11:17 PM.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Wow, you basically described a play by play of what I'm trying to do here! I am attempting to forever banish the WindowProcedure in favor of a more generic approach to handling events.

    And so...

    Originally, before I realized my child windows/buttons were not using the (MainWindow) class's WindProc, (which I had to declare a friend due to compiler restrictions, ie: could not pass/cast the MainWindow's WNDPROC to the WNDCLASSEX structure without it being a friend ) this is exactly what I was doing (passing "this" as the last parameter of CreateWindowEx(), and then fetching it from the other side of the window procedure, ie:

    case WM_NCCREATE:
    {
    CREATESTRUCT *createstruct = (CREATESTRUCT*)lParam;

    SetWindowLong(curr_hwnd, GWL_USERDATA, (long)createstruct->lpCreateParams);

    return DefWindowProc(curr_hwnd, message, wParam, lParam);
    }
    break;

    It worked fine for the MainWindow window, but a control didn't even fall into the WindProc. So I devised of a strategy of storing a pointer to a second WNDPROC in the " class Window " 's member area. (The MainWindow subclass simply made this pointer NULL.)

    Then, after calling CreateWindowEx() on a child Window, I placed this in the code:

    SecondaryWindProc = (WNDPROC)GetWindowLong(this->hwnd, GWL_WNDPROC);

    WNDPROC parent_proc = (WNDPROC)GetWindowLong(this->hwnd_parent, GWL_WNDPROC);

    SetWindowLong(this->hwnd, GWL_WNDPROC, (long)parent_proc);

    Finally, in the MainWindow's "friend" WNDPROC, if the current HWND was of a child, instead of returning 0, I do:

    return curwin->SecondaryWindProc(curr_hwnd, message, wParam, lParam);

    ...so that the control/child could then go on to invoke it's windows class-type window procedure.

    But now the child remains unresponsive! So I will try to reset the GWL_WNDPROC each time for children, as you suggested.


    Sorry if I'm long winded, but I thought I should explain my situation better.

    Anyway, thanks for all of your insight and help, Ken, you're a true gentleman!


    /*edit*/ BTW: I found it is just as easy to set the window's GWL_USERDATA right after calling CreateWindowEx()! So I have adopted this approach, and now just pass NULL as usual to the last param of CreateWindowEx()...
    Last edited by Sebastiani; 08-26-2002 at 10:49 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>you basically described a play by play<<

    Anything to boost the post count, eh?

    >>I thought I should explain my situation better<<

    It's a part time obsession of mine comparing wndproc wrapper techniques so thanks for sharing your approach/views.

    >>you're a true gentleman!<<

    If only this were really true - but thanks anyway!
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    When you're done with the control/window, use SetWindowLong to restore the original window procedure.
    I'm having a problem with this concept. That is, how/where do I set it back to the parent's window procedure afterward? I mean, after giving the child it's "original" window proc, there is no longer a way to communicate with it! (at least not from the parent proc...)
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>could not pass/cast the MainWindow's WNDPROC to the WNDCLASSEX structure without it being a friend<<

    Use a static wnd procedure so that the WNDPROC of the WNDCLASSEX recognises it as stdcall blah blah rather than this::wndproc(blah blah).

    >>I'm having a problem with this concept<<

    It's possibly not strictly necessary; I do it to make me feel happier but haven't noticed any problems (so far) by not doing it.

    Assuming you have a base wnd class (c++) from which you would derive, for example, a mainwnd, or a 'control', you can always put code into the class destructor to test if the wnd handle is valid when the control object is killed off. If it is, restore the original wndproc and call DestroyWindow on the control handle (assuming a c++ class control object encapsulates one and only one window control). I have a WNDPROC variable which I test - it should be NULL unless the control is subclassed, so if it's non-NULL the control must be subclassed so I would then use SetWindowLong to restore the original window procedure.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    SUCCESS!!!! All I had to do was return DefWindowProcedure from the window procedure. Thus, I don't need to store a pointer to the old procedure, nor do I need to reset the child's GWL_WNDPROC. I just set the child's to the parent's after creation, then return as above! I'm ecstatic! The tradidtional window procedure has forever dissapeared from my Windows programs...yay, no more switch statements!!
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Use a static wnd procedure so that the WNDPROC of the WNDCLASSEX recognises it as stdcall blah blah rather than this::wndproc(blah blah).
    Thanks! That helps a lot! I will change that now...( I was missing my "this"ness )


    /*edit*/ aww, forgot, still can't have "this". That's ok. I still like it better than "friend".
    Last edited by Sebastiani; 08-26-2002 at 12:47 PM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #13
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>SUCCESS!!!!<<

    Go on yourself, Sebastiani!

    >>no more switch statements<<

    So did you decided to go for some kind of functor then? (I still use msg macros from windowsx.h - sad but true ).
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    So did you decided to go for some kind of functor then?

    Sort of. Basically, all of the messages invoke a corresponding generic "class Window" virtual function. Thus, instead of having a window procedure, I will simply have to derive a class derived from a Window for EACH object created. I know this may sound convoluted, but it isn't really. It will, in effect, allow RAD to take effect quite naturally. I estimate that it will be around 80% faster to write a sophisticated application than currently is so. Lately, I have had to develop 3 non-trivial apps for a company I am working for, and the development cycle has been quite tedious and complex. i am the only developer! So one night I had this idea to create a more generic approach to it. I was already using classes for Windows, but not to this extent. Now that the subclassing and messaging is automatic and seamless, I can focus on the real programming, though. My next major overhaul is with the GDI, by the way...any suggestions?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  15. #15
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    No it doesn't sound convoluted - it's what I do too. I still have a virtual wndproc that the static wndproc forwards msgs to. It is in the body of this virtual wndproc (overriden as required) that I still have the msg macros in a switch to call individual virtual functions for each message I need to handle. This is convoluted and macros are apparently the devil's work when it comes to c++. I've been toying with one of those functor table type thingies off an on but to be honest I spend too much time here and at f-diddy.

    GDI: if you are writing for win2k/xp I would just go straight to GDI+ since it allegedly supercedes GDI. If not then msdn help is pretty good and there's heaps of stuff in www-land to be found.
    The GDI+ sdk can be found here:

    Go here to get GDI+ run-time dll - (it's called 'GDI+RTM'):

    http://www.microsoft.com/msdownload/...psdkredist.htm

    Note that winxp comes with gdiplus.dll as standard.

    edit: hopefully working link
    Last edited by Ken Fitlike; 08-26-2002 at 01:25 PM.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM