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?
Related
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 know there are many discussion this topic already but still i could not find an answer. Hope someone have a idea.
I load a bitmap in a PictureBox (SizeMode Normal, DockStyle Fill) and use the Paint event to draw the image.
To zoom I use MouseWheel event and increase / decrease zoom factor (Like _zoomFac += 1). The goal is to zoom at the mouse position. So in the MouseWheel event I also save the mouse position (_imageZoomLocation). This is my code (only little test implementation):
public partial class Form1 : Form
{
private Image _image;
private float _zoomFac;
private PointF _imageZoomLocation;
public Form1()
{
InitializeComponent();
_image = null;
_zoomFac = 1F;
_imageZoomLocation = PointF.Empty;
pictureBox.MouseWheel += new MouseEventHandler(OnMouseWheel);
}
private void pb_Paint(object sender, PaintEventArgs e)
{
if (_image == null)
return;
e.Graphics.TranslateTransform(-_imageZoomLocation.X + _imageZoomLocation.X / _zoomFac, -_imageZoomLocation.Y + _imageZoomLocation.Y / _zoomFac);
e.Graphics.ScaleTransform(_zoomFac, _zoomFac, MatrixOrder.Append);
e.Graphics.DrawImage(_image, new Point(0,0));
}
private void fileToolStripMenuItem_Click(object sender, EventArgs e)
{
... Code for loading image
}
private void OnMouseWheel(object sender, MouseEventArgs e)
{
if (_image == null)
return;
_imageZoomLocation = e.Location;
if (e.Delta > 0)
_zoomFac += 1F;
else
if (_zoomFac - 1F < 1F)
_zoomFac = 1F;
else
_zoomFac -= 1F;
Refresh();
}
private void pb_MouseEnter(object sender, EventArgs e)
{
pictureBox.Focus();
}
}
This works well as long as _imageZoomLocation is not changed, means the mouse is not moved i can zoom in and out perfectly (I can change mouse position when zoom factor is 1 and everything still works). However when I move the mouse to different position in a zoomed state (e.g. zoom factor is 2) and scroll, the image jumpes once to a different position than the mouse is and after this "jump" everything works well again.
Can anyone explain this behaviour?
In the following line, you are dividing imageZoomLocation.X and .Y by the zoom factor only half the time. Instead, maybe you need a separate variable to keep the previous mouse location.
e.Graphics.TranslateTransform(-_imageZoomLocation.X + _imageZoomLocation.X / _zoomFac, _
-_imageZoomLocation.Y + _imageZoomLocation.Y / _zoomFac);
I'm creating a simple application that draws a horizontal and a vertical line following the mouse.
The form is transparent using TransparencyKey, and the lines are drawn using the Paint event:
private void Form1_Paint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.Lime);
e.Graphics.DrawLine(pen, 0, py, this.Size.Width, py);
e.Graphics.DrawLine(pen, px, 0, px, this.Size.Height);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
px = e.X; // get cursor X pos
py = e.Y; // get cursor Y pos
Invalidate(); // fire Paint event
}
But the MouseMove event only is fired when the mouse is over the lines drawn. How to make the form catch mouse events when transparent? (Only the mouse move, I want the form still click-through)
As you can read here: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.transparencykey%28v=vs.110%29.aspx - "Any mouse actions, such as the click of the mouse, that are performed on the transparent areas of the form will be transferred to the windows below the transparent area". One way to accomplish your goal is to write your own method, that will check the cursor relative position to the form in a loop, here's what I mean (it worked for me with TransparencyKey, resizing and moving the form):
private void MouseMovedWithTransparency()
{
Point lastCursorPos = new Point(-1, -1); // Starting point.
while (this.Visible)
{
Point currentCursorPos = Cursor.Position;
if (this.ContainsFocus && currentCursorPos.X > this.Left && currentCursorPos.X < this.Left + this.Width &&
currentCursorPos.Y > this.Top && currentCursorPos.Y < this.Top + this.Height)
{
if ((currentCursorPos.X != lastCursorPos.X) || (currentCursorPos.Y != lastCursorPos.Y))
{
// Do actions as in MouseMoved event.
// Save the new position, so it won't be triggered, when user doesn't move the cursor.
lastCursorPos = currentCursorPos;
}
}
Application.DoEvents(); // UI must be kept responsive.
Thread.Sleep(1);
}
}
All you have to do now is to invoke this method from the Shown event - this.Visible has to be true, so it's the easiest way to make it work.
I Want Use a Panel in a Windows Form in C#.net. I Set Visible Property of this Control to false And When I Click on a Button, Panel is showed. I Want Show a Panel by some Effect.
Please Help me for this
You are leaving us guessing about what kind of effect you are looking for. I'll just arbitrarily pick a collapse and expand effect. It takes a Timer, you implement the effect in a Tick event handler. Here's an example, it requires a Panel, Timer and Button:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
timer1.Interval = 16;
timer1.Tick += new EventHandler(timer1_Tick);
panel1.BackColor = Color.Aqua;
mWidth = panel1.Width;
}
int mDir = 0;
int mWidth;
void timer1_Tick(object sender, EventArgs e) {
int width = panel1.Width + mDir;
if (width >= mWidth) {
width = mWidth;
timer1.Enabled = false;
}
else if (width < Math.Abs(mDir)) {
width = 0;
timer1.Enabled = false;
panel1.Visible = false;
}
panel1.Width = width;
}
private void button1_Click(object sender, EventArgs e) {
mDir = panel1.Visible ? -5 : 5;
panel1.Visible = true;
timer1.Enabled = true;
}
}
The only effect I can think of is to expand the panel by using a timer and change the size of the panel step-by-step.
I would recommend you to use WPF instead of Winforms that is very good at doing this kind of stuff. You can animate all properties of the control like location, size, alpha. Please, check these articles on WPF animation
WPF Animation overview
Walkthroughs: Create a Custom Animated Button
I have a window with WindowStyle="none" and WindowState=Maximized" and now I'd like in my contextmenu set the MenuItem to switch the application to the other desktop.
whats the simplest way to do that?
using System.Windows.Forms;
using System.Drawing;
using System.Windows.Interop;
Screen screen = Screen.FromHandle(new WindowInteropHelper(this).Handle);
int i;
for (i = 0; i < Screen.AllScreens.Length; i++)
{
if (Screen.AllScreens[i] == screen) break;
}
i++; i = i % Screen.AllScreens.Length;
this.WindowState = WindowState.Normal;
int x = 0;
for (int j = 0; j < i; j++)
{
x += Screen.AllScreens[j].Bounds.Width;
}
this.Left = x + 1;
this.WindowState = WindowState.Maximized;
This will move a maximised window to the next monitor. I didn't test it though as I have only one monitor. Moving a window that is not maximised is harder because the size of the new monitor is not necessarily the same as the size of the old monitor. You could leave out setting the WindowState and center the window on the screen, or get the x position of the window on the current monitor and add it to the new x position. When using the latter you need to check if the new position is still inside the monitor.
Also note that this only works if your monitors are set up next to each other. This will not work when monitors are stacked.
I've solve the problem
when click the maximized window with the MouseLeftButtonDown then minimized this and now can i drag this to the other screen. The MouseLeftButtonUp Methode maximized the window
private void win_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
click = new Point(e.GetPosition(this).X, e.GetPosition(this).Y);
win.WindowState = WindowState.Normal;
}
private void Window_MouseMove(object sender, MouseEventArgs e)
{
this.Left += e.GetPosition(this).X - click.X;
this.Top += e.GetPosition(this).Y - click.Y;
}
private void win_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
win.WindowState = WindowState.Maximized;
}
thx # all : )