Results 1 to 27 of 27

Thread: Prototype Elimination!!

  1. #1

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037

    Prototype Elimination!!

    I REALLY hate using prototypes. Is it possible to never use them? C# does not use them at all, I don't think they are at all necessary in C++ either.

    I have a Form class which is a window. I cannot process the window messages from the class. I have to use a global WndProc function and then pass the variables into a new class.

    Here is the problem, the form class needs to know about the global WndProc function and the WndProc function needs to know about the class.

    So I had to put a prototype of the WndProc function above the class. I want that nonsense to stop. I did not have to do that in Borland. Is this a compiler issue?

  2. #2
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    No, it's not. Not a specific compiler at least.

    C compilers basically are top-down compilers. They read and use line by line of the source. C# and Java compilers are lookahead compilers.
    The difference is that if a C compiler encounters a symbol it doesn't know, it immediatly fails. A C# compiler first checks the rest of the source file and even some other source files if it can find the symbol being declared somewhere. Only if that too is useless, it fails.

    C++ compilers are hybrids. Usually they still show the same behavior as a C compiler, but in some cases they don't.

    The reason why C works that way is that C was originally intended as a minimal language. The programs it creates are fast and small. This is to accommodate weak computers with little storage space. And the compiler should do the same. Top-down compilers are easier to implement than the other sort. Thus the requirement of function prototypes.

    It's possible to write a C/C++ program completly without prototypes, but only if it's limited to a single source file and you don't have any round-calling functions (a calls b, b calls a, or similar things with more functions).

    For your specific problem, I recommend two changes.
    First, your class declaration probably doesn't need to know about the global WndProc, so you can simpy define the WndProc above the class implementation.
    Second, screw the global function altogether. Declare it as static private member of the class. Makes much more sense that way.

    Finally, I have no idea why you don't like prototypes. I think they are a great self-documentation of source code.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  3. #3

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    They would be ok if I did not make changes the the source code. I just don't like making 2 changes instead of one.

    About the static WndProc, the downside to using a static WndProc is that it cannot access the instance members of the class. And I need access to them.

  4. #4
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Neither can the global. Here's how I do it (from a current project of mine):
    Code:
    // Header File:
    class Application
    {
    	int app_main(HINSTANCE instance, tchar_t *cmdline, int showcmd);
    	static LRESULT CALLBACK WndProcStub(HWND hwnd, UINT msg, WPARAM w, LPARAM l);
    protected:
    	HINSTANCE app_instance;
    	HWND app_hwnd;
    	virtual LRESULT WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l);
    	// ...
    };
    
    // Implementation
    int Application::app_main(HINSTANCE instance, tchar_t *cmdline, int showcmd)
    {
    	app_instance = instance;
    	// Create a window etc...
    	::WNDCLASS wc;
    	// ...
    	wc.lpszClassName = _T("T3D Game Window Class");
    	::RegisterClass(&wc);
    
    	app_hwnd = CreateWindow(_T("T3D Game Window Class"),
    		_T("T3D Game"), get_window_flags(), CW_USEDEFAULT,
    		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
    		NULL, instance, static_cast<void *>(this));
    
    	::ShowWindow(hwnd_app, showcmd);
    	::UpdateWindow(hwnd_app);
    
    	// Enter message loop
    	MSG msg;
    	while(::GetMessage(&msg, NULL, 0, 0) > 0)
    	{
    		::TranslateMessage(&msg);
    		::DispatchMessage(&msg);
    	}
    
    	return static_cast<int>(msg.wParam);
    }
    
    LRESULT CALLBACK Application::WndProcStub(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
    {
    	if(msg == WM_NCCREATE)
    	{
    		::CREATESTRUCT *pcs = reinterpret_cast<::CREATESTRUCT *>(l);
    		::SetWindowLongPtr(hwnd, 0,
    			reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
    	}
    	Application *pthis = reinterpret_cast<Application *>(
    		::GetWindowLongPtr(hwnd, 0);
    	return pthis->WndProc(hwnd, msg, w, l);
    }
    
    // etc...
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  5. #5
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    As for code changes - yeah, I don't like that part either, but you could see it as punishment for not planning properly
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  6. #6

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    This will not compile:
    ::CREATESTRUCT *pcs= reinterpret_cast<::CREATESTRUCT*>(lParam);
    Error: Parse error before ;

    This will but you know better than I do, CRASH!

    ::CREATESTRUCT *pcs;

    The compiler does not like something here:
    = reinterpret_cast<::CREATESTRUCT*>(lParam);

  7. #7

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    It did not like the :: before reinterpret_cast<CREATESTRUCT*>.

    Code:
    static LRESULT CALLBACK WndProcStatic(HWND h, UINT m, WPARAM wParam, LPARAM lParam)
        {
    
        switch(m)                 
        {
            case WM_NCCREATE:
            {
              ostringstream oss;
              
              ::CREATESTRUCT *pcs= reinterpret_cast<CREATESTRUCT*>(lParam);
              oss<< pcs<<"  "<< lParam<<"  "<<
    		      ::SetWindowLongPtr(h, 0, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
              MessageBox(NULL, oss.str().c_str(), "", MB_OK); 
    		    }
    		
    		default:
    		{
          Form *pthis= reinterpret_cast<Form*>(::GetWindowLongPtr(h, 0));
    ostringstream oss;
    oss<< pthis<<"  "<<"  "<<GetWindowLongPtr(h, 0);
                if(!pthis)
                {
                  MessageBox(NULL, oss.str().c_str(), "", MB_OK);
                  return 0;
                }
    			return pthis->WndProc(h, m, wParam, lParam);
    		}
        }
    The program produces a fatal error. Is ::SetWindowLongPtr supposed to return 0? Because it does. ::GetWindowLongPtr also returns 0.

    First default is called then WM_NCCREATE, and then default again, then the program crashes in default trying to use a pointer that points to nothing. That is if I did not stop it by returning 0 before if got to: return pthis->WndProc(h, m, wParam, lParam);
    Last edited by aewarnick; Jul 22nd, 2003 at 06:37 PM.

  8. #8

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    I am using the extended window style so I changed the 0's in GetWindow and SetWindow to GWL_EXSTYLE and now none of the messageboxe's show indicating that the variables are initialized but I still get the same error when it tries to return the WndProc.

    Or maybe it is because my createparameters are 0:
    pcs->lpCreateParams shows 0. If that is it, how do I change it?
    Last edited by aewarnick; Jul 22nd, 2003 at 08:52 PM.

  9. #9

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Got it working. Your code confused me. It looks like you wanted the part I have in default not return the DefWindowProc(). So what I tried was putting all that code in WM_NCCREATE and it works.

  10. #10
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    I haven't tested the code yet

    And the :: is because my code is in a namespace.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  11. #11
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    I never use a default: in my WndProcs. I like my way better.

    Which works like this:
    Code:
    WndProc
    {
      switch(msg)
      {
      case WM_SOME:
        // Handled
        return 0;
    
      case WM_OTHER:
        // Handled, but we still want default action
        break;
      }
      // Default action
      return DefWindowProc();
    }


    The reason why my code doesn't contain a DefWindowProc call is that this call is in the true WndProc.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  12. #12

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Every time the program starts, the pthis pointer is not initialized right away so I always get my messagebox error. I don't think that should be the case. What did I do wrong?
    Code:
    case WM_NCCREATE:
            {
              ::CREATESTRUCT *pcs= reinterpret_cast<CREATESTRUCT*>(lParam);
    		      ::SetWindowLongPtr(h, 0, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
              
              Form *pthis= reinterpret_cast<Form*>(::GetWindowLongPtr(h, 0));
              if(!pthis)
              {
                MessageBox(NULL, "create", "Error", MB_OK);
                //return -1;
                //return 0;
              }
              else
    	         return pthis->WndProc(h, m, wParam, lParam);
    		    }
    Last edited by aewarnick; Jul 23rd, 2003 at 06:02 AM.

  13. #13
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Check if WM_NCCREATE is really the first message the WndProc receives. If not, I need to change my code (and you too )
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  14. #14

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    No it's 36, whatever that is.

  15. #15

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    I tried using 36 and also WM_CREATE but both do the same:
    Code:
    static LRESULT CALLBACK WndProcStatic(HWND h, UINT m, WPARAM wParam, LPARAM lParam)
        {
        ostringstream oss;
        oss<< m;
        //MessageBox(NULL, oss.str().c_str(), "Error", MB_OK);
    
        switch(m)                 
        {
            case 36:
            {
              ::CREATESTRUCT *pcs= reinterpret_cast<CREATESTRUCT*>(lParam);
    		      ::SetWindowLongPtr(h, 0, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
              
              Form *pthis= reinterpret_cast<Form*>(::GetWindowLongPtr(h, 0));
              if(!pthis)
              {
                MessageBox(NULL, "create", "Error", MB_OK);
              }
              else
    	         return pthis->WndProc(h, m, wParam, lParam);
            break;
    		    }
        }
    
        return DefWindowProc(h, m, wParam, lParam);
        }

  16. #16

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    It works without most of that code too for some reason:
    ::CREATESTRUCT *pcs= reinterpret_cast<CREATESTRUCT*>(lParam);
    ::SetWindowLongPtr(h, 0, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
    That is all that is in NCCREATE and it works.
    Should that be ok?

  17. #17
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Uh... what?
    Isn't that what I had all along?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  18. #18

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Here is what you had:
    Code:
    LRESULT CALLBACK Application::WndProcStub(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
    {
    	if(msg == WM_NCCREATE)
    	{
    		::CREATESTRUCT *pcs = reinterpret_cast<::CREATESTRUCT *>(l);
    		::SetWindowLongPtr(hwnd, 0,
    			reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
    	}
    	Application *pthis = reinterpret_cast<Application *>(
    		::GetWindowLongPtr(hwnd, 0);
    	return pthis->WndProc(hwnd, msg, w, l);
    }

  19. #19
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    36 would be WM_GETMINMAXINFO...
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  20. #20
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    This should never crash. And I missed a closing parenthesis.
    Code:
    LRESULT CALLBACK Application::WndProcStub(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
    {
    	if(msg == WM_NCCREATE)
    	{
    		::CREATESTRUCT *pcs = reinterpret_cast<::CREATESTRUCT *>(l);
    		::SetWindowLongPtr(hwnd, 0,
    			reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));
    	}
    	Application *pthis = reinterpret_cast<Application *>(
    		::GetWindowLongPtr(hwnd, 0));
    	if(pthis)
    		return pthis->WndProc(hwnd, msg, w, l);
    	else
    		return ::DefWindowProc(hwnd, msg, w, l);
    }
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  21. #21

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Guess what? Your not going to like this, it does not work. I did a little experiment and took everything out of WM_NCCREATE and I got the same results- the program seemed to work correctly.

    I came to find out that the Window process that the instance form's process was calling was the static one and not the one it should be calling.

    Something must not be working right with this:
    ::CREATESTRUCT *pcs= reinterpret_cast<CREATESTRUCT*>(lParam);
    ::SetWindowLongPtr(h, 0, reinterpret_cast<LONG_PTR>(pcs->lpCreateParams));

  22. #22

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Here is where I got the idea to use a global WndProc:
    http://www.rpi.edu/~pudeyo/articles/wndproc/
    He does not mention anything like this. Maybe it can't work?
    Look that over and tell me what you think.

  23. #23

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    This one is the most like yours, although he still talks about using a global WndProc and not a static. But I think static should work the same way.
    "Per-Window Data"

  24. #24
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Static and global are binary equivalent.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  25. #25

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Have you tried your code out yo see if you can get it working? I could not get either to work.

  26. #26
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    No, not yet. And I will not for some days, I'll not be at home.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  27. #27

    Thread Starter
    Frenzied Member aewarnick's Avatar
    Join Date
    Dec 2002
    Posts
    1,037
    Ok. If I figure out how to get this working i'll post back, if not i'll just be looking forward to whatever you come up with.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width