when i move between forms buttons works as expected, but when im closing my custom pop up only seconds click on any button will trigger it
this is the code im using to load my custom popup
public void loadPopUp(Form from, Form to)
{
to.Tag = from;
to.Show(from);
}
and this is the code my using to close my custom popup
public void closePopUp(string formName)
{
for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
string name = Application.OpenForms[i].Name; //for debugging only
if (Application.OpenForms[i].Name == formName)
Application.OpenForms[i].Close();
}
}
note: this is not asp.net application
You should have something else in your code or you make something with the main window that changes the normal behavior of the forms engine. I have tried to build a sample app with LinqPAD using the code above and I have a normal behavior as expected. When I close the popup the focus is restored to the main form.
Nevertheless you could use the main form saved instance in the Tag property to call the Activate method and restore the focus to the main form.
public void closePopUp(string formName)
{
// No need to loop over all application OpenForms if you just want
// to close this popup
// for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
// {
// string name = Application.OpenForms[i].Name; //for debugging only
// if (Application.OpenForms[i].Name == formName)
// Application.OpenForms[i].Close();
//}
var mainForm = this.Tag as Form;
this.Close();
if(mainForm != null)
mainForm.Activate();
}
Note, I use a cast to the base Form class, so your code doesn't depend on the popup created by a particular class instance. This is possible because Activate is a base class method.
Related
I'm having trouble manipulating forms when from another thread.
I've overcome the issue by loading the form at runtime, showing it then hiding it. This means the form is created on the right thread and can be manipulated using invokes.
This is not the right way to do it. I have 3 problems that come from using this method
I can't spawn another popup box I have to use the one I created at runtime
The forms flash briefly on load - now that I have 3 forms its pretty obvious what I'm doing.
I have to use a variable bool to hold if the popup is open or not.
If anyone could point me in the right direction It would be much appreciated. Currently my code looks like:
On Main form Load:
CallerIDfrm = new frmCallerID();
CallerIDfrm.Show();
CallerIDfrm.Hide();
to manipulate the popup Im using
delegate void StringArgReturningVoidDelegate1(string CallerIDnum, string CallerIDname, string ContactID);
private void CallerID(string CallerIDnum, string CallerIDname, string ContactID)
{
if (CallerIDfrm.InvokeRequired)
{
StringArgReturningVoidDelegate1 d = new StringArgReturningVoidDelegate1(CallerID);
CallerIDfrm.Invoke(d, new object[] { CallerIDnum, CallerIDname, ContactID });
}
else
{
if (ContactID != null || ContactID != "0")
{
CallerIDfrm.ContactID = ContactID;
}
CallerIDfrm.Mainfrm = this;
CallerIDfrm.TopLevel = true;
CallerIDfrm.TopMost = true;
CallerIDfrm.lblCallerIDname.Text = CallerIDname;
CallerIDfrm.lblCallerIDnum.Text = CallerIDnum;
CallerIDfrm.Show();
CallerIDOpen = true;
}
}
To Hide the popup until required again im using:
delegate void StringArgReturningVoidDelegate2();
private void CallerIDClose()
{
if (CallerIDfrm.InvokeRequired)
{
StringArgReturningVoidDelegate2 d = new StringArgReturningVoidDelegate2(CallerIDClose);
CallerIDfrm.Invoke(d, new object[] { });
}
else
{
try
{
CallerIDfrm.Hide();
CallerIDOpen = false;
}
catch
{
}
}
}
I've tried otherways but the Popup loads as if it is not responding and I loose access to the popup.
Ultimately I'd like to be able to spawn multiple popups and have the ability to close them from the Main Form.
What I gather from your question: You have an caller api/lib/class and you like to show CallerId on a popup form when a call is received. Have a look at Events and Event Driven programming.
The following codes has not been tested, I wrote it from top of my head. Might not compile, they are here to show an example:
Create an CallReceived event in api/lib class as follows:
public event EventHandler<CallReceivedEventArgs> CallReceived;
protected void OnCallReceived(EventArgs e)
{
var handler = CallReceived;
if (handler != null)
handler(this, e);
// Note: For C# 6.0 and later, above statements can be simplified to
// CallReceived?.Invoke(this, e);
}
Note: If you don't have access to this api/lib code, create a Gateway class and put your event in there along with mechanism to trigger it.
Also create a CallReceivedEventArgs, this will be used to transfer event data:
public class CallReceivedEventArgs : EventArgs
{
public string CallerIDnum {get; set;}
public string CallerIDname {get; set;}
public string ContactID {get; set;}
}
Now, in your api/lib class raise this event whenever a call is received:
// a call received, replace dummy values with actual values
OnCallReceived(new CallReceivedEventArgs() { CallerIDnum="5554443322", CallerIDname="SOME_NAME", ContactID="SOME_CONTACT" });
Finally in your GUI form, register to said event and process accordingly.
// inside your main form class
private CallerAPI callerApi = new CallerAPI();
// somewhere inside you main form class, register to event
// from your use case, I would place it inside Main Form's constructor
callerApi.CallReceived += callerApi_Callreceived;
// receive event
void callerApi_Callreceived(object sender, CallReceivedEventArgs e)
{
var callerIDnum = e.CallerIDnum;
// etc.
// show callerId form with details
// you need to change frmCallerID's constructor accordingly
CallerIDfrm = new frmCallerID(e.CallerIDnum, CallerIDname, ContantID);
// to be able to track opened popups, you can store them inside a list
// private List<Form> openPopupList = new List<Form>();
//
// alternatively, you can assign CallerIDnum to form's name property
// and store these inside a List<string> instead of List<Form>
openPopupList.add(CallerIDfrm);
CallerIDfrm.Show();
}
Don't forget to unregister from event.
callerApi.CallReceived -= callerApi_Callreceived;
To wrap it up:
I can't spawn another popup box I have to use the one I created at runtime
You can create and show multiple frmCallerID, independent from each other.
The forms flash briefly on load - now that I have 3 forms its pretty obvious what I'm doing.
Since new approach creates CallerID forms based on events, you won't see these form flashing. It'll open whenever a CallReceived event is received.
I have to use a variable bool to hold if the popup is open or not.
A better approach would be: Register to forms FormClosed event, and remove from openPopupList accordingly.
frmCallerID.FormClosed += frmCallerID_FormClosed;
void frmCallerID_FormClosed(object sender, EventArgs e)
{
// remove form from openPopupList
frmCallerID closedPopup = (frmCallerID) sender;
openPopupList.remove(closedPopup);
}
I need to add hooks to wpf windows for creating keyboard shortcuts to my application.
I'm trying to get the window pointer from the Application class when it's activated, using the activated event. It works great when there's only one window.
We allow opening another window by pressing F11. This window opens in full screen mode and it can be closed only by pressing F11 or ESC. It seems like I can't get the correct pointer of this new window because all keyboard shortcuts don't work, except for F11 for some reason.
Code for getting pointer:
var windows = System.
Windows.Application. Current.Windows;
If (windows.Count < 1)
{
return false;
}
else if (windows. Count ==1)
{
winPointer = new WindowInteropHelper(windows[0]);
return true;
}
else
{
for (int I = 0; I < windows. Count; I++)
{
if (windows [I].IsActive)
winPointer =new WindowInteropHelper(windows[i]);
.
.
.
I'm not sure if I'm missing something, but if you're opening a new window, why can't you capture the key down for that window and handle it that way?
public partial class NewFullScreenWindow : Window
{
public NewFullScreenWindow()
{
InitializeComponent();
KeyDown += HandleKeyDown;
}
private void HandleKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape || e.Key == Key.F11)
{
Close();
}
}
}
I have C# WinForms code as follows to close all child forms when I open a new child form:
private void CloseAllActiveForms(Form[] MdiChildren)
{
Form[] childArray = MdiChildren;
foreach (Form childform in childArray)
{
childform.Close();
}
}
How can I use in WPF windows?
I tried the below code, but it will close all windows including the Parent and the Active window.
private void CloseAllWindows()
{
for (int intCounter = App.Current.Windows.Count - 1; intCounter >= 0; intCounter--)
{
Application.Current.Windows[intCounter].Close();
}
}
Thanks.
As far as I know, MDI support for WPF is limited, so try using the Tag attribute when you create your pseudo-child windows:
Window child = new Window();
child.Tag = "mdi_child";
Then, in your loop, modify it like this:
foreach (Window win in App.Current.Windows)
{
if (!win.IsFocused && win.Tag.ToString() == "mdi_child")
{
win.Close();
}
}
Note that for the above solution to work, ALL windows must have a Tag attribute, or else an Exception will be thrown at win.Tag.ToString().
Here is a method I use in WPF to close all child windows of my program, this code goes in the main window.cs file, but you could modify if(item!=this) to check for a particular window:
foreach(Window item in App.Current.Windows)
{
if(item!=this)
item.Close();
}
No faffing around with sub-classes or more lists (especially as the code already has a list of windows associated with it.)
If you wanted to selectively close windows then you could always modify the if statement to use a variable on the window class or check one of the pre-existing variables (such as a the class of the parent window) on the base window class.
I am trying to have it so once the file is opened, multiple forms of the same form opened. So in my code below, on program execution 10 forms of test would appear. I can see it working on the ram but it doesn't want to appear, or it will appear once and after I close one form another will open :P
Any ideas on what I am doing wrong?
Thanks :)
public partial class TestFrm : Form
{
public TestFrm()
{
InitializeComponent();
loopFrm();
}
public void loopFrm()
{
int loopNumber = 10;
Form[] TestFrm = new Form[loopNumber];
for (int i = 1; i < loopNumber; i++)
{
TestFrm[i] = new TestFrm();
TestFrm[i].ShowDialog();
}
}
}
ShowDialog() is a modal call. It will wait until the form is closed. If you want to have all forms open use Show(). But then these form are not modal to the main form.
You should use
TestFrm[i].Show();
Instead of
TestFrm[i].ShowDialog();
When ShowDialog() is called, the code following it is not executed until after the dialog box is closed.
I have a custom windows modal form with the following event code:
private void btnCancel_Click(object sender, EventArgs e)
{
Close();
_result = DialogResult.OK;
}
The problem is when I click OK, that triggers some process-intensive stuff (report generation) and the form becomes partially drawn on the screen. It's like the report generation is taking precedence over the window refresh. Is there something else I need to do in order to get it to disappear before the process-intensive code? This will most definitely annoy my users.
EDIT #1:
I'm trying to work Tergiver's method and pass in the dialog owner to ShowDialog. For my case, the calling method is not a form. So, I'm trying to create a IWin32Owner from the process's main window handle so that I can pass it into the ShowDialog method.
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
public WindowWrapper(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
private IntPtr _hwnd;
}
// In calling method
ShowDialog(new WindowWrapper(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle));
However, the dialog owner is still not set after the call to ShowDialog. I stepped into the WindowWrapper and the handle is non-zero. Any more ideas as to how to get the current process's active form?
EDIT #2
I'm now using the following code to retrieve the active form and then calling Owner.Refresh() in the OnFormClosed event.
public static Form GetActiveForm()
{
// Returns null for an MDI app
Form activeForm = Form.ActiveForm;
if (activeForm == null)
{
FormCollection openForms = Application.OpenForms;
for (int i= 0; i < openForms.Count && activeForm == null; ++i)
{
Form openForm = openForms[i];
if (openForm.IsMdiContainer)
{
activeForm = openForm.ActiveMdiChild;
}
}
}
return activeForm;
}
// In code opening dialog.
ShowDialog(GetActiveForm());
The obvious answer is not to do process-intensive code on the UI thread.
Use a BackgroundWorker or the ThreadPool to do the task.
Added
If you insist on doing it on the UI thread, you could use this.Owner.BeginInvoke to execute code after this closes.