I have a form that I want to show centred to its parent, using something like this.
Form f = new Form();
f.StartPosition = FormStartPosition.CenterParent;
f.ShowDialog(this);
The problem occurs if this code is triggered whilst the application is in a minimised state and when the application is restored my form is shown at the top right of the screen, rather than being centred to its parent.
Does anyone know how to fix this issue?
The Standard Windows MessageBox Dialog behaves correctly and when the application is restored from the minimised state, the dialog box is in the correct position.
My suggestion is to "cache" the parent form location when its being minimized (overriding WndProc() method will let the ability to cache the form location before its being minimized).
private Point CachedLocation;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0112) // WM_SYSCOMMAND
{
if (m.WParam == new IntPtr(0xF020)) // SC_MINIMIZE
{
// save the form location beofore it is minimized
CachedLocation= this.Location;
}
m.Result = new IntPtr(0);
}
base.WndProc(ref m);
}
Now, if the parent form is minimized when calling the child form use the Cached location point (by checking FormWindowState Enum):
private void button1_Click(object sender, EventArgs e)
{
Form f = new Form();
if (this.WindowState == FormWindowState.Minimized)
{
f.Top = (CachedLocation.Y + (this.Height / 2)) - f.Height / 2;
f.Left = (CachedLocation.X + (this.Width / 2)) - f.Width / 2;
f.StartPosition = FormStartPosition.Manual;
f.ShowDialog();
}
else
{
f.StartPosition = FormStartPosition.CenterParent;
f.ShowDialog();
}
}
Related
I'm writing an app that will play video on the main form or from another form when user clicks Go To Full Screen button. What I want to do is transfer the picture box and playback controls to the Full Screen form. If the user presses the Escape key, the picturebox and playback controls are returned to the main form. The controls show up on the Full Screen form, but the controls don't show up again on the main form after pressing the Escape key.
Here's the code for going to full screen...
private void btnGoToFullScreen_Click(object sender, EventArgs e)
{
frmFullScreen frm = new frmFullScreen();
frm.WindowState = FormWindowState.Maximized;
frm.Owner = this;
pbViewer.Parent = pnlVideoControls.Parent = frm;
pbViewer.Height = frm.Height;
pbViewer.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width / 2 - pbViewer.Width / 2,
Screen.PrimaryScreen.WorkingArea.Height / 2 - pbViewer.Height / 2);
pnlVideoControls.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width / 2 - pnlVideoControls.Width / 2,
Screen.PrimaryScreen.WorkingArea.Height - 200);
frm.Show();
}
And here's the code to return the controls to the main form...
private void frmMain_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
frmMain.Controls.Add(pbViewer);
frmMain.Controls.Add(pnlVideoControls);
pbViewer.Size = Properties.Settings.Default.Portrait;
pbViewer.Location = new Point(16, 24);
pnlVideoControls.Location = new Point(145, 418);
pbViewer.Show(); pbViewer.BringToFront();
pnlVideoControls.Show(); pnlVideoControls.BringToFront();
this.Refresh();
foreach (frmFullScreen frm in this.OwnedForms)
{
frm.Dispose();
}
}
}
NOTE: PictureBox is pbViewer and pnlVideoControls is the panel with playback buttons.
I am trying to send a window to a screen, and place that window in the center of the screen. When the button is clicked, it send / close the window and change button content.
My first issue is I can open and close the Window, but only 1 time. The second time I receive:
System.InvalidOperationException: 'Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.'
Also, if the button is closed manually, it does not change the button content.
Finally, it does not place the window in the center of the screen. I try to place the window in the center of the screen using:
window.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
window.VerticalAlignment = VerticalAlignment.Center;
but this does not work, it place the window upper left corner.
Can anyone out there guide me on how this should be handled?
Window1 w1 = new Window1();
private void ShowByCoordinates(Window window, string screenName, int LeftTransform, int TopTransform)
{
if (button4.Content.ToString() == "Send")
{
Screen s0 = Screen.AllScreens.FirstOrDefault(s => s.DeviceName == screenName) ?? Screen.PrimaryScreen;
Rectangle bounds = s0.WorkingArea;
window.Left = bounds.X + LeftTransform;
window.Top = bounds.Y + TopTransform;
window.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
window.VerticalAlignment = VerticalAlignment.Center;
window.Show();
button4.Content = "Stop";
}
else
{
window.Close();
button4.Content = "Send";
}
}
private void Button4_Click(object sender, RoutedEventArgs e)
{
ShowByCoordinates(w1, "DISPLAY2", 1920, 0);
}
First, once you close the window, it's disposed and you can't show it again. Use Show() and Hide() instead.
When you set WindowStartupLocation to CenterScreen ther is a problem: after the window is shown any programmatical changes to its position will be ignored. So you can only do it once this way.
To do it manually, you need to set WindowStartupLocation to Manual and then set your window's Top and Left properties.
The next problem you'll have to consider is the fact that there may be multiple monitors. If you only need to center the window on the monitor set as primary in the system, then:
w.Left = (SystemParameters.WorkArea.Width - w.ActualWidth) / 2 + SystemParameters.WorkArea.Left;
w.Top = (SystemParameters.WorkArea.Height - w.ActualHeight) / 2 + SystemParameters.WorkArea.Top
is enough. If you want to center the window on the current monitor, then you'll need to do something like this:
(method from here):
public static void PostitionWindowOnScreen(Window window, double horizontalShift = 0, double verticalShift = 0)
{
Screen screen = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(window).Handle);
window.Left = screen.Bounds.X + ((screen.Bounds.Width - window.ActualWidth) / 2) + horizontalShift;
window.Top = screen.Bounds.Y + ((screen.Bounds.Height - window.ActualHeight) / 2) + verticalShift;
}
To call it:
TestWindow w;
//....
w = new TestWindow();
w.WindowStartupLocation = WindowStartupLocation.Manual;
w.Closed += w_Closed;
//....
private void w_Closed(object sender, EventArgs e)
{
// to make sure there is no disposed window to access when user closes it manually
w = null;
// or:
// w = new TestWindow();
}
private void Button_ShowWindow_Click(object sender, RoutedEventArgs e)
{
if (w == null) return;
PostitionWindowOnScreen(w, 0, 0);
w.Show();
}
private void Button_HideWindow_Click(object sender, RoutedEventArgs e)
{
if (w == null) return;
w.Hide();
}
First, if you Close window, you cannot Show it again as already mentioned. You need to use Hide instead of Close.
To center your screen, just use this line:
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
I try to avoid the XY Problem by saying immediately what I want and then what I get. 😛
So, first of all, I minimize my MainWindow and thoroguh its NotifyIcon ContextMenu I want that my MainWindow reappears.
The problem: the MainWindow doesn't appear/show as Window, but it appears as Icon in the toolbar (see figure 2).
The code:
This is the TrayIcon initializer:
private void InitializeTrayIcon()
{
KyactusTrayIcon = new NotifyIcon();
KyactusTrayIcon.Icon = AppIcon;
KyactusTrayIcon.Visible = true;
KyactusTrayIcon.ContextMenu = new ContextMenu(new []
{
new MenuItem("Chiudi", ExitApplication),
new MenuItem("Mostra", ShowMainWindow),
});
ShowNotification(#"Ciao " + Globals.CurrentUser.Name + #"!", #"Benvenuto su Kyactus");
}
This is the delegate responsible to show the minimized MainWindow (not working at all):
private void ShowMainWindow(object sender, EventArgs e)
{
WindowState = WindowState.Normal;
Topmost = true;
Show();
Activate();
}
This is what happens when the MainWindow is minimized by clicking the [-] button (ie the Hide() method):
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
switch (this.WindowState)
{
case WindowState.Maximized:
ShowNotification("Bleah!", "Questo è proprio brutto! :(");
break;
case WindowState.Minimized:
Hide();
ShowNotification("Avviso", "L'applicazione è ora minimizzata qui");
break;
case WindowState.Normal:
break;
}
}
Step one. The method MainWindow_OnStateChanged will be invoked when click on [-]:
Step two. The window disappears (ok) and the Tray icon appears (ok). Then I click on 'Mostra' (translated as 'Show') and the ShowMainWindow delegate will be invoked
Step three. This is the final step, that is, what I do not expect. The MainWindos 'lives' as an Icon in the toolbar. But I can't see it as a Window.
Please note that I have not this problem when I close the window by clicking [X] instead of [-]. So, my suspect is the MainWindow's Window.State. I tried to restore it implementing the WindowState.Normal into the ShowMainWindow, but nothing.
Update: if is use WindowState.Maximized in the ShowMainWindow method,
I can see the window again, but it is maximized and this is bad and ugly.
Just change the order of operation when showing the window
private void ShowMainWindow(object sender, EventArgs e)
{
Show();
WindowState = WindowState.Normal;
Topmost = true;
Activate();
}
Simply,create some class-level integer variables and store the height,width and positioning values there.Then use them to get back the size of your window :
int height;
int width;
double left;
double top;
private void MainWindow_SizeChanged
{
height = this.Height;
width = this.Widthl
left = this.Left;
top = this.Top;
}
private void ShowMainWindow(object sender, EventArgs e)
{
this.Height = height;
this.Width = width;
this.Left = left;
this.Top = top;
}
suppose i have have two sdi form and when apps run then a sdi form show and from there i am showing another sdi form but the problem is i can drga any where the second sdi form which i do not want. in case of MDI form the mdi child form can not be drag out of mdi form boundary.so in my case i want to simulate the same thing. i want no other sdi form can not be drag out form my main sdi form's boundary. so just guide me how to do this.
i could guess that i have to work with form drag event and from there i have to check form top and left but need more suggestion.
private void Form1_Move(object sender, EventArgs e)
{
this.Location = defaultLocation;
}
i try to do it this way but it is not working.
public partial class Form2 : Form
{
Form1 _parent = null;
public Form2()
{
InitializeComponent();
}
public Form2(Form1 parent)
{
InitializeComponent();
_parent = parent;
}
private void Form2_Move(object sender, EventArgs e)
{
if((this.Location.X+this.Width) > _parent.Width)
{
this.Location = new System.Drawing.Point(_parent.ClientRectangle.Width-this.Width,this.Location.Y);
}
if ((this.Location.Y + this.Height) > _parent.Height)
{
this.Location = new System.Drawing.Point(_parent.ClientRectangle.Height - this.Height, this.Location.X);
}
if (this.Location.Y < 0)
{
this.Location = new System.Drawing.Point(this.Location.X);
}
if (this.Location.X < 0)
{
this.Location = new System.Drawing.Point(this.Location.Y);
}
}
}
please guide me where i made the mistake.
thanks
UPDATE
private void Form2_Move(object sender, EventArgs e)
{
int left = this.Left;
int top = this.Top;
if (this.Left < _parent.Left)
{
left = _parent.Left;
}
if (this.Right > _parent.Right)
{
left = _parent.Right - this.Width;
}
if (this.Top < _parent.Top)
{
top = _parent.Top;
}
if (this.Bottom > _parent.Bottom)
{
top = _parent.Bottom - this.Height;
}
this.Location = new Point(left, top);
}
I recomend to you follow the #ProgrammerV5 recomendation. But if you realy need to control the form movement, please see the use of Cursor.Clip property
here are some information: http://www.codeproject.com/Tips/375046/The-Cursor-Clip-Property
Also you may need to do a MouseCapture.
private void histogramGraphsToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Location = new Point(0, 0);
HistogramGraphs1 = new Lightnings_Extractor.Histogram_Graphs();
HistogramGraphs1.Show();
HistogramGraphs1.FormClosing += new FormClosingEventHandler(HistogramGraphs1_FormClosing);
histogramGraphsToolStripMenuItem.Enabled = false;
}
private void HistogramGraphs1_FormClosing(object sender , FormClosingEventArgs e)
{
this.StartPosition = FormStartPosition.CenterScreen;
histogramGraphsToolStripMenuItem.Enabled = true;
}
First time i put the Form in position 0,0
then on the Closing event i want it to back to the center screen but the Form is still in 0,0 position.
How can i fix it ?
First prevent to close this form by set e.Cancel = true. then move window to center of screen:
private void HistogramGraphs1_FormClosing(object sender , FormClosingEventArgs e)
{
histogramGraphsToolStripMenuItem.Enabled = true;
e.Cancel = true;
int x = Screen.PrimaryScreen.WorkingArea.Width / 2 - this.Width / 2;
int y = Screen.PrimaryScreen.WorkingArea.Height / 2 - this.Height / 2;
this.Location = new Point(x, y);
}
and this MSDN article may be useful:
Setting the Screen Location of Windows Forms
explain:
CancelEventArgs.Cancel: Gets or sets a value indicating whether the event should be canceled.
Form.Location Property: Gets or sets the Point that represents the upper-left corner of the Form in screen coordinates.
if your setting the this.StartPosition = FormStartPosition.CenterScreen; then you need to re-open the form. Other wise it will not effect.