W32 message routing

This is a discussion on W32 message routing within the Windows Programming forums, part of the Platform Specific Boards category; I think ive read just about every article and post on the internet relating to this subject and rewritten this ...

  1. #1
    Registered User Noose's Avatar
    Join Date
    Jul 2003
    Posts
    11

    W32 message routing

    I think ive read just about every article and post on the internet relating to this subject and rewritten this code in about 20 different ways. Aside from the strange results from different ways of doing it (window is drawn, but doesnt initially show up, but windows that cover it leave a print on the desktop in the shape of the windows frame) I can never seem to get the pointer to the window back using using SetWindowLong() or GetWindowLong().
    Heres the code im using now, pParentWindow is always 0 no matter what i try so it never jumps into the "MessageHandler()" from this function


    Code:
    LRESULT CALLBACK W32Window::WinProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) 
    {	    
        //=========================================
        // FOR ERROR CHECKING
        char error[128] = {0};
        LONG_PTR r;
        DWORD err;
        //=========================================
        
        W32Window* pParentWindow = 0;
        int proc = 0;    
        
        if(uMessage == WM_CREATE) // Message comes to the window
        {              
            //LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;                                
            //pParentWindow = (W32Window*)lpcs->lpCreateParams;   
               
            r = ::SetWindowLong(hWnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams); // WARNING 1 
            if(r == 0)
            {
                err = GetLastError();                
                sprintf(error, "Error code \" %d \" by SetWindowLong..", err);
                MessageBox(NULL, error, "TEST2", MB_OK);	    
            }                                       
        }    
        else
        {
            pParentWindow = (W32Window*)::GetWindowLong(hWnd, GWL_USERDATA); // GWLP_USERDATA      , WARNING 2 
            if(pParentWindow == 0)
            {
                err = GetLastError();
                if(err != 0 )
                {             
                    sprintf(error, "Error code \" %d \" by GetWindowLong..", err);
                    MessageBox(NULL, error, "TEST3", MB_OK);	           
                }                
            }
        }
        
        if(pParentWindow)
        {
            pParentWindow->MessageHandler(uMessage, wParam, lParam); // Dropped MessageBox() in here to see if it ever goes into MessageHandler, but no
        }
    
    return DefWindowProc(hWnd, uMessage, wParam, lParam);       
    }
    Ive dropped " this " into CreateWindowEx()

    some things ive tried are:
    - Rewritting it in different ways (the above being one of the shorter versions), trying WM_CREATE instead of WM_NCCREATE, using switch to handle messages
    - Using Get/SetWindowLongPtr
    - Using Get/SetProp instead
    - Setting GWL_USERDATA or GWLP_USERDATA (depending) to 0 (seen that done a few times, but GetLastError just give me invalid index error code 1413?)

    right now the window shows but the process doesnt end when i hit exit on the window disappears (know why that is)

    and get the warnings
    warning C4311: 'type cast' : pointer truncation from 'LPVOID' to 'LONG'
    warning C4312: 'type cast' : conversion from 'LONG' to 'W32Window *' of greater size

    No matter what ive never been able to get the window back through Set/GetWindowLong(Ptr) what am i missing. Using .NET 2003

  2. #2
    Registered User dalek's Avatar
    Join Date
    May 2003
    Posts
    135
    Why aren't you doing this in a switch statement:

    Code:
    switch(msg)
    {
    case WM_CREATE:
       [stuff]
       return 0;
    
    case WM_DESTROY:
       PostQuitMessage(0);
       return 0;
    
    default:
       return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    What you have there is going to try to process the WM_CREATE message, and then for whatever other message you get (and there are quite a few that your window will get in the first couple of seconds) you are trying to do the stuff in your else block.

    What are trying to do with the pointer?
    [edit]
    I am kind of confused, it looks like you are trying to get a pointer to the object that you are already in (whats wrong with using the "this" pointer?? Your message procedure is a member of the same object isn't it??). And then you call a method from this object to handle messages? Is that right?

    Seems a bit odd to me, but I probably haven't stared at it hard enough.

    [another edit]
    GetLastError just give me invalid index error code 1413?)
    If you are using MSVC there is a program (i think it is called err.exe in the bin directory) that will give the error number and it will give you an english explanation for it. There is also an API call that you can use to print this error out in your program in english.. basically the same output as the err.exe program. I will post the function later when I get home and can consult some documentation.

    Forgot, WinProc is static.
    Note: no this-> in static member functions.
    Ahhh....
    Last edited by dalek; 03-03-2004 at 03:22 AM.

  3. #3
    Registered User Noose's Avatar
    Join Date
    Jul 2003
    Posts
    11
    Forgot, WinProc is static.
    Note: no this-> in static member functions.

    yes i know about error handling, just stating that i have seen 0 passed instead of GWL_USERDATA at times when trying to do this same sort of thing and yet i get errors while in other code i have seen it in (windowing system for a rendering engine) it seems to work
    Last edited by Noose; 03-03-2004 at 12:34 AM.

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Ive dropped " this " into CreateWindowEx()

    Just to be sure, you past it to the last parameter, right?

    >> r = ::SetWindowLong(hWnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);

    SetWindowLong is going to return it's previous value (which is going to be zero, in this case). So don't bother with the return value, in most cases.

    >> MessageBox(NULL, error, "TEST2", MB_OK);

    For some reason, MessageBox can produce some pretty erratic behavior in applications when used during window creation. I can't stress that enough! Use files instead.

    I really don't see anything else that may be causing this error, though, strange. Try this and see what happens:


    Code:
         if(message == WM_NCCREATE)
        {     
             if(lParam)
            {
             LONG handle = (LONG)((CREATESTRUCT*)lParam)->lpCreateParams;
             
                 if(handle)
                {         
                 SetWindowLong(hwnd, GWL_USERDATA, handle);
                } 
                 else
                {
                 FILE * fp = fopen("BigTimeErrors.txt", "a");
                 fprintf(fp, "Pointer was zero in WM_NCREATE\n");        
                 fclose(fp);
                } 
            }
             else
            {
             FILE * fp = fopen("BigTimeErrors.txt", "a");
             fprintf(fp, "lParam was zero in WM_NCREATE\n");        
             fclose(fp);
            }  
        }

    >> What are trying to do with the pointer?

    It has to be done like that in order to work with the class pointer from the WM_NCCREATE/WM_CREATE messages. If you didn't need to do anything from those two messages, you could simply bypass all of the above by setting the LONG right after calling CreateWindowEx(). A lot of work for two measly messages - right?
    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;
    }

  5. #5
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    A simple test program and browsing through winuser.h to match message numbers show that the following messages arrive before WM_CREATE.

    WM_QUEUESYNC
    WM_NCCREATE
    WM_NCCALCSIZE

    N.B: Different versions of windows likely add or subtract from this list. Do not rely on this list.

    Each of these will fall through to your else block where your code generates an error message because the pointer has not yet been set.

    The answer is to simply ignore these pre-WM_CREATE messages. If pParentWindow is NULL, assume it is one of these messages and continue.

    warning C4311: 'type cast' : pointer truncation from 'LPVOID' to 'LONG'
    warning C4312: 'type cast' : conversion from 'LONG' to 'W32Window *' of greater size
    MSVC is telling you that the code may fail on Win64. This is because a pointer will not fit into a LONG on Win64. You should use SetWindowLongPtr. However, due to how SetWindowLongPtr is defined on Win32(ie. a macro to SetWindowLong) you will probably still get this warning. It can be safely ignored in that case.

    GetLastError just give me invalid index error code 1413?)
    You need to reserve the memory in the cbWndExtra member of the WNDCLASSEX structure when you register the window class. For a discussion on methods of storing window data see this recent thread(especially note link to catch22 article):
    Custom control information

    ...but the process doesnt end when i hit exit on the window disappears (know why that is)
    The process does not automatically end when the last window is destroyed. You must call PostQuitMessage to exit the message loop. This is typically done in the WM_DESTROY message.

    Finally, you should not call DefWindowProc for messages that you handle. You should typically return 0;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Strange string behavior
    By jcafaro10 in forum C Programming
    Replies: 2
    Last Post: 04-07-2009, 08:38 PM
  2. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 04:25 AM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. Dialog Box Problems
    By Morgul in forum Windows Programming
    Replies: 21
    Last Post: 05-31-2005, 06:48 PM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 10:44 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21