wxWidgets Closing window from system menu - wxwidgets

I am working on wxWidgets, In wxFrame I handled wxEVT_CLOSE event, inside the event handler I called Iconize(). When pressing the close button my window will be minimized it is work correctly. But while clicking quit from my system menu that time also my window is minimizing. But in my scenario I want to close my window from system menu and want to minimize while clicking close button.
This is my handler.
void Frame::OnClose(wxCloseEvent& event)
{
Iconize(true);
}

You can't distinguish between closing the window from the system menu and using the close button at wxWidgets API level. You can, however, do it using platform-specific code. For example, for MSW you can override MSWWindowProc() in your wxFrame-derived class and handle WM_SYSCOMMAND there and explicitly exit the application, instead of just iconizing it, when SC_CLOSE is received.

Just process menu command in other handler and call Destroy directly.
BEGIN_EVENT_TABLE(wxMyFrame,wxFrame)
EVT_MENU(wxMyFrame::idMenuQuit, wxMyFrame::OnMenuClose) // sample for using event table
END_EVENT_TABLE()
void wxMyFrame::OnMenuClose(wxCommandEvent& event)
{
Destroy();
}

Related

How to implement correct Back behaviour when using Frame.Navigate?

I have a Windows 10 Universal Windows Platform app with multiple pages, a main page, a list page and a details page and use the following to navigate to List page:
this.Frame.Navigate(typeof(ListPage), parameter);
When you are on the list page you can select an item which will launch a details page like so:
this.Frame.Navigate(typeof(DetailsPage), parameter);
Which works fine, the parameter is a selected Id or information then when using the Back button which on a Desktop app or Phone uses:
this.Frame.GoBack();
This always returns to the MainPage, that is when go from Main, to List to Details hitting back goes to Main, how do I get the GoBack to Go back to the previous page, it always seems to go home rather than the user expected behaviour, an ideas how to resolve this?
I’ve seen this before when you subscribe to the HardwareButtons.BackPressed event (or whatever the equivalent is in a Win10 UWP app) on a page, but then don’t unsubscribe from it. This means two event handlers get called when pressing Back, and both event handlers call Frame.GoBack().
I always subscribe to the event in the page’s NavigatedTo event, and unsubscribe in the NavigatedFrom event.
Could this be happening with your app?
If every page in your app should have the same behaviour, i.e. go back to the previous page, then subscribe to the back button event in the app class as suggested by #RoguePlanetoid in the comments:
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
The OnLaunched method would be a good place to do this. Don't forget to tell the OS to display the back button when the app is running on a desktop or tablet:
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
Then, add an event handler in the app class like this:
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
If you want different behaviour on different pages when back is pressed, i.e. ask the user to confirm losing their changes or something, then subscribe to the back button event in a pages OnNavigatedTo method (the code will be same as above), but make sure you unsubscribe in the page's OnNavigatedFrom event:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested -= this.OnBackPressed;
base.OnNavigatedFrom(e);
}

how to see mouseReleased() event outside canvas using processing.js

I have an object I want to drag around the screen with the mouse in Processing. I set acquired to true on mouse down over the object, and to false on mouse up, thus:
void mousePressed() {
if (overThing()) {
acquired = true;
}
}
void mouseReleased() {
acquired = false;
}
I then query acquired in my update(), and drag the object if it is true.
void update() {
\\ other stuff...
if (acquired) {
\\ drag thing code ...
}
}
This all works fine in Processing. mouseReleased() gets called whether I release the mouse inside or outside the active window.
However, when I move the code to Chrome, using processing.js (v1.4.8), mouseReleased() is not called if I release the mouse outside the canvas (whether the mouse is still over the web page, or outside the browser window). So when I return the (now unclicked) mouse to the canvas, the object is still getting dragged around.
I tried including a test of mousePressed in update(), but that also returns true in these circumstances.
Any help on what I need to do to make mouse state changes outside the canvas visible with processing.js?
I don't know about Processing specifically, but releasing mouse buttons outside a widget is a common issue in GUI development.
I suspect that you have no way of knowing the precise time when the mouse is released outside the widget, but you do have two options:
Set acquired = false in mouseOut(), as #Kevin suggests.
I assume there is some type of mouseEntered() method in Processing, and also some way of knowing if the mouse button is currently pressed (either a global variable, or an event object passed to mouseEntered()). You can catch the mouse entered event, check if the mouse has been released, and set acquired = false then.
Like so:
void mouseEntered() {
if (mouse button is pressed) {
acquired = false;
}
}
Edit: From your comments, #Susan, it seems like there is a bug in processing.js, where mousePressed is not set to false if the mouse button is released outside the canvas. One thing pointing to this being a bug is that the mouse movement example on the processing website also shows this behaviour.
Depending upon how much control you have over the website this is going on, and how much effort you want to go to, you could fix the bug yourself by writing some javascript (separate from your processing code):
Define a mouseUp() event on the page <body>, to catch all mouse release events on the page.
In the mouseUp() event, check if the event comes from your Processing control. (There is probably an event object passed to the mouseUp() function, and you might have to give your Processing control an ID to identify it)
If the event doesn't come from your Processing control, then fire a mouseUp event yourself, on the Processing control. This should (hopefully!) trigger a mouse event inside your Processing code.
I'm not sure what Processing will make of the mouse (x,y) position being outside its control when it handles the event you send it. You might want to set a flag on the event object (assuming you can add extra data to the event object) to say "don't use the (x,y) position of this event - it's outside the control".
Edit2: It was easier than I thought! Here is the JavaScript code to detect the mouse being released outside of the Processing canvas and send the mouseReleased event to the canvas. I've tested it on the mouse movement example from the Processing website, and it fixes the bug.
It uses jQuery (although it could be re-written to not use jQuery), and it assumes your Processing canvas has the ID "processingCanvas":
$(':not(processingCanvas)').mouseup(function(){
Processing.getInstanceById('processingCanvas').mouseReleased();
});
To use this code, include it anywhere in your page (in a JavaScript file or in <script> tags) and make sure you have the jQuery library included before this code.
The Processing object allows JavaScript to call any functions defined in your Processing code. Here I've used it to call Processing's built in mouseReleased() function, but if you wanted to call a custom function to handle the mouse-released-outside state differently, then you could.
You should use the mouseOut() function to detect when the mouse leaves the sketch:
void mouseOut() {
acquired = false;
}
More info in the reference here.

How to programatically close a JFace Dialog in Eclipse Application

I want to programatically close a JFace Dialog in eclipse application. The Dialog is being created using a Handler:
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window =HandlerUtil.getActiveWorkbenchWindowChecked(event);
CustomDialog dialog = new CustomDialog(window.getShell());
dialog.open();
}
Now the 'Custom Dialog' runs a background thread and I want to close this dialog once the background thread completes. Is there a way to do this programatically , similar to what we can do for editors and views.
Just call the dialog close() method.
Note that you must do this in the User Interface thread so a background thread would need to use Display.asyncExec.

MessageBox.Show in App Closing/Deactivated events

I have a MessageBox being shown in Application Closing/Deactivated methods in Windows Phone 7/8 application. It is used to warn the user for active timer being disabled because app is closing. The App Closing/Deactivated events are perfect for this, because putting logic in all application pages would be a killer - too many pages and paths for navigation. This works just fine - message box displays OK in WP7.
I also know for breaking changes in the API of WP8. There it is clearly stated that MessageBox.Show in Activated and Launching will cause exception.
The problem is that in WP8 the message box does not get shown on app closing. Code is executed without exception, but no message appears.
P.S. I've asked this on MS WP Dev forum but obviously no one knew.
Move the msgBox code from the app closing events and into your main page codebehind. Override the on back key press event and place your code there. This is how it was done on 7.x:
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (MessageBox.Show("Do you want to exit XXXXX?", "Application Closing", MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
{
// Cancel default navigation
e.Cancel = true;
}
}
FYI - On WP8 it looks like you have to dispatch the MsgBox Show to a new thread.
This prompts the user before the app ever actually starts to close in the event model. If the user accepts the back key press is allowed to happen, otherwise its canceled. You are not allowed to override the home button press, it must always go immediately to the home screen. You should look into background agents to persist your timer code through suspend / resume.
Register BackKeyPress event on RootFrame.
RootFrame.BackKeyPress += BackKeyPressed;
private void BackKeyPressed(object sender, CancelEventArgs e)
{
var result = (MessageBox.Show("Do you want to exit XXXXX?", "Application Closing", MessageBoxButton.OKCancel));
if (result == MessageBoxResult.Cancel)
{
// Cancel default navigation
e.Cancel = true;
}
}

Why isn't the LostFocus event occurring?

With a listbox visible, I have clicked on the windows form hoping to use the listbox.lostfocus event to let me hide the listbox - but the event does not occur. I suppose I can use the form.click event to hide the listbox, but how would I get the form to accept focus?
A Form does not want to receive the focus. It was designed to be a container control, it makes sure that one of its child controls always gets the focus. It is technically possible to whack it over the head and make it lose that behavior:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.SetStyle(ControlStyles.ContainerControl, false);
}
protected override void OnClick(EventArgs e) {
this.Focus();
base.OnClick(e);
}
}
This is however a bad idea. A Form doesn't have any way to indicate that it has the focus, you'll also have to override OnPaint() to do something like draw a focus rectangle. If you don't then the user completely loses track of where the focus is located. Then there's the considerable inconvenience that nothing interesting can happen when the user uses the keyboard, a form doesn't have a use for it.
Don't do this. If you want to make a control disappear then add a menu item, toolbar button or a normal button to your UI. Something the user can click on.
the LostFocus event work when the focus move to another control like textbox,... or when the form all of it lost the focus you can use click event for the form to detect taht