Change FormBorderStyle without client area moving - c#

I have a floating borderless form that contains two buttons. When the user moves the mouse over the form, the FormBorderStyle changes to SizableToolWindow and then returns after a set time using a timer. When this happens the form shifts to accommodate the title bar and Form edge. I am able to compensate for this however when it happens you get a flicker of the form being shifted before being placed back into place.
Is there any way I can stop the window refreshing until after I have already shifted it back into place?
Here's my shifting code:
if (this.FormBorderStyle != FormBorderStyle.None)
{
// Suspend layout of Form
this.SuspendLayout();
// Suspend layout of button controls
this.cbBlankDisplay.SuspendLayout();
this.btnPurgeMessages.SuspendLayout();
this.FormBorderStyle = FormBorderStyle.None;
this.Left += this.change.Width;
this.Top += this.change.Height;
// Resume layout of buttons and Form
this.btnPurgeMessages.ResumeLayout();
this.cbBlankDisplay.ResumeLayout();
this.ResumeLayout();
}

I ended up doing as Hans Passant suggested and creating a duplicate of my ClientRectangle area which is displayed on an already transparent full screen overlay.
My MouseLeave Event just starts the Timer.
This is the Code in my MouseEnter Event:
private void FloatingButtons_MouseEnter(object sender, EventArgs e)
{
if (this.FormBorderStyle != FormBorderStyle.SizableToolWindow)
{
if (this.Tag is Bitmap)
{
Owner.overlay.CreateGraphics().DrawImage(
(Bitmap)this.Tag,
new Rectangle(
Point.Add(this.Location, this.change),
this.ClientRectangle.Size),
new Rectangle(this.Location, this.ClientRectangle.Size),
GraphicsUnit.Pixel
);
}
this.Hide();
this.SuspendLayout();
this.cbBlankDisplay.SuspendLayout();
this.btnPurgeMessages.SuspendLayout();
if (this.change.Height == 0)
{
this.FormBorderStyle = FormBorderStyle.SizableToolWindow;
Rectangle scrPosition = RectangleToScreen(this.ClientRectangle);
this.change.Width = (scrPosition.Left - this.Left);
this.change.Height = (scrPosition.Top - this.Top);
}
this.Left -= this.change.Width;
this.Top -= this.change.Height;
this.FormBorderStyle = FormBorderStyle.SizableToolWindow;
this.btnPurgeMessages.ResumeLayout();
this.cbBlankDisplay.ResumeLayout();
this.ResumeLayout();
this.Show();
if (this.Tag != null && this.Tag is Bitmap)
{
((Bitmap)this.Tag).Dispose();
this.Tag = null;
Overlay.performUpdate = true;
}
}
}
This is the code in my Timer_Tick Event:
if (this.FormBorderStyle != FormBorderStyle.None)
{
// Create a bitmap the size of my Form
Bitmap bmp = new Bitmap(this.Bounds.Width, this.Bounds.Height);
// Copy the form to the newly created Bitmap
this.DrawToBitmap(bmp, new Rectangle(Point.Empty, this.Bounds.Size));
// Create a rectangle of the Location and Size of the ClientArea
Rectangle rect = new Rectangle((Point)this.change, this.ClientRectangle.Size);
// The Owner Form contains a class that already performs overlays on the screen
Owner.overlay.CreateGraphics().DrawImage(
bmp,
new Rectangle(
Point.Add(this.Location, this.change),
this.ClientRectangle.Size),
rect,
GraphicsUnit.Pixel
);
// Store the Bitmap in the Tag for Disposal after being used
this.Tag = bmp;
// Now I can hide my Form and perform necessary changes
this.Hide();
this.SuspendLayout();
this.cbBlankDisplay.SuspendLayout();
this.btnPurgeMessages.SuspendLayout();
this.FormBorderStyle = FormBorderStyle.None;
this.Left += this.change.Width;
this.Top += this.change.Height;
this.btnPurgeMessages.ResumeLayout();
this.cbBlankDisplay.ResumeLayout();
this.ResumeLayout();
this.Show();
}

Related

How do I reduce the flickering when the form is refreshing?

So when ever I hold the left mouse button and draw the rectangle on the form.
The form itself keeps flickering.
I've tried setting the DoubleBuffered property to true, that didnt change anything.
Is there a way to change the refresh rate or something similar?
Because from what I've tried, the example above and
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
It doesnt seem to change anything
Here is a gif showing the flickering
https://i.imgur.com/Wa3kmbM.gifv
private void Form1_Load(object sender, EventArgs e)
{
//Hide the Form
this.Hide();
label1.Visible = false;
label2.Visible = false;
//Create the Bitmap (This is an a black bitmap holding just the size.) (Bitmap is mutable)
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height);
//Create a graphics object that's ready for alteration. `printscreen` is now a graphics Object
Graphics graphics = Graphics.FromImage(printscreen);
//Alter the graphics object which again is the printscreen
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
//Create a temporary memory stream for the image
using (MemoryStream s = new MemoryStream())
{
//save graphic variable into memory
printscreen.Save(s, ImageFormat.Bmp);
//Set the size of the picturebox
pictureBox1.Size = new Size(Width, Height);
//set the value of the picturebox.Image to an Image.FromStream and load the temp stream
pictureBox1.Image = Image.FromStream(s);
}
//Show Form
this.Show();
//Cross Cursor
Cursor = Cursors.Cross;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
//startX is holds the corresponding value of where the mouse is in relation to the pixels of the width
//for instance, if it's all the way to the right, it holds the value of 1920.
startX = e.X;
startY = e.Y;
selectPen = new Pen(Color.DimGray, 2);
selectPen.DashStyle = DashStyle.Dash;
pictureBox1.Refresh();
start = true;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (start)
{
pictureBox1.Refresh();
//selectingWidth is equal to how much we have selected from the starting point.
//Let's say the starting point is 10 and our current mouse position is at 10 then we have selected 0 pixels to the right.
//However if we move our mouse 10 pixels to the right it means we have selected 10 pixels to the right.
selectingWidth = e.X - startX;
selectingHeight = e.Y - startY;
//if the selectingWidth is less than 0, then set the origin to the current position of the mouse.
var drawfromX = selectingWidth < 0 ? e.X : startX;
var drawfromY = selectingHeight < 0 ? e.Y : startY;
pictureBox1.Refresh();
pictureBox1.CreateGraphics().DrawRectangle(selectPen,
drawfromX,
drawfromY,
Math.Abs(selectingWidth),
Math.Abs(selectingHeight));
}
}

c# form running after close

I have an app with 2 forms. Form1 have the pictureBox and buttons, Form2 has a code that, when i call the form:
private void button1_Click(object sender, EventArgs e)
{
new Form2().Show();
}
it turns is a Zoom Lens, that i can use in Form1 pictureBox.
Problem is, when Form2(lens) is runing and i click ESC to close the form2, it closes but keep increasing consuming memory. Even the errors that form2(lens) has is triggering, like move mouse too far at the border, even after call close to form2.
Here is the code to the Lens form2:
PictureBox pictureBox1 = new PictureBox(); // Have a picture box
int zoom = 1; // Variable for zoom value
public Form1()
{
pictureBox1.Dock = DockStyle.Fill; // Occupy the full area of the form
pictureBox1.BorderStyle = BorderStyle.FixedSingle; // Have a single border of clear representation
Controls.Add(pictureBox1); // Add the control to the form
FormBorderStyle = FormBorderStyle.None; // Make the form borderless to make it as lens look
Timer timer = new Timer(); // Have a timer for frequent update
timer.Interval = 100; // Set the interval for the timer
timer.Tick += timer_Tick; // Hool the event to perform desire action
timer.Start(); //Start the timer
printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); // Have a bitmap to store the image of the screen
}
void timer_Tick(object sender, EventArgs e)
{
var graphics = Graphics.FromImage(printscreen as Image); // Get the image of the captured screen
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size); // Get the copy of screen
var position = Cursor.Position; // Get the position of cursor
var lensbmp = new Bitmap(50, 50); // Have a bitmap for lens
var i = 0; // Variable for row count
var j = 0; // Variable for column count
for (int row = position.X - 25; row < position.X + 25; row++) // Indicates row number
{
j = 0; // Set column value '0' for new column
for (int column = position.Y - 25; column < position.Y + 25; column++) // Indicate column number
{
lensbmp.SetPixel(i, j, printscreen.GetPixel(row, column)); // Place current region pixel to lens bitmap
j++; // Increase row count
}
i++; // Increase column count
}
this.pictureBox1.Image = new Bitmap(lensbmp, lensbmp.Width * zoom, lensbmp.Height * zoom); // Assign lens bitmap with zoom level to the picture box
Size = pictureBox1.Image.Size; // Assign optimal value to the form
Left = position.X + 20; // Place form nearer to cursor X value
Top = position.Y + 20; // Place form nearer to cursor Y value
TopMost = true; // Keep the form top level
}
// Override OnKeyDown for zoom in and zoom out actions
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyValue == 73) // Set "i" as the key for Zoom In.
zoom++; // Increase zoom by 1 item greater
else if (e.KeyValue == 79) // Set "o" as the key for Zoom Out
zoom--; // Decrease zoom by 1 item smaller
else if (e.KeyValue == 27) // Set "Esc" to close the magnifier
{
Close(); // Close the form
Dispose(); // Dispose the form
}
base.OnKeyDown(e);
}
Is that a way to close this form2 and stop all methods while form1 keep runing? It keep increasing memory consume like 1mb for sec.
You have a dangerous timer because it isn't declared at the form scope, so it can still keep running.
Declare it at the form level instead:
PictureBox pictureBox1 = new PictureBox();
int zoom = 1;
Timer timer = new Timer();
public Form1()
{
pictureBox1.Dock = DockStyle.Fill; // Occupy the full area of the form
pictureBox1.BorderStyle = BorderStyle.FixedSingle; // Have a single border of clear representation
Controls.Add(pictureBox1); // Add the control to the form
FormBorderStyle = FormBorderStyle.None; // Make the form borderless to make it as lens look
timer.Interval = 100; // Set the interval for the timer
timer.Tick += timer_Tick; // Hool the event to perform desire action
timer.Start(); //Start the timer
printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); // Have a bitmap to store the image of the screen
}
Also, make sure you dispose of your image and graphic objects, too, when they aren't being used anymore.

Display image being dragged as it is dragged [duplicate]

This question already has answers here:
C# Drag-and-Drop: Show the dragged item while dragging
(5 answers)
Closed 8 years ago.
I am dragging a picturebox that has a background image in it onto another picturebox, and when it is dropped i will call a method that draws the image to the drop location. When it drags, it just shows the small square icon indicating that it can be dropped. How do i display the image in the picturebox being dragged?
You can add 2 PictureBoxes which have the same Location, BackgroundImage, BackgroundImageLayout, Size. 1 PictureBox is for dragging, 1 PictureBox is fixed (in Size and Location during runtime). Everything is very simple. Here is the demo code for you:
public partial class Form1 : Form {
public Form1(){
InitializeComponent();
draggingPic.Location = pictureBox2.Location;
draggingPic.Size = pictureBox2.Size;
draggingPic.Parent = this;
draggingPic.BackgroundImage = pictureBox2.BackgroundImage;
draggingPic.BackgroundImageLayout = pictureBox2.BackgroundImageLayout;
draggingPic.BorderStyle = pictureBox2.BorderStyle;
draggingPic.BringToFront();//This is important, your draggingPic should be on Top
//MouseDown event handler for draggingPic
draggingPic.MouseDown += (s, e) => {
downPoint = e.Location;
};
//MouseMove event handler for draggingPic
draggingPic.MouseMove += (s, e) => {
if(e.Button == MouseButtons.Left){
draggingPic.Left += e.X - downPoint.X;
draggingPic.Top += e.Y - downPoint.Y;
}
};
//MouseUp event handler for draggingPic
draggingPic.MouseUp += (s, e) => {
g.DrawImage(draggingPic.BackgroundImage, new Rectangle(pictureBox1.PointToClient(draggingPic.PointToScreen(Point.Empty)), draggingPic.Size));
draggingPic.Location = pictureBox2.Location;
};
//Initialize bm
//your pictureBox1 should have fixed Size during runtime
//Otherwise we have to recreate bm in a SizeChanged event handler
bm = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.Image = bm;
g = Graphics.FromImage(bm);
}
Bitmap bm;
Graphics g;
Point downPoint;
PictureBox draggingPic = new PictureBox();
}
Initial look:
When dragging:
After some drag-drops:

C# - Transparent modal form on a window

I want to use fully transparent Modal form in my application, with being able to fill it with partially-transparent image; For this, I used to remove all visible elements from the form and got the code below.
class WinScreenshotWindow : Form
{
public WinScreenshotWindow()
{
// Create from without erasing background with a color
// Going not to use transparent form instead, it will produce context menu bugs in textboxes for child form
this.SuspendLayout();
this.MaximizeBox = false;
this.MinimizeBox = false;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.None;
this.StartPosition = FormStartPosition.Manual;
this.ControlBox = false;
this.Visible = false;
this.Size = new Size(100, 100);
this.Location = new Point(200, 200);
this.ResumeLayout();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// Erase Background Windows message:
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle clientRect = e.ClipRectangle;
e.Graphics.FillRectangle(Brushes.Transparent, clientRect);
}
}
static void Main()
{
Form form = new Form();
form.Size = new Size(400, 400);
form.Show();
var ww = new WinScreenshotWindow();
ww.ShowDialog(form);
}
But the result is something strange:
When I remove filling in OnPaint(), it is not visible at all.
The question is - why does this happen? If the background is transparent why do it shows the form in such way? And what can be done in this situation?
Any help appreciated.
Wouldn't it be easier to open a borderless form with a red backcolor and set the TransparencyKey = red?

C# WinForms problem with draw image

class OriginalImage: Form
{
private Image image;
private PictureBox pb;
public OriginalImage()
{
pb = new PictureBox {SizeMode = PictureBoxSizeMode.CenterImage};
pb.SizeMode = PictureBoxSizeMode.StretchImage;
Controls.Add(pb);
image = Image.FromFile(#"Image/original.jpg");
this.Width = image.Width;
this.Height = image.Height;
this.Text = "Original image";
this.Paint += new PaintEventHandler(Drawer);
}
public virtual void Drawer(object source, PaintEventArgs e)
{
Graphics g = pb.CreateGraphics();
g.DrawImage(image,0,0);
}
I call this create object OriginalImage in other form on button click, but image is not draw? Where is problem?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var oi = new OriginalImage();
oi.Show();
}
}
You're creating a PictureBox and adding it to your controls, but you never actually use it (you're drawing the image manually in the Paint event). Why? This control is likely obscuring the drawing area of the form, as any controls go on top of whatever you draw in the Paint event.
In addition, you're getting the Graphics object by calling CreateGraphics on the PictureBox rather than the Form itself. This is wrong, as the PictureBox's Paint event will fire after this code, erasing whatever you draw.
I would recommend changing your OriginalForm code to the following:
class OriginalImage: Form
{
private Image image;
private PictureBox pb;
public OriginalImage()
{
pb = new PictureBox();
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Dock = DockStyle.Fill; // this will make the PictureBox occupy the
// whole form
Controls.Add(pb);
image = Image.FromFile(#"Image/original.jpg");
this.ClientSize = new Size(image.Width, image.Height); // this allows you to
// size the form while
// accounting for the
// border
this.Text = "Original image";
pb.Image = image; // use this instead of drawing it yourself.
}
}

Categories