I have an application written in C# using Microsoft.Office.Interop.PowerPoint. This application opens a PowerPoint presentation file to the user. The user interacts with the file. After applying some modifications, the user submits the file through the application submit button.
The Problem:
When user modifies the content of the presentation, for example changes font color of the text to red, by using a dialog and keeps the dialog open without clicking on "Apply" or "OK" button and thereby submits the file by clicking on application submit button, those dialog done changes aren't reflected in the submitted file and hence such changes can't be tracked of.
I somehow want to alert a user to close any open dialog before clicking on submit button.
I do this easily on Word and excel files by checking Exception on saving such files because Word and Excel throws exception on using save method if there is any dialog open, like the Following:
try{
document.Save();
}
catch (Exception e){
//Alert user here here
}
but this doesn't work for PowerPoint files. I tried the following:
PowerPointApplication application = new Microsoft.Office.Interop.PowerPoint.Application();
Microsoft.Office.Interop.PowerPoint.Presentations presentations = application.Presentations;
Microsoft.Office.Interop.PowerPoint.Presentation presentation =
presentations
.Open(file, WithWindow: Microsoft.Office.Core.MsoTriState.msoTrue,ReadOnly:Microsoft.Office.Core.MsoTriState.msoFalse,Untitled:Microsoft.Office.Core.MsoTriState.msoFalse);
The following is triggered on Submit button click event:
try
{
presentation.Save();
}
catch (Exception e)
{
//alert user here
}
Is there a way to track if there are any open dialog boxes?
Typically if any dialog window is displayed to a user the code is blocked because the dialog window uses the main thread for running. Do you use multiple threads in the code?
Anyway, you can use Windows API functions for detecting the active window, see GetActiveWindow which retrieves the window handle to the active window attached to the calling thread's message queue. To get the handle to the foreground window, you can use GetForegroundWindow. To get the window handle to the active window in the message queue for another thread, use GetGUIThreadInfo.
After retrieving the window handle you can use the GetWindowText function which copies the text of the specified window's title bar (if it has one) into a buffer. If the specified window is a control, the text of the control is copied.
Related
I'm developing a WPF application that's meant to live in the tool tray, so it doesn't involve any windows. Right-clicking the tool tray icon brings up a menu with a Configure Report Path... option, and I'd like to display a folder browser dialog to the user when this is clicked:
What I'm finding is that when the option is selected, a dialog opens and immediately closes unless I assign some window to Application.Current.MainWindow and show it before opening the dialog. This is the code I'm using:
public CounterIconViewModel(IMessenger messenger)
{
void ConfigureReportPath()
{
// Application window must be created and displayed.
Application.Current.MainWindow = new Window();
Application.Current.MainWindow.Show();
var browseDialog = new VistaFolderBrowserDialog { ShowNewFolderButton = false };
if (browseDialog.ShowDialog() != true)
{
return;
}
// (Separate issue) Command doesn't execute unless I comment out the line below.
//messenger.Send(browseDialog.SelectedPath, "ReportPath");
}
ConfigureReportPathCommand = new RelayCommand(ConfigureReportPath);
ExitApplicationCommand = new RelayCommand(Application.Current.Shutdown);
}
In this case I'm using VistaFolderBrowserDialog from Ookii.Dialogs.Wpf, but I've tried the same thing with another WPF browser dialog and notice identical behaviour.
Is there a reason why a browser dialog seems to require a window to be displayed to remain open, and any workarounds?
Update
I've found that if I initialize and pass an instance of Window to browseDialog.ShowDialog, the dialog remains open without me having to assign the main application window and display it:
if (browseDialog.ShowDialog(new Window()) != true)
I don't understand why this works. I'll post this as an answer if no others appear so that at least people in a similar situation are aware of this workaround.
Update 2
The other dialog I tested it with was CommonOpenFileDialog from Microsoft.WindowsApiCodePack-Shell:
var browseDialog = new CommonOpenFileDialog { IsFolderPicker = true };
browseDialog.ShowDialog();
My tool tray icon displays a rich tool-tip (a custom UserControl) if I hover over it, and with this browser dialog I found that:
If I hover over the icon to make the tool-tip display, then the browser dialog works fine when I try to open it on the first and every subsequent attempt.
If I try to open the browser dialog before displaying the tool-tip display, the browser dialog opens and closes immediately on the first try, but then remains open on every subsequent attempt.
This dialog also accepts a Window instance in ShowDialog but it makes no difference if I pass one or not.
My workaround (initializing and passing a blank window to the Ookli dialog browser) seems to work fine regardless of whether I first bring up the tool-tip, so I'm sticking with that for the time being.
I've been working with this WPF application that integrates a UrhoSharp Window. When I click somewhere in the Urho window, there's this dialog that pops up as rendered by the main WPF Application.
The issue is that on every application startup or first page load, the dialog pops as it should but doesn't respond to any of the user actions (the dialog has buttons in it) which is supposed to close the dialog eventually. However, if I resize the window or just click the application in the Start Bar, the dialog now responds(happily ever after). This issue doesn't return until I exit the current application page and switch back to the same page. The case is also the same for every application startup.
All the buttons in the dialog executes this command:
ICommand cmd = DialogHost.CloseDialogCommand;
Execute(null);
And the CloseDialogCommand is awaited like this:
var dialog = new SomeDialog();
dialog = (SomeDialog)await Controller.dialogHandler(dialog, true);
I couldn't figure out what the issue actually is. May be some help would do good.
I'm currently building a winforms application. The idea is to force the user to press Close or Cancel button and will not remove focus from the winform or be overlapped by the (whatsoever clicked item/apps/) if the user clicks outside of its winform border/size.
* Update *
I am not trying to create a ransomware. We are trying to copy the behavior of bootstrap modal that we created in our web app that the only way to close the modal is by pressing our "x" button. We are focusing on consistency.
I hope that you are talking about a modal dialog - one that blocks interaction with the rest of your application, rather than all applications running on the PC.
Assuming this is the case, do the following when opening your dialog:
using (var frm = new MyCustomForm())
{
//This is a blocking call - the execution stops here until that
//form is closed and you can then examine the result
var result = frm.ShowDialog();
}
See https://msdn.microsoft.com/en-us/library/c7ykbedk%28v=vs.110%29.aspx for more information on ShowDialog method.
I've run into an issue with the Microsoft.Win32.SaveFileDialog in our Wpf application.
If the user enters an enormous file path, above the allowed maximum (I think its 255 chars?), within the SaveFileDialog then it starts to become unusable (details of this are in the code example).
So as a work-around I want to close the dialogue and make them enter the file path again. However the problem is that the SaveFileDialog does not have a Close() routine or anything else that I can see to close it. How can I close the dialogue programmatically?
// error only seems to occur if a filter is specified.
var dialog = new Microsoft.Win32.SaveFileDialog
{
Filter = "My juicy file (*.mjf) | *.mjf"
};
try
{
dialog.ShowDialog();
}
catch (System.IO.PathTooLongException error) // handle
{
/*
* if I handle this exception (by displaying a message to the user)
* the dialog will remain open, but if the user attempts to use it
* and enter another filename a mixture of the following exceptions
* are raised:
*
* AccessViolationException
* FatalExecutionEngineError
* ExecutionEngineException
*/
MessageBox.Show(error.Message);
}
EDIT
Thanks for you answers/comments. I've just tested this on my Windows 7 box and it behaves as expected so this maybe an issue only on XP.
In WPF 4.0 on Windows 7 the SaveFileDialog is showing its own error dialog:
<long path?
The path is too long.
Try a shorter name.
with an OK button to dismiss the error dialog. That leads the user back to the original SaveFileDialog where they can change their value or Cancel.
For earlier versions where the behavior might be different, you can use the Windows UI Automation framework to programmatically click the 'Cancel' button on the SaveFileDialog.
if (dialog != null)
{
dialog.DialogResult = DialogResult.Cancel;
}
Try setting the dialog result to close the dialog.
Send the window a WM_SYSCOMMAND message with a wParam parameter of SC_CLOSE. This is the equivalent of clicking on the Close button in the upper-right corner of the dialog.
I'm writing a shared addin for Excel. It adds a CommandBarButton that when clicked opens a WPF window to collect some information from the user.
I wanted to keep the same WPF dialog in memory and reuse it so that if the user clicks the CommandBarButton again their previous values would still be there.
So I made a reference to my WPF dialog as a private member of my addin object that implements Extensibility.IDTExtensibility2.
I created the window during OnStartupComplete(), but for some reason when I run Excel the window immediately opens even though I never called ShowDialog() and when I do call ShowDialog() when the CommandBarButton is clicked to reopen the window it fails to load.
Does anyone know why this happens and what the correct way to handle this is?
Thanks very much for any help.
CODE UPDATE:
public void OnStartupComplete(ref System.Array custom)
{
MyDialog dlg = new MyDlg(); //This will open the dialog ?!?!
}
....
public MyDialog()
{
InitializeComponent();
Loaded += new RoutedEventHandler(OnLoaded);
}
OnLoaded just wires up some event handlers for buttons and sets some ItemSources. Even if I comment it out it still open the window.
I have picked up on the fact that once a WPF window is closed it can't be reoped and this is by design. But why it opens automatically when constructed inside an excel addin is a mystery.
I've been able to reproduce your problem. In the WPF designer, make sure that the form's Visbility property is set to Collapsed. If you have it as Visible, it will automatically show when the dialog is created.