I'm having a problem with displaying transparent images with a transparent background. The transparent background takes the color of the underlying control and that is fine ... bu the problem is that some details (lines) on the underlying background are being covered the the images as can be seen in the image below.
Here is the code I am using.... This is the code for the notes....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Drawing;
namespace Simpe_Piano_new
{
class MusicNote: PictureBox
{
public SoundPlayer sp = new SoundPlayer();
Timer tmr = new Timer();
public int pitch; //The no. of the music key (e.g. the sound freuency).
public int noteDuration; //Shape of note.
public string noteShape;
public MusicNote(int iPitch, int iNoteDuration)
: base()
{
pitch = iPitch;
noteDuration = iNoteDuration;
Size = new Size(40, 40);
}
public void ShowNote()
{ if (this.noteDuration == 1) noteShape = "Quaver.png";
if (this.noteDuration == 4) noteShape = "Crotchet.png";
if (this.noteDuration == 7) noteShape = "minim.png";
if (this.noteDuration == 10) noteShape = "DotMin.png";
if (this.noteDuration == 12) noteShape = "SemiBreve.png";
this.BackgroundImage = Image.FromFile(noteShape);
this.BackColor = Color.Transparent;
Location = new Point((pitch * 40) - 40, 100);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
public void PlaySound()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
}
public void StopSound()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Stop();
}
public void Play()
{
sp.SoundLocation = this.pitch + ".wav";
sp.Play();
//Time to play the duration
tmr.Interval = noteDuration;
tmr.Start();
tmr.Tick += new System.EventHandler(ClockTick);
}
void ClockTick(object sender, EventArgs e)
{
sp.Stop();
tmr.Stop();
}
}
}
This is the code for the underlying control..the music staff
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace Simpe_Piano_new
{
public class MusicStaff: Panel
{
Pen myPen;
Graphics g;
public MusicStaff()
{
this.Size = new Size(1000, 150);
this.Location = new Point(0, 0);
this.BackColor = Color.Transparent;
this.Paint += new PaintEventHandler(DrawLines);
}
private void DrawLines(object sender, PaintEventArgs pea)
{
myPen = new Pen(Color.Black, 1);
g = this.CreateGraphics();
for (int i = 1; i < 6; i++)
{
g.DrawLine(myPen, 0, (this.Height / 6) * i, this.Width, (this.Height / 6) * i);
}
}
}
}
I have found that C# does not handle transparency really well...
Any help would be greatly appreciated..
add the top control "MusicNote" in the children of the underlying control "MusicStaff"
something like that after -Initializing all components-
// mStaff: the MusicStaff object
// mNote: the MusicNote object
mStaff.Children.Add(mNote);
in old scenario, the form is the parent of both of them, so they display the form background in any transparent area
after modifying the parent of the "MusicNote", it displays the "MusicStaff" background in the transparent area
I hope that help!
Two mistakes. PictureBox supports transparent images well, as long as you set its BackColor property to Color.Transparent. Which you did for the MusicStaff but not for the MusicNote. Layered transparency does not work, you don't need MusicStaff to be transparent, just the picture boxes.
This kind of transparency is simulated by asking the Parent to paint itself into the control to provide the background pixels. Which is your second mistake, you use CreateGraphics() in your DrawLines() method. Which draws directly to the screen, not the control surface. You must use pea.Graphics here.
Do note that the value-add you get from using PictureBox is a very low one. Controls are expensive and you'll easily burn up hundreds of them to display a sheet of music. You'll notice, it will become slow to paint itself. You avoid this by having MusicStaff just paint the notes itself, using Graphics.DrawImage() gets the job done. Transparency effects are now much simpler as well, just layers of paint. Which is the way WPF does it. The only inconvenience you'll have to deal with is that mouse hit testing isn't as simple anymore, you need to map the panel's MouseDown event's coordinates to a note. Just keep a List that keeps track where every note is displayed. You'll use that for painting as well as mouse hit testing.
Related
I am working on a program that displays the liveView image from a Nikon camera in a pictureBox. I want to be able to hover with the cursor over the image and display a zoomed in area around the cursor in another picturebox. I would also like to add a crosshair instead of mouse pointer. The only solution I have found so far is the following:
zoom an image in a second picturebox following cursor
It does exactly what I want, however I can not get it to work. More specifically, nothing is showing up in picZoom. In the example, images are loaded while in my case, a video stream is shown. That might be the reason why I am not getting it to work. I am relatively new to c#, and did not fully understand the example.
Lets say I have picBox where I receive the video stream. How do I show a portion of picBox around the cursor (let's say a rectangle around the cursor of dimensions x,y) in picZoom with a crosshair as in the example. I do not need to worry about differing dimensions of picBox and picZoom since they will not vary. I also want to be able to vary the degree of zoom by a factor zoomFactor.
If anyone could give me pointers or a solution, it would be greatly appreciated. Also, sorry if my question is poorly formatted, I am new to the forum.
Thank you!
Alexander
I would approach it like this
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MagnifierExample
{
class Magnifier : PictureBox
{
public Magnifier()
{
Visible = false;
}
PictureBox source;
private Point sourcePoint;
Cursor oldCursor;
public PictureBox Source
{
get
{
return source;
}
set
{
if (source != null)
{
source.MouseEnter -= Source_MouseEnter;
source.MouseLeave -= Source_MouseLeave;
source.MouseMove -= Source_MouseMove;
source.Cursor = oldCursor;
}
source = value;
if (source != null)
{
source.MouseEnter += Source_MouseEnter;
source.MouseLeave += Source_MouseLeave;
source.MouseMove += Source_MouseMove;
oldCursor = source.Cursor;
source.Cursor = Cursors.Cross;
}
}
}
private void Source_MouseEnter(object sender, EventArgs e)
{
Visible = true;
BringToFront();
}
private void Source_MouseLeave(object sender, EventArgs e)
{
Visible = false;
}
private void Source_MouseMove(object sender, MouseEventArgs e)
{
sourcePoint = e.Location;
Location = new Point(source.Location.X + e.X - Width / 2, source.Location.Y + e.Y - Height / 2);
Invalidate();
}
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 0x0084;
const int HTTRANSPARENT = (-1);
if (!DesignMode && m.Msg == WM_NCHITTEST)
{
m.Result = (IntPtr)HTTRANSPARENT;
}
else
{
base.WndProc(ref m);
}
}
protected override void OnPaint(PaintEventArgs pe)
{
if (!DesignMode && Source != null && Source.Image != null)
{
Rectangle destRect = new Rectangle(0, 0, Width, Height);
// IMPORTANT: This calculation will depend on the SizeMode of the source and the amount you want to zoom.
// This does 2x zoom and works with PictureBoxSizeMode.Normal:
Rectangle srcRect = new Rectangle(sourcePoint.X - Width / 4, sourcePoint.Y - Height / 4, Width / 2, Height / 2);
pe.Graphics.DrawImage(Source.Image, destRect, srcRect, GraphicsUnit.Pixel);
}
else
{
base.OnPaint(pe);
}
}
}
}
To hook it up all you have to do is add a Magnifier to your form, give it a size, and set its Source to the PictureBox you want it to magnify.
this.magnifier1.Source = this.pictureBox1;
I used the approach in this answer to ignore messages from the magnifier window.
Importantly, I only coded up the zoom math for the PictureBoxSizeMode.Normal SizeMode of the source PictureBox. But I think this is a pretty good start.
Not 100% sure what you wanted for crosshairs, but this uses the built-in crosshair cursor.
It's getting to the F_Paint event but not to the F_MouseDown event.
What I want to be able to draw rectangle on the F form.
Maybe since the F form is transparent it can't draw on it ? But it's never get to the F_MouseDown event I use a break point inside the F_MouseDown event.
Not sure why it's not getting to the MouseDown event.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tester
{
public partial class Form1 : Form
{
Ffmpeg ffmpeg = new Ffmpeg();
private bool _canDraw;
private int _startX, _startY;
private Rectangle _rect;
public Form1()
{
InitializeComponent();
BackColor = Color.Blue;
TransparencyKey = BackColor;
Opacity = 1;
var f = new HelperForm { Opacity = 0, ShowInTaskbar = false, FormBorderStyle = FormBorderStyle.None };
f.MouseDown += F_MouseDown;
f.MouseMove += F_MouseMove;
f.MouseUp += F_MouseUp;
f.Paint += F_Paint;
f.Show();
Visible = false;
Owner = f;
Visible = true;
Move += (o, a) => f.Bounds = Bounds;
Resize += (o, a) => f.Bounds = Bounds;
f.Bounds = Bounds;
ffmpeg.Start(#"d:\ffmpegx86\test.mp4", 24);
}
private void F_Paint(object sender, PaintEventArgs e)
{
//Create a new 'pen' to draw our rectangle with, give it the color red and a width of 2
using (Pen pen = new Pen(Color.Red, 2))
{
//Draw the rectangle on our form with the pen
e.Graphics.DrawRectangle(pen, _rect);
}
}
private void F_MouseUp(object sender, MouseEventArgs e)
{
//The system is no longer allowed to draw rectangles
_canDraw = false;
}
private void F_MouseMove(object sender, MouseEventArgs e)
{
//If we are not allowed to draw, simply return and disregard the rest of the code
if (!_canDraw) return;
//The x-value of our rectangle should be the minimum between the start x-value and the current x-position
int x = Math.Min(_startX, e.X);
//The y-value of our rectangle should also be the minimum between the start y-value and current y-value
int y = Math.Min(_startY, e.Y);
//The width of our rectangle should be the maximum between the start x-position and current x-position minus
//the minimum of start x-position and current x-position
int width = Math.Max(_startX, e.X) - Math.Min(_startX, e.X);
//For the hight value, it's basically the same thing as above, but now with the y-values:
int height = Math.Max(_startY, e.Y) - Math.Min(_startY, e.Y);
_rect = new Rectangle(x, y, width, height);
//Refresh the form and draw the rectangle
Refresh();
}
private void F_MouseDown(object sender, MouseEventArgs e)
{
//The system is now allowed to draw rectangles
_canDraw = true;
//Initialize and keep track of the start position
_startX = e.X;
_startY = e.Y;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ffmpeg.Close();
}
}
class HelperForm : Form
{
protected override CreateParams CreateParams
{
get
{
const int WS_EX_TOOLWINDOW = 0x80;
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TOOLWINDOW;
return cp;
}
}
}
}
There're several reasons preventing the rectangle from being drawn and firing mouse events. First, you're setting the Opacity to 0; this means whatever you try to draw could never be visible. Instead, you should set the TransparencyKey to the color in BackColor:
f.TransparencyKey = f.BackColor;
Then, you're trying to draw a rectangle using the object _rect which was never initialized; therefore the rectangle you're trying to draw will be drawn with the size of 0 width and 0 height which means it won't be drawn, so, during your initialization, you should give a default value for _rect e.g:
_rect = new Rectangle(Point.Empty, this.Size);
The drawn rectangle should be visible by now; however, the events won't fire because you're reversing form ownership, so, instead of
Owner = f;
Use:
f.Owner = this;
I'm working on a .NET solution with an unmanaged EXE. This means, i have no VisualStyles enabled.
I'm trying to use a marquee progessbar without using EnabledVisualStyles().
What happened is that my progressbar appears without any animation.
Mine:
Should be like this:
Do you know if this is possible at all? And is there any workaround?
Create User Control, take one panel in it, dock it in parent container. Take one timer control.
Your user control code should like:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ProgressBar
{
public partial class PBar : UserControl
{
public PBar()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
int incre = 0;
private void timer1_Tick(object sender, EventArgs e)
{
int width = 15;
int gap = 5;
Graphics g = panel1.CreateGraphics();
g.Clear(panel1.BackColor);
SolidBrush blueBrush = new SolidBrush(Color.DarkBlue);
g.FillRectangle(blueBrush, new Rectangle(new Point(incre, 0), new Size(width, panel1.Height - 1)));
g.FillRectangle(blueBrush, new Rectangle(new Point(incre + width + gap, 0), new Size(width, panel1.Height - 1)));
g.FillRectangle(blueBrush, new Rectangle(new Point(incre + 2 * (width + gap), 0), new Size(width, panel1.Height - 1)));
g.FillRectangle(blueBrush, new Rectangle(new Point(incre + 3* (width + gap), 0), new Size(width, panel1.Height - 1)));
incre += 10;
if (incre > panel1.Width)
incre = 0;
}
}
}
Build your application and drag your user control in your form.
Modify code and variable's values as per your requirement.
You can use picture box with gif image.
I work in a team working on a IDE similar to Visual Studio to develop custom Winform code for our local clients. In our code we have User Controls overridden to make our tasks easier but most of our controls are derived from basic C# Winform Controls.
I currently need help in implementing dotted border around all our controls, with the type of grip points as provided by Visual Studio.
Unselected Controls
Selected Controls
This feature is highly demanded as it can help in aligning without compensation on visual guidelines.
We have currently implemented a dark border around all controls, using
this.BackColor = Color.Black;
this.Height = ComboBox.Height + 4;
Which puts a black border around the generated Controls, which in the above code snippet is a ComboBox.
One member pointed us towards using Margins and Padding as shown in the Microsoft documentation: https://msdn.microsoft.com/library/3z3f9e8b(v=vs.110)
But this is mostly theory and does not seem to help much. the closest thing that has come to solve this problem so far has been an online CodeProject link:
public class MyGroupBox : GroupBox
{
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawBorder(e.Graphics, ClientRectangle,
Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset,
Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset,
Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset,
Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset);
}
}
I am surprized to not find a close match to my search so far, perhaps i am using the wrong terminology, as I recently got into programming in this domain.
I believe that future online searches are going to be benifitted, if this problem gets solved. Looking forward for pointers form those with experience in this problem. Really appreciate any help in this direction.
I work in a team working on a IDE similar to Visual Studio ....
Developing a custom form designer is not a trivial task and needs a lot of knowledge and a lot of time and I believe the best solution which you can use, is hosting windows forms designer.
It's not just about drawing selection borders:
Each control has it's own designer with specific features, for example some controls like MenuStrip has it's own designer which enables you to add/remove items on designer.
Controls may have some specific sizing and positioning rules. For example some of them are auto-sized like TextBox or docked controls can not be reposition by mouse and so on.
Components are not visible on your form which you may need to edit them.
Some properties are design-time properties.
Some properties are added using extender providers and you need to perform additional tasks to provide a way to change them in your custom designer.
And a lot of other considerations.
Solution 1 - Hosting Windows Forms Designer
To learn more about design time architecture, take a look at Design-Time Architecture. To host windows forms designer in your application, you need to implement some interfaces like IDesignerHost, IContainer, IComponentChangeService, IExtenderProvider, ITypeDescriptorFilterService, IExtenderListService, IExtenderProviderService.
For some good examples you can take a look at:
Hosting Windows Forms Designers by Tim Dawson
Tailor Your Application by Building a Custom Forms Designer with .NET by Sayed Y. Hashimi
You may find this post useful:
Hosting Windows Forms Designer - Serialize and Deserialize designer at runtime
The post contains a working example on how to host windows forms designer at run-time and generate code:
Solution 2 - Drawing selection border over a transparent panel
While I strongly recommend using the first solution, but just for learning purpose if you want to draw selection border around controls, you can add the forms which you want to edit as a control to the host form, then put a transparent panel above the form. Handle Click event of transparent Panel and find the control under mouse position and draw a selection border around it on transparent panel like this:
In the example, I just created a transparent panel and drew selection border. It's just an example and performing sizing and positioning is out of scope of the example. It's just to show you how you can draw selection border around controls. You also can use the idea to create a SelctionBorder control and encapsulate sizing and positioning logic in the control and instead of drawing the borders, add an instance of SelectionBorder control to transparent panel and in its sizing and positioning events, change corresponding control coordinates.
Please pay attention it's just an example and in a real designer environment you should consider a lot of important things.
Transparent Panel
using System.Windows.Forms;
public class TransparentPanel : Panel
{
const int WS_EX_TRANSPARENT = 0x20;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
}
Host Form
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
public partial class HostForm : Form
{
private Panel containerPanel;
private TransparentPanel transparentPanel;
private PropertyGrid propertyGrid;
public HostForm()
{
this.transparentPanel = new TransparentPanel();
this.containerPanel = new Panel();
this.propertyGrid = new PropertyGrid();
this.SuspendLayout();
this.propertyGrid.Width = 200;
this.propertyGrid.Dock = DockStyle.Right;
this.transparentPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.transparentPanel.Name = "transparentPanel";
this.containerPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.containerPanel.Name = "containerPanel";
this.ClientSize = new System.Drawing.Size(450, 210);
this.Controls.Add(this.transparentPanel);
this.Controls.Add(this.propertyGrid);
this.Controls.Add(this.containerPanel);
this.Name = "HostForm";
this.Text = "Host";
this.Load += this.HostForm_Load;
this.transparentPanel.MouseClick += this.transparentPanel_MouseClick;
this.transparentPanel.Paint += this.transparentPanel_Paint;
this.ResumeLayout(false);
}
private void HostForm_Load(object sender, EventArgs e)
{
this.ActiveControl = transparentPanel;
/**************************************/
/*Load the form which you want to edit*/
/**************************************/
var f = new Form();
f.Location = new Point(8, 8);
f.TopLevel = false;
this.containerPanel.Controls.Add(f);
SelectedObject = f;
f.Show();
}
Control selectedObject;
Control SelectedObject
{
get { return selectedObject; }
set
{
selectedObject = value;
propertyGrid.SelectedObject = value;
this.Refresh();
}
}
void transparentPanel_MouseClick(object sender, MouseEventArgs e)
{
if (this.Controls.Count == 0)
return;
SelectedObject = GetAllControls(this.containerPanel)
.Where(x => x.Visible)
.Where(x => x.Parent.RectangleToScreen(x.Bounds)
.Contains(this.transparentPanel.PointToScreen(e.Location)))
.FirstOrDefault();
this.Refresh();
}
void transparentPanel_Paint(object sender, PaintEventArgs e)
{
if (SelectedObject != null)
DrawBorder(e.Graphics, this.transparentPanel.RectangleToClient(
SelectedObject.Parent.RectangleToScreen(SelectedObject.Bounds)));
}
private IEnumerable<Control> GetAllControls(Control control)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAllControls(ctrl)).Concat(controls);
}
void DrawBorder(Graphics g, Rectangle r)
{
var d = 4;
r.Inflate(d, d);
ControlPaint.DrawBorder(g, r, Color.Black, ButtonBorderStyle.Dotted);
var rectangles = new List<Rectangle>();
var r1 = new Rectangle(r.Left - d, r.Top - d, 2 * d, 2 * d); rectangles.Add(r1);
r1.Offset(r.Width / 2, 0); rectangles.Add(r1);
r1.Offset(r.Width / 2, 0); rectangles.Add(r1);
r1.Offset(0, r.Height / 2); rectangles.Add(r1);
r1.Offset(0, r.Height / 2); rectangles.Add(r1);
r1.Offset(-r.Width / 2, 0); rectangles.Add(r1);
r1.Offset(-r.Width / 2, 0); rectangles.Add(r1);
r1.Offset(0, -r.Height / 2); rectangles.Add(r1);
g.FillRectangles(Brushes.White, rectangles.ToArray());
g.DrawRectangles(Pens.Black, rectangles.ToArray());
}
protected override bool ProcessTabKey(bool forward)
{
return false;
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.Refresh();
}
}
Some caution would be appropriate here, modeling a UI designer after the Winforms designer is an easy decision, actually implementing it is a job that can keep you occupied for many months. Discovering that you cannot paint outside the control bounds is indeed the very first obstacle you'll run into, many more like that.
The first shortcut you might consider is to draw place-holders for the controls so you don't depend on the Control class. Works fine as long as it doesn't have to look too closely like the real control (i.e. give up on WYSIWYG) and you don't have to resize them.
But you'll surely dismiss that. You then have to do the same thing the Winforms designer does, you have to overlay a transparent window on top of the design surface. You can draw anything you want on that overlay and it provides automatic mouse and keyboard isolation so the control itself is completely oblivious of the design-time interaction. Find examples of such an overlay in this post and this post.
Last but not least, it is worth mentioning that you can leverage the existing Winforms designer in your own projects as well. You have to implement IDesignerHost. And a bunch more, unfortunately the abstraction level is fairly high and the MSDN docs rather brief. Best thing to do is to work from a sample that shows a full-featured designer. This KB article has the link. Code is excellent and well documented, you get an almost complete designer with toolbox and Properties window which de/serializes the design from/to XML and can generate C# and VB.NET code. Do look past the garish UI, it doesn't enable Visual Styles and color choices are the kind that I would make :) Making it pretty wasn't the point of the code sample.
I Have Created I windows Form Application Hope this will Help you
BackEnd C# Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Paint += new PaintEventHandler(this_Paint);
}
private void this_Paint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.Green, 2.0F);
pen.DashStyle = DashStyle.Dash;
foreach (Control c in groupBox1.Controls)
{
e.Graphics.DrawRectangle(pen, (groupBox1.Location.X + c.Location.X)-1, (groupBox1.Location.Y + c.Location.Y)-1, c.Width + 2, c.Height + 2);
}
pen.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Designer C# Code
namespace WindowsFormsApplication2
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.comboBox2 = new System.Windows.Forms.ComboBox();
this.comboBox3 = new System.Windows.Forms.ComboBox();
this.comboBox4 = new System.Windows.Forms.ComboBox();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.BackColor = System.Drawing.Color.Transparent;
this.groupBox1.Controls.Add(this.comboBox4);
this.groupBox1.Controls.Add(this.comboBox3);
this.groupBox1.Controls.Add(this.comboBox2);
this.groupBox1.Controls.Add(this.comboBox1);
this.groupBox1.Location = new System.Drawing.Point(33, 36);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(193, 184);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "groupBox1";
//
// comboBox1
//
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(36, 40);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 21);
this.comboBox1.TabIndex = 0;
//
// comboBox2
//
this.comboBox2.FormattingEnabled = true;
this.comboBox2.Location = new System.Drawing.Point(36, 67);
this.comboBox2.Name = "comboBox2";
this.comboBox2.Size = new System.Drawing.Size(121, 21);
this.comboBox2.TabIndex = 1;
//
// comboBox3
//
this.comboBox3.FormattingEnabled = true;
this.comboBox3.Location = new System.Drawing.Point(36, 94);
this.comboBox3.Name = "comboBox3";
this.comboBox3.Size = new System.Drawing.Size(121, 21);
this.comboBox3.TabIndex = 1;
//
// comboBox4
//
this.comboBox4.FormattingEnabled = true;
this.comboBox4.Location = new System.Drawing.Point(36, 121);
this.comboBox4.Name = "comboBox4";
this.comboBox4.Size = new System.Drawing.Size(121, 21);
this.comboBox4.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.groupBox1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.ComboBox comboBox4;
private System.Windows.Forms.ComboBox comboBox3;
private System.Windows.Forms.ComboBox comboBox2;
}
}
Make GroupBox1 backgroundcolour 'Transparent' because I am drawing on Form not on
GroupBox
You Can also Create Border on Selected Controls by Adding if(c is ComboBox)
or if (c.Name == "comboBox1")
in foreach loop
!! Change the Color According to your Need !!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
hatchedPen = (Pen)SystemPens.ControlDarkDark.Clone();
hatchedPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Clear any existing grab handles
using (Graphics g = Graphics.FromHwnd(this.Handle))
{
foreach (Control ctrl in Controls)
{
var rect = GetGrabBounds(ctrl);
g.FillRectangle(SystemBrushes.ButtonFace, rect);
}
}
// Need to draw grab handles?
if (ActiveControl != null && e.ClipRectangle.IntersectsWith(GetGrabBounds(ActiveControl)))
{
DrawGrabHandles(ActiveControl);
}
}
private void DrawGrabHandles(Control ctrl)
{
using (Graphics g = Graphics.FromHwnd(this.Handle))
{
Rectangle bounds = GetGrabRect(ctrl);
g.DrawRectangle(hatchedPen, bounds);
foreach (Point pt in new Point[]
{
new Point(bounds.Left, bounds.Top),
new Point(bounds.Left + bounds.Width / 2, bounds.Top),
new Point(bounds.Right, bounds.Top),
new Point(bounds.Left, bounds.Top + bounds.Height / 2),
new Point(bounds.Right, bounds.Top + bounds.Height / 2),
new Point(bounds.Left, bounds.Bottom),
new Point(bounds.Left + bounds.Width / 2, bounds.Bottom),
new Point(bounds.Right, bounds.Bottom),
})
{
Rectangle r = new Rectangle(pt, new Size(5, 5));
r.X = r.X - 2;
r.Y = r.Y - 2;
g.FillRectangle(SystemBrushes.ButtonFace, r);
g.DrawRectangle(SystemPens.ControlDarkDark, r);
}
}
}
private static Rectangle GetGrabRect(Control ctrl)
{
var result = ctrl.Bounds;
result = Rectangle.Inflate(result, 4, 4);
result.X--;
result.Y--;
return result;
}
private static Rectangle GetGrabBounds(Control ctrl)
{
var result = GetGrabRect(ctrl);
result.Inflate(4, 4);
return result;
}
private Pen hatchedPen;
}
I have a user control chart in my Form1 designer and this is the code to resize it:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.Size = new Size(600, 600);
}
When I move the mouse to the control area it's not resizing it make it bigger but deleting some other controls.
This is an image before I move the mouse over the control:
And this is an image when I moved the mouse over the control:
This is the code of the user control where the chart is:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web;
using System.Windows.Forms.DataVisualization.Charting;
namespace GatherLinks
{
public partial class GraphChart : UserControl
{
public GraphChart()
{
InitializeComponent();
}
private double f(int i)
{
var f1 = 59894 - (8128 * i) + (262 * i * i) - (1.6 * i * i * i);
return f1;
}
private void GraphChart_Load(object sender, EventArgs e)
{
chart1.Series.Clear();
var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "Series1",
Color = System.Drawing.Color.Green,
IsVisibleInLegend = false,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line
};
this.chart1.Series.Add(series1);
for (int i = 0; i < 100; i++)
{
series1.Points.AddXY(i, f(i));
}
chart1.Invalidate();
}
}
}
EDIT:
I did this in the user control class code:
public void ChangeChartSize(int width, int height)
{
chart1.Size = new Size(width, height);
chart1.Invalidate();
}
I had to add chart1.Invalidate(); to make it to take effect but then it sized the chart it self inside the user control. The user control was not changed.
So in the Form1 mouse enter I also changing the graphChart1 the control size:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
graphChart1.Size = new Size(600, 600);
}
The problem is that now it's taking a lot of time almost 20 seconds or so until it take effect when I'm moving the mouse over the control. If I will remove the second line:
graphChart1.Size = new Size(600, 600);
it will work fast but then it will change the chart only inside the control but it won't change the control size.
Tried also with invalidate:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
graphChart1.Size = new Size(600, 600);
graphChart1.Invalidate();
}
But still very slow. Maybe I need to change the control it self size also in the user control class code and not in Form1 ?
The problem is that you are resizing the GraphicChart (your user control) but not the Chart itself. You could add the method in your GraphChart class in order to do that. This is the method that will change the chart size:
public void ChangeChartSize(int width, int height)
{
chart1.Size = new Size(width, height);
}
And in your mouse enter event handler you could call something like this:
void graphicChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
}
With graphChart1.Size = you are resizing your container but not the chart within it.
The easiest work-around is probably to make chart1 public in the control and do graphChart1.chart1.Size = instead.
In the user control class code I did:
public void ChangeChartSize(int width, int height)
{
this.Size = new Size(width, height);
chart1.Size = new Size(width, height);
chart1.Invalidate();
}
In Form1 I did:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
}
Working smooth.