stopping application on window close with OF_WINDOW

I don’t know if it could be called a bug but…

if I close the app with the esc key, both the opengl screen and the command-line terminal are closed, but if I do it with the X key (using OF_WINDOW instead of OF_FULLSCREEN), the command-line remains running. I have to close it manually…

hi jesus,

thanks for pointing that out… I think that’s a feature of glut, because in glut you can open and close windows, as well as iconify them. Since we aren’t using that functionality of glut, it might make sense to take the window close as a cue to exit -

thanks! - zach

sorry –

I don’t see a quick way to fix this

there is a patched glut here, which fixes this problem:
http://www-users.york.ac.uk/~rpf1/glut.html

it’s in the FAQ of glut, which talks about the hack
http://www.opengl.org/resources/faq/technical/glut.htm

I’m looking for other solutions in the meantime…

take care!
zach

does freeGlut have the bug? (or “feature”)

http://freeglut.sourceforge.net/

(does of use freeglut or glut??)

hi -

Freeglut, I’m pretty sure, fixes it (and a bunch of other glut issues) but I am not sure about freeGlut’s availbility on all three platforms —

I see stuff like this online about it:

  1. The FreeGLUT for OS X from Fink works with OS X X11 but Xcode wasn’t able to launch it correctly. i.e. FreeGLUT from Fink doesn’t work with quartz OS X windows yet. It’ll be sweet when the FreeGLUT creators build that in.

We currently use freeglut in linux OF, regular glut in windows / osx OF.

take care,
zach

hmm - I am wondering if we couldn’t get the window HWND using the same trick for fake fullscreen and then override the close button behavior - this would be nice because it would completely bypass having to hack glut.

some stuff I found seems to imply that you can both remove the button altogether as well as catching the WM_CLOSE message:

http://www.codeguru.com/forum/archive/i-…-63433.html

Okay I got it working. Basically we get the window handle, use the window handle to get the glut message handler, we then store that message handler and give the window our new message handler. Ourmessage handler listens for the close and destroy messages and calls OF_EXIT_APP - all other messages are passed onto the glut message handler.

D O P E!

The only issue is that the way we get the window handle is by looking for either the GLUT process name or the openFrameworks window title - both of which could exist for more than one app. I am sure there is a better way to get the window handle of a current process. But here is the code for now.

  
#ifdef TARGET_WIN32  
  
WNDPROC currentWndProc;  
  
LRESULT CALLBACK winProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)  
{  
    switch(Msg)  
    {  
	case WM_CLOSE:  
		//printf("I am being closed\n");  
		OF_EXIT_APP(0);  
	break;  
	case WM_DESTROY:  
        	//printf("I am being destroyed\n");  
		OF_EXIT_APP(0);  
        break;  
	default:  
                //we give all other messages back to glut - aren't we nice :)  
		return currentWndProc(hwnd, Msg, wParam, lParam);  
	break;  
    }  
  
    return 0;  
}  
  
//--------------------------------------  
static void fixCloseWindow(){  
    //find our window handle - we should find a better way of doing this  
    HWND vWnd  = FindWindow(L"GLUT", NULL);  
  
    //store the current message handler  
    currentWndProc = (WNDPROC)::GetWindowLong(vWnd, GWL_WNDPROC);  
      
    //tell it to use our message handler instead  
    SetWindowLong(vWnd, GWL_WNDPROC, (long)winProc);  
}  
  
#endif  
  

cool !! nice research !

I’m happy to have a fix for this – it’s been really annoying and unclean in a way, so good to get closing the window close to ESC.

can’t wait to hook it up – zach

ps :

since the window you create is the top-most after OF starts up you could do this:

  
  
HWND wnd = WindowFromDC(wglGetCurrentDC());  
  

to get the window (and avoid conflicts, I’d bet) as compared to using the title. this is what I use when I need to hook up libraries like the wacom library that need to talk to the window at a low level…

-zach

Awesome, I was facing this problem earlier. So guys where do you intend to amend the changes?

Nice - I imagine that is more foolproof than the method I am using.
Looks like the sure method is to get the processID of your app and then use that to return the window handle. There is no direct way to do this but the general method is to go through every window in the system and check the windows process id till it matches your apps process id.

  1. GetCurrentProcessID - get your apps process id
    http://msdn2.microsoft.com/en-us/library/ms683180(VS.85.aspx

  2. EnumWindows - loop through all hwnd
    http://msdn2.microsoft.com/en-us/library/ms633497(VS.85.aspx

  3. GetWindowThreadProcessId() - gets the process id of the windows
    http://msdn2.microsoft.com/en-us/library/ms633522(VS.85.aspx

I’ll do another test later - with this approach. Otherwise the top most approach should be fine too.

Theo

So guys where do you intend to amend the changes?

we are working on it, and it could wind up (at least for windows) in 0.05. this solution is only for windows, we need to work on mac and linux too. for now, of course, ESC will quit the app just fine - z

Okay so I got the working code. Seems to work well!
Tested on VS in debug mode - need to test CW and DevC++

Learned some interesting things.
There are three windows associated with the openFrameworks process.
The console window, the glut window and an invisible openGL context.

This code enumerates through all windows and when it finds ones matching the process id it checks to make sure it gets the handle to just the glut window.

As a fallback if it can’t get the handle this way it gets the topmost window handle which should also be the glut app.

This code works for both clicking on the [x] button and control clicking on the tasking bar and selecting close.

  
#ifdef TARGET_WIN32  
  
static WNDPROC currentWndProc;  
static HWND handle  = NULL;  
  
static bool CALLBACK EnumWindowsProc(HWND hWnd, LPARAM processID){  
  
	//get the process id for each window  
	DWORD tempID = 0;  
	GetWindowThreadProcessId(hWnd, &tempID);  
  
	if( tempID == (DWORD)processID){  
		//three windows are associated with our id  
		//a console window, the glut window and an invisible gl context  
		//we get the name of each window to determin which is the one we want  
		wchar_t name[256];  
		GetClassName(hWnd, name, 255);  
		  
		//if you want to see the process names  
		//wprintf(L"class name is %s \n", name);   
		  
		//we check the process name to see if it GLUT  
		//if so we store the handle and then stop the search  
		if( wcsncmp(name, L"GLUT", 4) == 0 ){  
			handle = hWnd;	  
			return false;  
		}  
  
	}  
	return true;  
}  
  
static LRESULT CALLBACK winProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam){	  
	  
	//we catch close and destroy messages  
	//and send them to OF  
	switch(Msg){  
		case WM_CLOSE:  
			OF_EXIT_APP(0);  
		break;  
		case WM_DESTROY:  
			OF_EXIT_APP(0);  
			break;  
		default:  
			//all other messages our handled by glut  
			return currentWndProc(hwnd, Msg, wParam, lParam);  
		break;  
    }  
  
    return 0;  
}  
  
//--------------------------------------  
static void fixCloseWindow(){  
	  
   //we get our current process id  
   DWORD ourProcessID = GetCurrentProcessId();  
  
   //we run through all windows and look for windows matching  
   //our process id  
   EnumWindows((WNDENUMPROC)EnumWindowsProc, ourProcessID);  
  
   //a fallback incase no window handle is found  
   //we use the top most.  
   if(handle == NULL){  
		handle = WindowFromDC(wglGetCurrentDC());   
   }  
	  
   //store the current message event handler for the window  
   currentWndProc = (WNDPROC)::GetWindowLong(handle, GWL_WNDPROC);  
     
   //tell the window to now use our event handler!  
   SetWindowLong(handle, GWL_WNDPROC, (long)winProc);  
}  
  
#endif  

Hi,
Where we might put the code Theo has posted?
I’ve tried in testApp.cpp and the application just hangs.
I’m using CodeBlocks, release mode, running in Windows.
Thanks,
Anna

this code doesn’t work with mingw, therefore, we didn’t put it into the main OF release. :slight_smile:

take care!
zach

I force the application to close at certain time.
Maybe it’s ugly code :? but getting the ProcessID and using TerminateProcess does it.
Ugly code but it works!
Thanks for your help.
Anna.

Why does the ESC key work properly however when you use other close techniques it hangs… In that case couldn’t we send a fake “ESC” keyboard event…?

Is there a final “fix” for this?

I tried simulating a ESC key, but that didn’t seem to work.

Of the previously mentioned methods, which should I use? Or, is there a final fix that hasn’t been mentioned?

I tried the code posted in visual studio. I put it in testApp.cpp and it didn’t do anything.

Where should I be putting this code?

I am resurrecting this post in the hopes it will lead to a solution.

Has anyone been able to find a fix or workaround, using Code::blocks and the MinGW compiler?

Paul