Is there any way to make the form semi-transparent while it is being moved and then become opaque when it's not being moved anymore? I have tried the Form_Move event with no luck.
I'm stuck, any help?
The reason the form loads as semi-transparent is because the form has to be moved into the starting position, which triggers the Move event. You can overcome that by basing whether the opacity is set, on whether the form has fully loaded.
The ResizeEnd event fires after a form has finished moving, so something like this should work:
bool canMove = false;
private void Form1_Load(object sender, EventArgs e)
{
canMove = true;
}
private void Form1_Move(object sender, EventArgs e)
{
if (canMove)
{
this.Opacity = 0.5;
}
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.Opacity = 1;
}
To do it properly I expect you'd need to override the message processing to respond to the title bar being held, etc. But you could cheat, and just use a timer so that you make it opaque for a little while when moved, so continuous movement works:
[STAThread]
static void Main()
{
using (Form form = new Form())
using (Timer tmr = new Timer())
{
tmr.Interval = 500;
bool first = true;
tmr.Tick += delegate
{
tmr.Stop();
form.Opacity = 1;
};
form.Move += delegate
{
if (first) { first = false; return; }
tmr.Stop();
tmr.Start();
form.Opacity = 0.3;
};
Application.Run(form);
}
}
Obviously you could tweak this to fade in/out, etc - this is just to show the overall concept.
Related
I am trying to do some animations with panels and a timer in a C# Windows Forms project. Currently, there is a panel (in my code called 'pnSideBlock') which is located at the left edge of the window. Right next to it is a button.
The idea is that if the mouse enters the button, then the panel should relocate outside of the window (in my project the panel has a width of 20px, therefor I make its new location 20px outside of the window) and will move into it again with the help of a timer. As soon as the panel has reached a specific location, in my case 0px, then the timer should stop and the panel should stop moving.
But at the moment, the timer just keeps on going, which causes the panel to keep moving to the right.
private void btnMainMenu_MouseEnter(object sender, EventArgs e)
{
pnSideBlock.Left = -20;
timerForAnim.Enabled = true;
if(pnSideBlock.Left == 0)
{
timerForAnim.Enabled = false;
}
}
private void btnMainMenu_MouseLeave(object sender, EventArgs e)
{
timerForAnim.Enabled = false;
}
private void timerForAnim_Tick(object sender, EventArgs e)
{
pnSideBlock.Left += 1;
}
according to your code you need to change it to be like this:
private void btnMainMenu_MouseEnter(object sender, EventArgs e)
{
pnSideBlock.Left = -20;
timerForAnim.Enabled = true;
}
private void btnMainMenu_MouseLeave(object sender, EventArgs e)
{
timerForAnim.Enabled = false;
}
private void timerForAnim_Tick(object sender, EventArgs e)
{
pnSideBlock.Left += 1;
if(pnSideBlock.Left == 0)
{
timerForAnim.Enabled = false;
}
}
this change is required becouse btnMainMenu_MouseEnter happen only once when you enter to the button with the mouse.
and you need to check if the panel in place after every move.
Something similar, using a async Method.
Make your Button's MouseEnter handler async and call the async Task SlidePanel() method, specifying the initial and final position of the Control to slide and the speed of the animation (expressed in milliseconds).
When the Control is first entered, it's MouseEnter handler is detached (so it won't be raised again if the mouse pointer enters it while the animation is playing) and is be wired again when the animation finishes.
You can interact with the Button as usual.
The animation will be performed to its end even if the Button shows a modal Window when clicked (a MessageBox, for example).
Visual behaviour:
private async Task SlidePanel(Control control, int start, int end, int speed)
{
while (start < end)
{
await Task.Delay(speed);
start += 1;
control?.BeginInvoke(new Action(() => control.Left += 1));
}
}
private async void btnSlider_MouseEnter(object sender, EventArgs e)
{
btnMainMenu.MouseEnter -= btnMainMenu_MouseEnter;
pnSideBlock.Left -= pnSideBlock.Width;
await SlidePanel(pnSideBlock, pnSideBlock.Left, pnSideBlock.Width, 100);
btnMainMenu.MouseEnter += btnMainMenu_MouseEnter;
}
I've created my own dragable control. The dragging is very simple:
bool moving = false; Point click = new Point(0, 0);
private void _MouseDown(object sender, MouseButtonEventArgs e)
{
moving = true;
click = Mouse.GetPosition(this);
}
private void _MouseUp(object sender, MouseButtonEventArgs e) { moving = false; }
private void _MouseMove(object sender, MouseEventArgs e)
{
if (moving == true)
{
Point po = Mouse.GetPosition(this);
this.Margin = new Thickness(this.Margin.Left + (po.X - click.X), this.Margin.Top + (po.Y - click.Y), 0, 0);
}
}
My problem is that if I drag too fast the cursor "escapes" my control. It's obvious why, however it's not too obvious how to fix this since I can't easily subscribe to every other control's mousemove in the window, and my control is small (about 35,15 px) so this happends a lot. I think that if I can easily force the mouse cursor to stay in the controll that would be a solution(not ideal, though).
So what is the bast way to fix this? How professinoal controls handle this?
P.S. I'm learning WPF, so I'm probably doing some things wrong
Your cursor leaves the usercontrol on fast moves and the MouseMove event will not be triggered anymore.
As said in the comments from the author in Drag Drop UserControls using the MouseMove event of a surrounding Canvas should help.
I've figured it out, it's very simple, using a timer.
bool moving = false; Point click = new Point(0, 0);
System.Timers.Timer _MOVER = new System.Timers.Timer();
public PersonControl()
{
InitializeComponent();
_MOVER.Elapsed += new System.Timers.ElapsedEventHandler((o, v) => { Dispatcher.Invoke(Move); });
_MOVER.Enabled = true;
_MOVER.Interval = 10;
}
private void _MouseDown(object sender, MouseButtonEventArgs e)
{
moving = true;
click = Mouse.GetPosition(this);
Canvas.SetZIndex(this, 100);
_MOVER.Start();
}
private void _MouseUp(object sender, MouseButtonEventArgs e)
{
moving = false;
Canvas.SetZIndex(this, 0);
_MOVER.Stop();
}
private void Move()
{
if (moving == true)
{
Point po = Mouse.GetPosition(this);
this.Margin = new Thickness(this.Margin.Left + (po.X - click.X), this.Margin.Top + (po.Y - click.Y), 0, 0);
}
}
I'm trying to do transparent and clickable form. This form will work full screen. So this form must be clickable. For example if desktop exists behind this form, I must be able to click to folders and open.
If a document exists I must be able to change this document. I couldn't solve how to enable this.
I think it can be done with API codes, but I don't know which API. If you can give me some information/link I will be pleased.
This is simple and works without calling any API function.
But it will prohibit any interaction of your program with the user..
For a Screensaver this makes no sense, however, at least not as you described it.
The rule is this:
Anything that is not 100% transparent is not click-through.
So you could easily create a darker screen using Opacity and a Black BackColor but it won't be click-through.
The simplest solution would be to switch between the both modes upon MouseMove using a Timer to turn the saving mode back on, maybe like this:
public Form1()
{
InitializeComponent();
this.Text = "";
this.MinimizeBox = false;
this.MaximizeBox = false;
this.ControlBox = false;
this.WindowState = FormWindowState.Maximized;
switchSaverState(false);
}
Point lastMosePosition = Point.Empty;
int savingWaitMinutes = 10;
int minute = 60000;
Timer timer1 = new Timer;
void switchSaverState(bool saving)
{
if (saving)
{
this.BackColor = Color.Black;
this.Opacity = 0.8;
}
else
{
this.TransparencyKey = Color.Fuchsia;
this.BackColor = Color.Fuchsia;
this.Opacity = 1;
timer1.Interval = minute * savingWaitMinutes;
timer1.Start();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (timer1.Interval == minute * savingWaitMinutes)
{
timer1.Interval = 100;
switchSaverState(true);
lastMosePosition = Cursor.Position;
}
else
{
if (Cursor.Position != lastMosePosition) { switchSaverState(false); }
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
lastMosePosition = Cursor.Position;
switchSaverState(false);
}
But again: This is like a Screensver, meaning that you can't work while it 'saves'! To do that use the controls on your monitor!!
My Form has a problem with that GroupBbox MouseEvents.
I'm trying to make some GUI gadgetries (docking, opacity..).
Here is an example:
I've linked all (GUI)-Objects to these two functions.
private void MyMouseMove(object sender, MouseEventArgs e)
{
this.Opacity = 1;
}
private void MyMouseLeave(object sender, EventArgs e)
{
this.Opacity = 0.5;
}
..expect the group panels, because they don't have MouseMove and MouseLeave events. Can they be added? A standard Panel has them as well.
I really like the layout of that GroupPanels (with that border and text), that's why I would love to be able to solve that problem with GroupBox.
That gadgets I create will only be triggered, if the cursor is in- or outside the form. (doesn't matter if inactive or active). Maybe there is another way to trigger it, than MouseMove and MouseLeave.
Using a Timer is probably the simplest solution!
Thank you LarsTech for linking to this 'Winform - determine if mouse has left user control' question.
I'm able to continue my Project with this sample below.
public partial class Form1 : Form
{
private Timer timer1;
public Form1()
{
InitializeComponent();
this.Opacity = 0.5D;
timer1 = new Timer();
timer1.Interval = 200;
timer1.Tick += timer1_Tick;
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
if (this.DesktopBounds.Contains(Cursor.Position))
this.Opacity = 1D;
else
this.Opacity = 0.5D;
}
}
credits goes to: Hans Passant
I have a windows form application with a PictureBox control containing an image. I want to move the PictureBox control to the right in a slow movement. Here is my code:
Point currentPoint = pictureBox_Logo.Location;
for (int i = 0; i < 25; i++)
{
pictureBox_Logo.Location = new Point(pictureBox_Logo.Location.X + 1, pictureBox_Logo.Location.Y);
Thread.Sleep(30);
}
The problem here is that when the code executes instead of seeing the picture move, I see a white picture move and the moving stops until the picture appears.
What am I missing and what can I do about it?
Code:
public partial class Form1 : Form
{
void timer_Tick(object sender, EventArgs e)
{
int x = pictureBox1.Location.X;
int y = pictureBox1.Location.Y;
pictureBox1.Location = new Point(x+25, y);
if (x > this.Width)
timer1.Stop();
}
public Form1()
{
InitializeComponent();
timer1.Interval = 10;
timer1.Tick += new EventHandler(timer_Tick);
}
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Show();
timer1.Start();
}
}
original thread is here Move images in C#
Try to use pictureBox_Logo.Refresh() after Thread.Sleep(30);
Or look for standard Timer control.
My code is good written, but what I did wrong was putting the code in an event:
private void Form1_Shown(object sender, EventArgs e);
But when I put my code in a button it works without any problems.