WPF C# Send Window to Screen and align - c#

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;

Related

Cannot show MainWindow after minimization

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;
}

WPF connect two windows to drag and resize

I want to create a sort of side-window next to another window.
It should resize with the mainwindow and also move with it when I drag the mainwindow. How do I do this?
the first thing you do is to create your second window.
SecondWindow secondwindow;
Then you call the window directly next to your MainWindow.
secondwindow = new Secondwindow();
secondwindow.WindowStartupLocation = WindowStartupLocation.Manual;
secondwindow.Left = this.Left + this.Width;
secondwindow.Top = this.Top;
secondwindow.Height = this.Height;
secondwindow.Show();
If you want the second window to resize with your MainWindow (I guess just the height) type this in your
MainWindow - SizeChanged - event.
private void mainwindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (secondwindow != null)
{
secondwindow.Left = this.Left + this.Width;
secondwindow.Top = this.Top;
secondwindow.Height = this.Height;
}
}
Same without the height-change for the LocationChanged.
private void mainwindow_LocationChanged(object sender, EventArgs e)
{
if (secondwindow != null)
{
secondwindow.Left = this.Left + this.Width;
secondwindow.Top = this.Top;
}
}

Resize form to both directions simultaneously

I have launcher application which contains borderless full form sized FlowLayoutPanel, and loads shortcuts to it's child FlowLayoutPanels. Form should be always centered to the screen, so ResizeEnd event centers it.
I want that when user resizes form bigger from bottom (this.Bottom increases), form automatically resizes bigger from top also (this.Top increases).
I tried following approach (works only when resizing bigger to save code here). Yes it works, but it flickers way too much and content is jumping up and down.
private void Form1_ResizeBegin(object sender, EventArgs e)
{
resizeStarted = true;
top = this.Top;
bottom = this.Bottom;
height = this.Height;
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
if (resizeStarted)
{
// if resizing up, automatically resize form bigger so that bottom goes down
if (this.Top < top)
{
int change = top - this.Top;
this.Height = height + (2 * change);
}
// if resizing down, automatically resize form bigger and move up
else if (this.Bottom > bottom)
{
int change = this.Bottom - bottom;
this.Top = top - change;
this.Height = height + (2 * change);
}
}
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
resizeStarted = false;
centerForm();
}
Is there any smarter way to accomplish this behaviour?

Why when i close the control the Form1 is not back to the CenterScreen position?

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.

How to get popup to animate?

Here is my code (Say we have a single button on the page that initiates the popup):
private void button1_Click(object sender, RoutedEventArgs e)
{
Rectangle rect = new Rectangle();
rect.Width = 50;
rect.Height = 50;
Popup mypop = new Popup();
mypop.Child = rect; // just to put something inside the popup for now
mypop.PopupAnimation = PopupAnimation.Slide;
mypop.StaysOpen = false;
mypop.PlacementTarget = button1; // open next to the button
mypop.IsOpen = true;
}
The popup just appears without animating, even though I set the PopupAnimation property.. anyone know why?
See this: Popup class:
A Popup control supports animation when the AllowsTransparency property is set to true and the application is running with full trust

Categories

Resources