Why does hiding and showing a mdi child move the child? - c#

I have a very basic out the box mdiparent which has a number of mdichildren and a menu item. Each button on the menu item hides all the forms and then shows the one respective to that button.
When I do it this way:
//dontHide is the Form we want to show.
for(int i = 0; i < this.MdiChildren.Length; i++)
{
if (this.MdiChildren[i] != dontHide)
{
this.MdiChildren[i].Visible = false;
}
}
dontHide.Visible = true;
Switching forms causes the new form opened to be positioned bit lower and to the right of the old form, but clicking the menu item for the currently displayed form does nothing (as expected).
But, when I do this:
//dontHide is the Form we want to show.
for(int i = 0; i < this.MdiChildren.Length; i++)
{
this.MdiChildren[i].Visible = false;
}
dontHide.Visible = true;
Even clicking the menu item for the currently visible form causes it to shift to the lower right, same as opening a new form. Why is that?
Edit:
I've also noticed when centering the form and then displaying it (so you don't risk having someone glimpse it right before it is moved), setting visible to true completely resets any centering I've done.

This is caused by an obscure implementation detail in Winforms. The native MDI support built into Windows does not support hiding child windows. Winforms works around this restriction by destroying the child window when you set its Visible property to false. And re-creating it when you set it back to true.
This can have various side-effects, the state of the native window is lost when this happens of course. Winforms has fairly decent support for restoring the window again from its properties. But one thing it doesn't do is recreating the window in the same location. So you'll see it getting recreated in the location that new MDI child windows get, staggered from the previous window. Whether that was an oversight or intentional isn't that clear to me, 95% odds for the latter.
Otherwise simple to work around, you can assign the Location property yourself to get it back where it was:
var loc = dontHide.Location;
dontHide.Visible = true;
dontHide.Location = loc;
Or just set the MDI child form's StartPosition to Manual.

Related

Infragistics UltraTabbedMdiManager overlapping tab forms and panel shifts down

I am using a UltraTabbedMdiManager for a C# winform application. Each tab is added one at a time and displays a unique form. The tab panel is nested within its parent form. I am experiencing two issues related to new tab instantiation.
Issue #1: On adding a new tab the entire tab plane shifts down exposing a strip at the top of the parent form (Mdi container), just below its title bar. When clicking on another tab or elsewhere on the parent form, the tab plane reverts to its original position. This strip only appears on creating a new tab and disappears as soon as the focus is lost (by clicking elsewhere). It also occurs only every second tab that is generated which suggests an activation focus issue on new tabs. The problem does not occur when clicking between already generated tabs or when removing tabs.
I have found a work around for this issue: After the creation of the tab and its form, iterate through all the tabs in the mdi manager and disable them. This iteration is then immediately repeated with enabling all the tabs. The new tab is then reactived. These steps force a loss and then regain of focus and then activation of the tab (N.B. without activation the previous tab will be active). The following is a (verbose) piece of my code which does this operation:
var activeTab = MdiTabManager.ActiveTab;
foreach (var tabgroup in MdiTabManager.TabGroups)
{
foreach (var tab in tabgroup.Tabs)
{
tab.Form.Enabled = false;
}
}
foreach (var tabgroup in MdiTabManager.TabGroups)
{
foreach (var tab in tabgroup.Tabs)
{
tab.Form.Enabled = true;
}
}
activeTab.Activate();
Issue #2: On the generation of some new tabs. The form shifts down and the controls at the top of the previous tab are displayed (but are inactive) on the new tab. It is as if they were superimposed onto the new tab. A similar work around like before resolves this issue; I had read this on another infragistics forum post. However this time the tab's form ShowInTaskbar property is set to false and then true (after iterating through all the mdi managers tabs).
However, the workaround(s) have side-effects if relying on the Application.OpenForms collection. Calling ShowInTaskbar will effectively remove the open forms from this collection (a known Windows form bug as described here Application.OpenForms.Count = 0 always). Unfortunately my application relies on this collection. So my workaround is not applicable to my application. Though, it could be useful to other designs not relying on the OpernForms collection.
It is possible that the two issues are related. Perhaps solved in later version of infragistics. Infragistics does suggest upgrading. Before doing this has anyone experience such problems before?
Just for further information about our application. The form, that contains the mdi manager, is launched from our application's main form. This main form also uses a UltraTabbedMdiManager but does have these issues. Therefore are there known problems with having more than one mdi manager in the same project or solution ?
Here are my environment details:
Infragistics v14.1, .Net v4.7, Visual Studio 2017 Enterprise, C# 7.0, WinForms

C# & XAML Popup doesn't show in screenshot

I have many popups in a custom GUI application. These popups are window objects, not popup objects. The popups do not show up in a screenshot when using the Print Screen button on the keyboard. Instead, the disabled mainwindow below is all that shows in the screenshot. The popup never flickers or disappears, it just doesn't show in the screenshot.
WindowInstance.IsEnabled = true;
WindowInstance.Refresh();
DisplayPopUpWindow(WindowInstance);
The code in DisplayPopupWindow:
private void DisplayPopUpWindow(Window theWindow)
{
if (theWindow != null)
{
if (theWindow is MessagePopup)
{
// Only show one popup at a time (queue is handled elsewhere)
RemovePopUpsCommand.Execute(true, null);
}
ActiveWindow.IsEnabled = false; // main screen disabled
foreach (KeyValuePair<Window, int> aPopup in popUpWindows)
{
if ((aPopup.Key.IsVisible) && (aPopup.Key.Opacity == 1) && (aPopup.Key != theWindow))
{
// if window is a lower priority then disable it
if (aPopup.Value > displayPriority)
aPopup.Key.IsEnabled = false;
}
}
theWindow.Show();
theWindow.Opacity = 1;
}
}
Is there some property in the XAML that affects whether the window is visible for screenshots? This is a large issue as this also affects some remoting software we use in that popups do not display on the shared screen. Also affects our combobox implementation.
The "popups" are actually their own standalone windows. Some have instances created once during application startup and simply shown/hidden when needed, however, most are created on demand to be displayed. This problem affects both types.
The remoting software used is axeda access remote.
If I remember correctly I had the same problem and I think it was related to setting the popup windows parent to the main window that fixed it, I'd have to look at my code at home to confirm.
So make sure this is correctly set.
EDIT:
Try using this code when you create the Window object:
MainWindowVariable.Owner = Window.GetWindow(this)
You can read more here:
http://msdn.microsoft.com/en-us/library/system.windows.window.owner(v=vs.110).aspx

control box showing twice [duplicate]

All, I have a WinForms MDI control and in it I dock several child windows. When I first did this I managed (somehow) to get rid of the window list (shown above the tabbed forms below)
I am not talking about the double window menu (on the right) I know that this is due to a bug in the WinForms control and that if you add MdiChild elements in the Load event instead of the Constructor, this behaviour resolves itsef (see this post for details).
Here I am talking about the menu strip itself, I don't want it! How do I get rid of it? Any advice is much appreciated...
Note: I am adding MdiChild forms in the following way:
foreach (Form mdiChild in MdiChildForms)
{
mdiChild.MdiParent = this;
mdiChild.Show();
}
where MdiChildForms is a List<Form>.
Here is the possible solution:
public MainForm() {
IsMdiContainer = true;
InitializeComponent();
this.MainMenuStrip = new MenuStrip(); // create our own menu strip
this.MainMenuStrip.Visible = false;
}

Reset the panel scroll position in winform application c#

I'm working on winfom application c#.
I have two forms called Welome and Details.
Details contains 7 grids in the Panel.
Scenario:
If I click on any of the item on welcome page it will take to the Details page with seven grids. If I drag the scroll bar down, and come back after moving back to welcome form, still the scroll bar stays at the same position.
Question:
I want to reset the scroll position to top each time the user visits the details form, so that I can always see first grid.
Set AutoScroll to true
panel1.AutoScroll = true;
And, then in Details form's load event, set the VerticalScroll
panel1.VerticalScroll.Value = 0;
If Angshuman Agarwal's answer doesn't work for you, the culprit is likely that after load some control in the form is receiving focus, which will scroll into view and override any changes to the scroll position.
You could set TabStop to false, but then your form wouldn't be tabbable :(
A clunky work-around, but still relatively simple fix, is manually fire focus on the first control in your form:
yourFirstControl1.Select();
See also: How to make the panel scroll bar to be at the TOP position on loading the form
Old post, but still relevant. The above only worked when I added a line:
displayPanel.AutoScroll = true;
displayPanel.AutoScrollPosition = new Point(displayPanel.AutoScrollPosition.X, 0);
displayPanel.VerticalScroll.Value = 0;
Then it worked great, without having to set any tab indexes.
What is mentioned above is fine but, you should add VerticalScroll.Value in Panel1_Paint
Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
Panel1.VerticalScroll.Value = 0
End Sub

Form.Location doesn't work

I asked this question previously and thought I had it figured out but it still doesn't work.
Form.Show() moves form position slightly
So I have a parent form that opens a bunch of children with show() and then when one is needed I use bringToFront() to display it. The problem is when show() is called the child form is aligned perfectly but when I use bringToFront it moves left and down 1 px which screws with my borders. I have set all the child forms startPosition properties to Manual before show()-ing them. I have set frm.location = new Point(x,y) when bringing to front. I've also tried explicity setting frm.location when show()-ing also. It still moves it left and down 1 px when I bringToFront(). Is there something with bringToFront() that doesn't let me change the location property of the form? Here is my code:
if (myNewForm != null)
{
myNewForm.MdiParent = this;
bool isFormOpen = false;
foreach (Form frm in Application.OpenForms)
{
if (frm.GetType() == myNewForm.GetType())
{
frm.WindowState = FormWindowState.Maximized;
frm.BringToFront();
frm.Location = new Point(-4, -30);
isFormOpen = true;
break;
}
}
if (!isFormOpen)
{
myNewForm.StartPosition = FormStartPosition.Manual;
myNewForm.Show();
}
}
EDIT: Ok so apparently Microsoft has a bug that lets StartPosition only work for ShowDialog() and not Show() but refuses to fix it: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=107589
But my application needs to keep all the different forms open and just bring them to the front when needed...so ShowDialog() could not be appropriately used in this instance correct? So what options do I have? Any?
If you wish to set the form location, you have to set the form's WindowState to Normal (on any other setting, the location is set for you according to the rules of that setting, so your value is ignored), and its StartPosition to Manual.
frm.WindowState = FormWindowState.Normal;
frm.StartPosition = FormStartPosition.Manual;
frm.BringToFront();
frm.Location = new Point(-4, -30);
I suppose the forms are moved by the code that handles the Show() (and BringToFront) requests, so you really cannot set the form's location - neither before nor after calling the method - because the form location will be updated after the code in your main window has executed (and left control back to the window message pump, in Win32 terms, basically).
I would use a subclass of Form for each of your forms and then add an explicit Point property that indicates the fixed position where that particular form is expected to be. Inside this class, override the OnShown virtual method (or perhaps the OnActivated method too) and simply update this.Location with the correct location.
That should force the forms to the correct position, even if some code inside windows forms changes it at some time.
Have you tried:
this.Location
or
Form.ActiveForm.Location ?
What about using a p/Invoke to MoveWindow? The link provided includes a C# example.
Have you tried showing the form, and then adjusting the Location?
Edit: Or, have you tried adjusting the Left and Top properties?

Categories