When the user closes my application I'd like to be able to prompt them with a confirmation if they have unsaved changes, and cancel the application's closing if they indicate to do so. The Application's Exit event does not allow cancellation. Is there any way to do this?
Catch the Closing event of the MainWindow instead:
App.Current.MainWindow.Closing += MainWindow_Closing;
Then you can set the Cancel property to true in the event handler if necessary:
private void MainWindow_Closing(object sender, System.ComponentModel.ClosingEventArgs e)
{
e.Cancel = true;
}
Hope this helps...
Chris
Related
We've inherited some code for a VSTO Outlook Add-In that pops up a modal dialog sort of as an acknowledgement to the end user before sending an email.
The dialog is fired on the Application_ItemSend event
Private Sub Application_ItemSend(ByVal Item As Object, ByRef Cancel As Boolean) Handles Application.ItemSend
The problem that we're seeing is that when we show the dialog:
objCheckDialog.ShowDialog()
The outgoing email window is minimized, when the dialog pops-up which is not desirable and using .Show() is also not desirable.
During our research we've seen some issues where it was suggested to investigate parent properties of our dialog object, however we don't see any parent properties available which would allow us to maximize the parent:
Another suggestion was to pass the ShowDialog() a reference to the Add-In to specify an owner of the dialog box, IE:
objCheckDialog.ShowDialog(Me)
Since that property is also Nothing, but thought that this might populate Parent:
However, that throws the following exception:
{"Unable to cast object of type 'XYZ.ThisAddIn' to type 'System.Windows.Forms.IWin32Window'."}
Any idea of what we're doing wrong?
Thanks.
You would need to use the NativeWindow class.
objCheckDialog.ShowInTaskbar = false;
IntPtr wnd = ParentWindow();
if (wnd != IntPtr.Zero)
{
NativeWindow nativeWindow = new NativeWindow();
nativeWindow.AssignHandle(wnd);
return objCheckDialog.ShowDialog(nativeWindow);
}
else
{
return form.ShowDialog();
}
Parent windows handle can be retrieved from Explorer or Inspector object using IOleWindow interface:
[ComImport]
[Guid("00000114-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleWindow
{
void GetWindow(out IntPtr phwnd);
void ContextSensitiveHelp([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode);
}
public IntPtr ParentWindow()
{
IntPtr wnd = new IntPtr(0);
object window = _application.ActiveWindow();
if (window != null)
{
IOleWindow oleWindow = window as IOleWindow;
if (oleWindow != null)
{
oleWindow.GetWindow(out wnd);
}
}
return wnd;
}
I'm trying to register a handler for the WindowSelectionChanged event. It works, but when quitting Outlook, it will discard any changes to NormalEmail.dotm file.
For example, any changes to the Quick Part Gallery (Insert->Text->QuickParts) will only be visible during the current session; closing Outlook and starting it again will show the previous list of elements, even if they were deleted, or new ones were added).
Deleting the file :
C:\Users[USER]\AppData\Roaming\Microsoft\Templates\ NormalEmail.dotm
should prompt Outlook to create a new one, but this won't happen when the Addin is enabled.
This can be reproduced by registering even an empty method to the WindowSelectionChange event:
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.Inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(RegisterChangeHandler);
}
void RegisterChangeHandler(Outlook.Inspector inspector)
{
Microsoft.Office.Interop.Word.Application app = Application.ActiveExplorer().ActiveInlineResponseWordEditor?.Application;
--> app.WindowSelectionChange += WinSelectionChange; <-- this line causes the bug
}
private void WinSelectionChange(Selection Sel)
{
/* nothing */
}
...
}
This causes no exceptions; the result is the same when putting try/catch blocks in place, or when the callback is unregistered in the Application.Quit event.
Question: How can Outlook be made to commit the NormalEmail.dotm file, while also being able to register a callback for WindowSelectionChange event ?
(the project type is "2013 and 2016 VSTO Addin")
In my application, I am handling a QCloseEvent (when the close button X was pressed):
void MainWindow::closeEvent(QCloseEvent* event)
{
if ( !isAbortedFilestoSave() ) {
this->close();
}
// else abort
}
The if clause is triggereed when no abort was pressed. I would like to implement an else clause where a QCloseEvent is aborted? How?
You must use the ignore() on the event to "abort it" - to let Qt know you don't want the widget to actually close.
The isAccepted() function returns true if the event's receiver has agreed to close the widget; call accept() to agree to close the widget and call ignore() if the receiver of this event does not want the widget to be closed.
Also, no need to call close() yourself - the "X" button does that already, that's why you receive a close event!
So your code should be:
void MainWindow::closeEvent(QCloseEvent* event)
{
// accept close event if are not aborted
event->setAccepted(!isAbortedFilestoSave());
}
I'am very new to threading and quite unclear as to why this is happening in my code, when I click on a button that verifies hyperlinks in my document, I start a new thread that does the verification once it starts I want to disable the ribbon button and enable it again after thread finished but this is not happening and I dont know what is the mistake .Here is what I have tried so far:
public class Alpha :Ribbon1
{
// This method that will be called when the thread is started
public void Beta()
{
foreach() { //do something } after this loop ,enable the button again
button.enable=true //not applying
} }
private void button_Click(object sender, RibbonControlEventArgs e)
{
Alpha oAlpha = new Alpha();
// Create the thread object, passing in the Alpha.Beta method
Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
// MessageBox.Show("Please wait till the document is checked for invalid links");
// Start the thread
oThread.Start();
button7.Label = "Pls wait";
button7.Enabled = false;
}
Ribbon needs to be rendered again after enable/disable for change to take effect, you can do this by calling IRibbonUI.Invalidate()
Dows anyone know how I can build a timeout feature into a windows forms app.
The app is event driven, but I am thinking of somehow using a timer which counts down for say 10minutes, and one the timer ticks then we time out the user.
The problem I have is how can I reset the timer each time the mouse is moved or clicked.
Any help appreciated.
Cheers
you can use System.Windows.Forms.Timer.
you can drag it from your toolbox to the designer surface.
Use the properties window to set the Interval Property to the time span you want(miliseconds), the Enabled property should be set to false.
on the for load set the timer Enabled property to true.
(The event handler in the sample are written using c# - sorry about that)
private void Form1_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
}
Double click the timer tick event to register to the event, and close the form on the timer tick
private void timer1_Tick(object sender, EventArgs e)
{
Close();
}
In setting timer.Interval to 0 it does not work ?
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
Me.Timer1.Stop()
Me.Timer1.Start()
End Sub
As bad as it seems, I think the best way for that is to use a system.timer object with a set interval of a few milliseconds at most.
What I saw once is the use of a global variable that would get the time of the last action and that variable would be set to Now (using a global function for example) each time an action is performed. In your timer elapsed event, you check if now if bigger that the last action with your 10 minutes limit and act accordingly.
As for multi-form app, you could either use a different timer on each form , or only have the timer run on your main form.
Hope that helps.