customizing application close

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
ericaus
Posts: 14
Joined: Sat Sep 19, 2009 10:53 am
Location: Australia

customizing application close

Post by ericaus »

hello,
I recently started using Irrlicht a couple of days ago, with C++ and just wondering how do I go about making it so when Alt+F4 or the X button is pressed on the application window, a message box is created by addMessageBox with a yes & no button, and if yes is pressed the program closes, but if no the program stays opened?

I've been trying to figure out how to do this but couldnt... please help.
omar shaaban
Posts: 616
Joined: Wed Nov 01, 2006 6:26 pm
Location: Cairo,Egypt
Contact:

Post by omar shaaban »

since this is related to the windows api rather than irrlicht as irrlicht cant execute a command while application is closing(or whatever) so u have to use win api which means not a console application but rather windows api application
here's the code (found at msdn) it doesn't need explanation the code simply send message if exit function is called and when user says no it breaks and returns to the program(cancel exit function)

Code: Select all

case WM_CLOSE:
{
    if (MessageBox(hWnd, "Are You Sure You Want To Exit?", "Exit", MB_YESNO) == IDYES)
    {
        PostQuitMessage(0);
    }
    else
        return 0;
}break;
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Post by serengeor »

omar shaaban you helped me out too :)
I never knew how to check what user presses on a message box lol :D
Thank you very much
Working on game: Marrbles (Currently stopped).
omar shaaban
Posts: 616
Joined: Wed Nov 01, 2006 6:26 pm
Location: Cairo,Egypt
Contact:

Post by omar shaaban »

no problem :wink:
ericaus
Posts: 14
Joined: Sat Sep 19, 2009 10:53 am
Location: Australia

Post by ericaus »

cool it works :D I placed that into the WndProc in CIrrDeviceWin32.cpp, and commented out the WM_DESTROY case. Thanks :D

Edit:: Awesome, I just found out theres some dev = getDeviceFromHWnd(hWnd); inside some of the other switch cases. I now tried doing something like,

Code: Select all

case WM_CLOSE:
{
    dev = getDeviceFromHWnd(hWnd);

    if (dev)
    {
        dev->getGUIEnvironment()->addMessageBox(L"Test", L"T", true, irr::s32(0x4) | irr::s32(0x8));
    }
} break;
that seems to work. :D I just gotta figure out how to make it so only 1 can popup instead of many, and then give the yes button a PostQuitMessage(0) event.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You could also just use postEventFromUser() and eat the message right there. Something like this...

Code: Select all

case WM_CLOSE:
  // you'd need to add additional minor changes to IEventReceiver.h
  event.EventType = irr::EET_WINDOW_EVENT;
  event.WindowEvent.EventType = irr::EWE_APPLICATION_CLOSE;

  dev = getDeviceFromHWnd(hWnd);

  // tell the user event receiver that the app requested a close event
  if (dev && dev->postEventFromUser(event)) {

    // device pointer was valid, and the user event receiver
    // consumed the event. assume user event receiver will
    // exit the application if necessary. return now.
    return 0;
  }

  // device pointer was invalid, or user event receiver failed to
  // consume the event. this break causes us to do the default,
  // which will allow the application to exit. this should maintain
  // existing behavior for apps that don't explicitly handle this
  // event type.
  break;
That way you can write a user event receiver that properly handles the message and causes the application to exit in the same way as it would if the user had pressed a quit button inside the application...

Code: Select all

struct MyEventReceiver : public IEventReciever
{
  MyEventReceiver (IrrlichtDevice* device)
    : Device(device)
  {
  }

  virtual bool OnEvent(const SEvent& ev)
  {
    if (ev.EventType == EET_WINDOW_EVENT &&
        ev.AppEvent == EWE_APPLICATION_CLOSE)
    {
      gui::IGUIEnvironment* gui = Device->getGUIEnvironment();
      assert (gui);

      gui->addMessageBox(L"Test", L"T", true, EMBF_YES | EMBF_NO);
      return true;
    }
    else if (ev.EventType == EET_GUI_INPUT_EVENT &&
             ev.GUIEvent.EventType == EGET_MESSAGEBOX_YES)
    {
      Device->closeDevice();
      return true;
    }
  }

private:
  IrrlichtDevice* Device;
};
A change like this would be appropriate for putting into the engine so other users can take advantage of the enhancement without needing to modify the engine source. It also has the advantage that you don't need to rebuild the Irrlicht.dll every time you decide you want to change an attribute of the message box.

Travis
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, better support for system events is on our list, maybe someone could put this code and the request into a ticket?
ericaus
Posts: 14
Joined: Sat Sep 19, 2009 10:53 am
Location: Australia

Post by ericaus »

vitek wrote:You could also just use postEventFromUser() and eat the message right there. Something like this...

Code: Select all

case WM_CLOSE:
  // you'd need to add additional minor changes to IEventReceiver.h
  event.EventType = irr::EET_WINDOW_EVENT;
  event.WindowEvent.EventType = irr::EWE_APPLICATION_CLOSE;

  dev = getDeviceFromHWnd(hWnd);

  // tell the user event receiver that the app requested a close event
  if (dev && dev->postEventFromUser(event)) {

    // device pointer was valid, and the user event receiver
    // consumed the event. assume user event receiver will
    // exit the application if necessary. return now.
    return 0;
  }

  // device pointer was invalid, or user event receiver failed to
  // consume the event. this break causes us to do the default,
  // which will allow the application to exit. this should maintain
  // existing behavior for apps that don't explicitly handle this
  // event type.
  break;
That way you can write a user event receiver that properly handles the message and causes the application to exit in the same way as it would if the user had pressed a quit button inside the application...

Code: Select all

struct MyEventReceiver : public IEventReciever
{
  MyEventReceiver (IrrlichtDevice* device)
    : Device(device)
  {
  }

  virtual bool OnEvent(const SEvent& ev)
  {
    if (ev.EventType == EET_WINDOW_EVENT &&
        ev.AppEvent == EWE_APPLICATION_CLOSE)
    {
      gui::IGUIEnvironment* gui = Device->getGUIEnvironment();
      assert (gui);

      gui->addMessageBox(L"Test", L"T", true, EMBF_YES | EMBF_NO);
      return true;
    }
    else if (ev.EventType == EET_GUI_INPUT_EVENT &&
             ev.GUIEvent.EventType == EGET_MESSAGEBOX_YES)
    {
      Device->closeDevice();
      return true;
    }
  }

private:
  IrrlichtDevice* Device;
};
A change like this would be appropriate for putting into the engine so other users can take advantage of the enhancement without needing to modify the engine source. It also has the advantage that you don't need to rebuild the Irrlicht.dll every time you decide you want to change an attribute of the message box.

Travis
:D I like the sound of this, I might need to do some research on it and figure out where to place WindowEvent, AppEvent and EWE_APPLICATION_CLOSE in IEventReceiver.h.
Post Reply