I have made a control which inherits TextBox, and I'm trying to give a notebook grid:
I already have the code that will specify where to draw the lines including all of the grids features, but I'm not sure what to draw it to.
I've Googled a lot and searched for a brush that will let me have the same interface as a DrawingContext (so I could call drawingContext.DrawLine() etc.), or something familiar, but I couldn't find any!
So how can I achieve to get my grid background?
P.S I can't create a static bmp file and load it, because the grid color and spacing would most certainly change
You could try using DrawingVisual to get your DrawingContext then create a VisualBrush to assign to your Background. Something like this.
DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();
dc.DrawLine( new Pen(Brushes.Red,5),new Point(0,0),new Point(50,50));
dc.Close();
VisualBrush vb = new VisualBrush(dv);
textBox1.Background = vb;
You can intercept the Paint event for your control. You get a PaintEventArgs argument, which includes a ClipRectangle and a Graphics object.
Check out Control.Paint Event.
Once you have your Graphics object, you can call DrawLine and FillRectangle on it directly.
You're looking to make a custom-drawn control. You'll want to override the OnPaint method of your control class and draw the background in that method. Here's an example on how to do it: http://msdn.microsoft.com/en-us/library/b818z6z6(v=vs.90).aspx
To draw your background, grab the drawing context and draw your background after first calling the base OnPaint method:
protected override void OnPaint(PaintEventArgs pe)
{
// Call the OnPaint method of the base class.
base.OnPaint(pe);
// Declare and instantiate a new pen.
System.Drawing.Pen myPen = new System.Drawing.Pen(Color.Aqua);
// Draw an aqua rectangle in the rectangle represented by the control.
pe.Graphics.DrawRectangle(myPen, new Rectangle(this.Location, this.Size));
}
EDIT:
Since you're using WPF, you can take a look here to see a full example on custom designs: WPF .NET 3.5 Drawing Customized Controls and Custom UI Elements
Related
In my WPF application, I have added WindowsFormsHost in one grid, I want to draw a rectangle on the control inside WinFormsHost.
Application layout:
Code I'm trying:
Adorner Class
public class SimpleRectAdorner : Adorner
{
// Be sure to call the base class constructor.
public SimpleRectAdorner(UIElement adornedElement)
: base(adornedElement)
{
}
// A common way to implement an adorner's rendering behavior is to override the OnRender
// method, which is called by the layout system as part of a rendering pass.
protected override void OnRender(DrawingContext drawingContext)
{
Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
// Some arbitrary drawing implements.
SolidColorBrush renderBrush = new SolidColorBrush(Colors.Green);
renderBrush.Opacity = 0.2;
Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
// Draw a circle at each corner.
Rect rect = new Rect(new Point(adornedElementRect.TopLeft.X, adornedElementRect.TopLeft.Y + 50), new Size(150, 50));
drawingContext.DrawRectangle(renderBrush, renderPen, rect);
}
}
Code to add adorner
private void btnDraw_Click(object sender, RoutedEventArgs e)
{
AdornerLayer.GetAdornerLayer(viewerGrid.Children[0]).Add(new SimpleRectAdorner(viewerGrid.Children[0]));
}
Is there any possible way to draw a rectangle on Control which is inside WindowsFormsHost?
Thanks in advance.
As noted in the comment by Clemens, WindowsFormsHost is rendered separately from the rest of your Window, and by necessity it is rendered on top of the Window. At first glance, this seems to be a design limitation about which you can do nothing; however, that is not strictly true.
If a second layer is added over your first layer, simply add a third layer on top of the second. Another Window or a Popup can render over the top of your WindowsFormsHost, and while you will have to jump through some hoops to make it all seem like part of the same Window--ensuring everything moves, minimizes, and restores at the same time, etc--it is certainly possible to do so.
You can use transparency in your third layer to allow the content in the WindowsFormsHost to show and be accessed. For example, you can set AllowsTransparency to true on your WPF Popup. It will be a bit of extra work, but if you absolutely need this feature, you can do it.
I have a windows form with several controls, e.g. labels and buttons. When the form is painted, in the Paint event handler, I can use the PaintEventArgs e to:
private void Form_Paint(object sender, PaintEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
SolidBrush brush = new SolidBrush(Color.Black);
e.Graphics.DrawString("Test String", font, brush, 100, 100);
}
This way I can create a string using Graphics.DrawString() that conforms to the properties I set such as TextRenderingHint.
How can I change the Graphics properties for all the controls on the form, the labels and buttons etc, so that when they are painted/rendered they conform to the Graphics properties as I would like them to?
Specifically - I want to change the TextRenderingHint for controls on the form. I'd be equally happy if doing this for the Form itself including all controls was possible.
How can I change the Graphics properties for all the controls on the form, the labels and buttons etc, so that when they are painted/rendered they conform to the Graphics properties as I would like them to?
You can't.
As Hans has said in the comments, the built-in controls for Winforms are mostly just thin wrappers around existing native Windows control classes. They will render using the current user settings, which are global for all applications.
Even if they weren't, there's the other problem that the Graphics instance being used is new for every Paint event, and each window-based control (i.e. most of them) gets a Graphics instance corresponding to the native HDC for that control's window's WM_PAINT event. There's no "global" Graphics instance that you could change, and which then would be reused for every Paint event.
I am writing a program in Visual C# 2010 that has several icons on the form. When the mouse is placed over the icon (which is just an image) I want the icon to b highlighted via a border around the icon. In visual basic i can make a transparent rectangle with a colored border and position it over the icon. In C#, i can do the same however until i call invalidate multiple borders appear. The problem with calling invalidate is that my program is doing something in the background every second so the border keeps flashing (re-drawing).
Anyone got any ideas how i can implement this?
You didn’t say how you draw the border but from your description you are creating a graphics context for this. Don’t do this, it’s wrong. Instead, draw inside the Paint element of either the control or the its parent container.
The Paint event handler could look as follows:
private void yourControl_Paint(object sender, PaintEventArgs e)
{
if (! HasFocus(yourControl))
return;
Graphics g = e.Graphics;
using (Pen p = new Pen(Color.FromArgb(128, 0, 0, 128)))
g.DrawRectangle(p, 0, 0, yourControl.Width -1, yourControl.Height - 1);
}
This uses a hypothetical HasFocus method to determine whether this control should have a focus rectangle.
By the way, this is identical in VB and C#.
How do put rectangular box around few controls on my winform? (i dont want the grouping thing).
If you don't want to use a GroupBox, you can put your controls in a Panel and set its BorderStyle property to BorderStyle.FixedSingle or BorderStyle.Fixed3D.
What's wrong with the GroupBox control? Grouping together a related set of controls is exactly what it's intended for. Your users have seen it in every other application they use, and throughout the Windows shell. They're much more likely to recognize what it means than your own custom-drawn rectangle. Deviating from standard platform conventions is rarely a good idea. I strongly recommend using the GroupBox control, even if it's not exactly the perfect look that you had in mind.
That being said, it's certainly possible to draw your own box around a group of controls on a form. To do so, you'll need to override your form's OnPaint method and write some code to draw a rectangle. Doing it this way gives you complete control over the color of your box, as well as the line thickness.
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// Call the base class
base.OnPaint(e);
// Create your drawing pen
using (Pen p = new Pen(SystemColors.WindowText, 2.0))
{
// Calculate the position and dimensions of the box
Rectangle rect = new Rectangle(10, 10, 30, 30);
// Draw the rectangle
e.Graphics.DrawRectangle(p, rect);
}
}
The only thing you'll need to add is the code that calculates the dimensions of your rectangle, relative to the controls you want it to surround. Use the Location property of each control to get this information.
You can put your controls into a panel and set its BorderStyle from None to FixedSingle - it is the easiest way
http://msdn.microsoft.com/en-us/library/cyh3c8h8.aspx
Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0));
e.Graphics.DrawLine(pen, 20, 10, 300, 100);
You can draw lines on a windows form this way. This would hook into the Paint method where e is PaintEventArgs
I have created a UserControl which simply defines a new GraphicsPath and sets that to be the Region of the control. Its primary use is to act as a backdrop for other controls so typically the only thing set on it is BackColor. When I call DrawToBitmap on the control's parent, the child control is drawn as a rectangle rather than getting clipped to region I expected. Am I missing something here?
Standard use of the control does not exhibit this problem.
Also, I need to be able to draw this control to an image while it is not currently shown on screen. I have seen some workarounds would could have worked had I not had this additional requirement.
DrawToBitmap does not honor regions. But Graphics.CopyFromScreen does.
Bitmap bitmap = new Bitmap(this.Width, this.Height);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(this.Location, new Point(0, 0), this.Size);
}