This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I change the border thickness of a Groupbox on a windows form in C#?
Guys
I am using groupbox' in Visual studio. But the Border in the groupbox is to small. I was wondering if there is a way to edit the border by giving it a color or maybe a thicker edge?
As u can see in the image it is very hard to see the border around it.
Can anyone help me with this ?
You can Use This:
using System.Drawing;
using System.Drawing.Drawing2D;
private void Form1_Load(object sender, EventArgs e)
{
myGroupBox myGroupBox = new myGroupBox();
myGroupBox.Text = "GroupBox1";
this.Controls.Add(myGroupBox);
}
public static GraphicsPath CreatePath(float x, float y, float width, float height,
float radius, bool RoundTopLeft, bool RoundTopRight, bool RoundBottomRight, bool RoundBottomLeft)
{
float xw = x + width;
float yh = y + height;
float xwr = xw - radius;
float yhr = yh - radius;
float xr = x + radius;
float yr = y + radius;
float r2 = radius * 2;
float xwr2 = xw - r2;
float yhr2 = yh - r2;
GraphicsPath p = new GraphicsPath();
p.StartFigure();
//Top Left Corner
if (RoundTopLeft)
{
p.AddArc(x, y, r2, r2, 180, 90);
}
else
{
p.AddLine(x, yr, x, y);
p.AddLine(x, y, xr, y);
}
//Top Edge
p.AddLine(xr, y, xwr, y);
//Top Right Corner
if (RoundTopRight)
{
p.AddArc(xwr2, y, r2, r2, 270, 90);
}
else
{
p.AddLine(xwr, y, xw, y);
p.AddLine(xw, y, xw, yr);
}
//Right Edge
p.AddLine(xw, yr, xw, yhr);
//Bottom Right Corner
if (RoundBottomRight)
{
p.AddArc(xwr2, yhr2, r2, r2, 0, 90);
}
else
{
p.AddLine(xw, yhr, xw, yh);
p.AddLine(xw, yh, xwr, yh);
}
//Bottom Edge
p.AddLine(xwr, yh, xr, yh);
//Bottom Left Corner
if (RoundBottomLeft)
{
p.AddArc(x, yhr2, r2, r2, 90, 90);
}
else
{
p.AddLine(xr, yh, x, yh);
p.AddLine(x, yh, x, yhr);
}
//Left Edge
p.AddLine(x, yhr, x, yr);
p.CloseFigure();
return p;
}
class myGroupBox : GroupBox
{
public myGroupBox()
{
base.BackColor = Color.Transparent;
}
[Browsable(false)]
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
}
}
private Color backColor = Color.Transparent;
public Color ActualBackColor
{
get { return this.backColor; }
set { this.backColor = value; }
}
protected override void OnPaint(PaintEventArgs e)
{
Size tSize = TextRenderer.MeasureText(this.Text, this.Font);
Rectangle borderRect = e.ClipRectangle;
borderRect.Y += tSize.Height / 2;
borderRect.Height -= tSize.Height / 2;
GraphicsPath gPath = CreatePath(0, borderRect.Y, (float)(this.Width - 1), borderRect.Height - 1, 5, true, true, true, true);
e.Graphics.FillPath(new SolidBrush(ActualBackColor), gPath);
e.Graphics.DrawPath(new Pen(Color.Red), gPath);
borderRect.X += 6;
borderRect.Y -= 7;
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), borderRect);
}
}
Related
I was trying to make a normal rounding. And I can't smooth out the rounding itself for the button.
And the second question, how do I round off the button so that the photo that is used in BackgroundImage doesn't get rounded off???
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Test_Project.SupportClass
{
public class Buttom_Class4 : Button
{
public Buttom_Class4()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.ResizeRedraw, true);
}
private int radius = 20;
[DefaultValue(20)]
public int Radius
{
get { return radius; }
set
{
radius = value;
this.RecreateRegion();
}
}
private GraphicsPath GetRoundRectagle(Rectangle bounds, int radius)
{
GraphicsPath path = new GraphicsPath();
path.AddArc(bounds.X, bounds.Y, radius, radius, 180, 90);
path.AddArc(bounds.X + bounds.Width - radius, bounds.Y, radius, radius, 270, 90);
path.AddArc(bounds.X + bounds.Width - radius, bounds.Y + bounds.Height - radius,
radius, radius, 0, 90);
path.AddArc(bounds.X, bounds.Y + bounds.Height - radius, radius, radius, 90, 90);
path.CloseAllFigures();
return path;
}
private void RecreateRegion()
{
var bounds = ClientRectangle;
bounds.Width--; bounds.Height--;
using (var path = GetRoundRectagle(bounds, this.Radius))
this.Region = new Region(path);
this.Invalidate();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.RecreateRegion();
}
}
}
Both labels have AutoSize true & TextAlign MiddleCenter.
How can also label2 show smooth borders?
Here is the test code for handlers Form.Load(...) & Form.Paint(...):
int _cornerRadius = 10;
Point _locationLabel2;
// Form.Load(...)
private void Form3_Load(object sender, EventArgs e)
{
// Step 1: Cut the label regions (seems to be ok, result is the same for both labels)
GraphicsPath graphicsPath = _getRoundPath(label1.ClientRectangle, _cornerRadius);
label1.Region = new Region(graphicsPath);
graphicsPath = _getRoundPath(label2.ClientRectangle, _cornerRadius);
label2.Region = new Region(graphicsPath);
_locationLabel2 = this.PointToClient(label2.Parent.PointToScreen(label2.Location));
}
// Form.Paint(...)
private void Form3_Paint(object sender, PaintEventArgs e)
{
using (Pen pen = new Pen(label1.BackColor, 3.0f))
{
// Step 2: Smooth the label borders (ok only for label1)
_drawRoundedRectangle(e.Graphics, pen, label1.Location.X, label1.Location.Y,
label1.ClientRectangle.Width, label1.ClientRectangle.Height, _cornerRadius);
_drawRoundedRectangle(e.Graphics, pen, _locationLabel2.X, _locationLabel2.Y,
label2.ClientRectangle.Width, label2.ClientRectangle.Height, _cornerRadius);
}
}
// Helper 1/3
private static GraphicsPath _getRoundPath(Rectangle rectangle, int radius)
{
int x = rectangle.X;
int y = rectangle.Y;
int width = rectangle.Width;
int height = rectangle.Height;
radius = radius << 1;
GraphicsPath path = new GraphicsPath();
if (radius > 0)
{
if (radius > height) radius = height;
if (radius > width) radius = width;
path.AddArc(x, y, radius, radius, 180, 90);
path.AddArc(x + width - radius, y, radius, radius, 270, 90);
path.AddArc(x + width - radius, y + height - radius, radius, radius, 0, 90);
path.AddArc(x, y + height - radius, radius, radius, 90, 90);
path.CloseFigure();
}
else
{
path.AddRectangle(rectangle);
}
return path;
}
// Helper 2/3
private void _drawRoundedRectangle(Graphics graphics, Pen pen, int x, int y, int width, int height, int radius)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = _generateRoundedRectangle(graphics, rectangle, radius);
SmoothingMode old = graphics.SmoothingMode;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawPath(pen, path);
graphics.SmoothingMode = old;
}
// Helper 3/3
private static GraphicsPath _generateRoundedRectangle(Graphics graphics, RectangleF rectangle, int radius)
{
GraphicsPath path = new GraphicsPath();
float diameter = radius * 2.0F;
SizeF sizeF = new SizeF(diameter, diameter);
RectangleF arc = new RectangleF(rectangle.Location, sizeF);
path.AddArc(arc, 180, 90);
arc.X = rectangle.Right - diameter;
path.AddArc(arc, 270, 90);
arc.Y = rectangle.Bottom - diameter;
path.AddArc(arc, 0, 90);
arc.X = rectangle.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
return path;
}
Main code parts are from Arun Reginald Zaheeruddin
Solved it according to this answer by #Reza Aghaei.
Solution
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public class RoundLabel : Label
{
[Browsable(true)]
public Color _BackColor { get; set; }
public RoundLabel()
{
this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (var graphicsPath = _getRoundRectangle(this.ClientRectangle))
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var brush = new SolidBrush(_BackColor))
e.Graphics.FillPath(brush, graphicsPath);
using (var pen = new Pen(_BackColor, 1.0f))
e.Graphics.DrawPath(pen, graphicsPath);
TextRenderer.DrawText(e.Graphics, Text, this.Font, this.ClientRectangle, this.ForeColor);
}
}
private GraphicsPath _getRoundRectangle(Rectangle rectangle)
{
int cornerRadius = 15; // change this value according to your needs
int diminisher = 1;
GraphicsPath path = new GraphicsPath();
path.AddArc(rectangle.X, rectangle.Y, cornerRadius, cornerRadius, 180, 90);
path.AddArc(rectangle.X + rectangle.Width - cornerRadius - diminisher, rectangle.Y, cornerRadius, cornerRadius, 270, 90);
path.AddArc(rectangle.X + rectangle.Width - cornerRadius - diminisher, rectangle.Y + rectangle.Height - cornerRadius - diminisher, cornerRadius, cornerRadius, 0, 90);
path.AddArc(rectangle.X, rectangle.Y + rectangle.Height - cornerRadius - diminisher, cornerRadius, cornerRadius, 90, 90);
path.CloseAllFigures();
return path;
}
}
I have a custom rounded textbox. But I couldn't add the textbox behaviors like text editing, text selection etc. Those properties take much time if I decide make myself. How can I add this properties into my textbox?
My TextBox class:
public class AltoTextBox : Control
{
public AltoTextBox()
{
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.SupportsTransparentBackColor |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
RoundedRectangleF strokeRect = new RoundedRectangleF(Width, Height, 10);
RoundedRectangleF innerRect = new RoundedRectangleF(Width - 0.5f, Height - 0.5f, 10f, 0.5f, 0.5f);
e.Graphics.DrawPath(Pens.Black, strokeRect.Path);
e.Graphics.FillPath(Brushes.White, innerRect.Path);
}
}
public class RoundedRectangleF
{
Point location;
float radius;
GraphicsPath grPath;
float x, y;
float width, height;
public RoundedRectangleF(float width, float height, float radius,float x = 0,float y = 0)
{
location = new Point(0, 0);
this.radius = radius;
RectangleF upperLeftRect = new RectangleF(x, y, 2 * radius, 2 * radius);
RectangleF upperRightRect = new RectangleF(width - 2 * radius - 1, x, 2 * radius, 2 * radius);
RectangleF lowerLeftRect = new RectangleF(x, height - 2 * radius - 1, 2 * radius, 2 * radius);
RectangleF lowerRightRect = new RectangleF(width - 2 * radius - 1, height - 2 * radius - 1, 2 * radius, 2 * radius);
grPath = new GraphicsPath();
grPath.AddArc(upperLeftRect, 180, 90);
grPath.AddArc(upperRightRect, 270, 90);
grPath.AddArc(lowerRightRect, 0, 90);
grPath.AddArc(lowerLeftRect, 90, 90);
grPath.CloseAllFigures();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public RoundedRectangleF()
{
}
public GraphicsPath Path
{
get
{
return grPath;
}
}
public RectangleF Rect
{
get
{
return new RectangleF(x, y, width, height);
}
}
public float Radius
{
get
{
return radius;
}
set
{
radius = value;
}
}
}
I have found a solution from Hazeldev's custom controls.
In this solution we add a textbox control as our child control.
public class AltoTextBox : Control
{
int radius = 15;
public TextBox box = new TextBox();
GraphicsPath Shape;
public AltoTextBox()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
AddTextBox();
Controls.Add(box);
BackColor = Color.Transparent;
ForeColor = Color.DimGray;
Text = null;
Font = new Font("Comic Sans MS", 11);
Size = new Size(135, 33);
DoubleBuffered = true;
}
void AddTextBox()
{
box.Size = new Size(Width - 2*radius, Height - 6);
box.Location = new Point(radius, 3);
box.BorderStyle = BorderStyle.None;
box.TextAlign = HorizontalAlignment.Left;
box.Multiline = true;
box.Font = Font;
}
protected override void OnBackColorChanged(EventArgs e)
{
base.OnBackColorChanged(e);
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
box.Text = Text;
}
GraphicsPath innerRect;
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
box.Font = Font;
}
protected override void OnResize(System.EventArgs e)
{
base.OnResize(e);
Shape = new RoundedRectangleF(Width, Height, radius).Path;
innerRect = new RoundedRectangleF(Width - 0.5f, Height - 0.5f, radius, 0.5f, 0.5f).Path;
AddTextBox();
}
protected override void OnPaint(PaintEventArgs e)
{
Bitmap bmp = new Bitmap(Width, Height);
Graphics grp = Graphics.FromImage(bmp);
grp.SmoothingMode = SmoothingMode.HighQuality;
grp.DrawPath(Pens.Gray, Shape);
grp.FillPath(Brushes.White, innerRect);
e.Graphics.DrawImage((Image)bmp.Clone(), 0, 0);
base.OnPaint(e);
}
}
Hey everyone im trying to figure out how to make a 3D pyramid out of existing code that is already a 3D cube in visual studio by changing some of the code. I've been messing around with the verts as my friend suggested but I am still unsuccessful. Here is the code..
// ================================================
// | Downloaded From |
// | Visual C# Kicks - http://www.vcskicks.com/ |
// ================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace EulerRotation
{
public partial class Form1 : Form
{
Cube cube;
public Form1()
{
InitializeComponent();
}
private void btnReset_Click(object sender, EventArgs e)
{
tX.Value = 0;
tY.Value = 0;
tZ.Value = 0;
render();
}
private void Form1_Load(object sender, EventArgs e)
{
cube = new Cube(100);
render();
}
private void render()
{
//Set the rotation values
cube.RotateX = tX.Value;
cube.RotateY = tY.Value;
cube.RotateZ = tZ.Value;
//Cube is positioned based on center
Point origin = new Point(picCube.Width / 2, picCube.Height / 2);
picCube.Image = cube.drawCube(origin);
}
private void tX_Scroll(object sender, EventArgs e)
{
render();
}
private void tY_Scroll(object sender, EventArgs e)
{
render();
}
private void tZ_Scroll(object sender, EventArgs e)
{
render();
}
}
internal class Math3D
{
public class Point3D
{
//The Point3D class is rather simple, just keeps track of X Y and Z values,
//and being a class it can be adjusted to be comparable
public double X;
public double Y;
public double Z;
public Point3D(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
public Point3D(float x, float y, float z)
{
X = (double)x;
Y = (double)y;
Z = (double)z;
}
public Point3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public Point3D()
{
}
public override string ToString()
{
return "(" + X.ToString() + ", " + Y.ToString() + ", " + Z.ToString() + ")";
}
}
public class Camera
{
//For 3D drawing we need a point of perspective, thus the Camera
public Point3D Position = new Point3D();
}
public static Point3D RotateX(Point3D point3D, double degrees)
{
//Here we use Euler's matrix formula for rotating a 3D point x degrees around the x-axis
//[ a b c ] [ x ] [ x*a + y*b + z*c ]
//[ d e f ] [ y ] = [ x*d + y*e + z*f ]
//[ g h i ] [ z ] [ x*g + y*h + z*i ]
//[ 1 0 0 ]
//[ 0 cos(x) sin(x)]
//[ 0 -sin(x) cos(x)]
double cDegrees = (Math.PI * degrees) / 180.0f; //Convert degrees to radian for .Net Cos/Sin functions
double cosDegrees = Math.Cos(cDegrees);
double sinDegrees = Math.Sin(cDegrees);
double y = (point3D.Y * cosDegrees) + (point3D.Z * sinDegrees);
double z = (point3D.Y * -sinDegrees) + (point3D.Z * cosDegrees);
return new Point3D(point3D.X, y, z);
}
public static Point3D RotateY(Point3D point3D, double degrees)
{
//Y-axis
//[ cos(x) 0 sin(x)]
//[ 0 1 0 ]
//[-sin(x) 0 cos(x)]
double cDegrees = (Math.PI * degrees) / 180.0; //Radians
double cosDegrees = Math.Cos(cDegrees);
double sinDegrees = Math.Sin(cDegrees);
double x = (point3D.X * cosDegrees) + (point3D.Z * sinDegrees);
double z = (point3D.X * -sinDegrees) + (point3D.Z * cosDegrees);
return new Point3D(x, point3D.Y, z);
}
public static Point3D RotateZ(Point3D point3D, double degrees)
{
//Z-axis
//[ cos(x) sin(x) 0]
//[ -sin(x) cos(x) 0]
//[ 0 0 1]
double cDegrees = (Math.PI * degrees) / 180.0; //Radians
double cosDegrees = Math.Cos(cDegrees);
double sinDegrees = Math.Sin(cDegrees);
double x = (point3D.X * cosDegrees) + (point3D.Y * sinDegrees);
double y = (point3D.X * -sinDegrees) + (point3D.Y * cosDegrees);
return new Point3D(x, y, point3D.Z);
}
public static Point3D Translate(Point3D points3D, Point3D oldOrigin, Point3D newOrigin)
{
//Moves a 3D point based on a moved reference point
Point3D difference = new Point3D(newOrigin.X - oldOrigin.X, newOrigin.Y - oldOrigin.Y, newOrigin.Z - oldOrigin.Z);
points3D.X += difference.X;
points3D.Y += difference.Y;
points3D.Z += difference.Z;
return points3D;
}
//These are to make the above functions workable with arrays of 3D points
public static Point3D[] RotateX(Point3D[] points3D, double degrees)
{
for (int i = 0; i < points3D.Length; i++)
{
points3D[i] = RotateX(points3D[i], degrees);
}
return points3D;
}
public static Point3D[] RotateY(Point3D[] points3D, double degrees)
{
for (int i = 0; i < points3D.Length; i++)
{
points3D[i] = RotateY(points3D[i], degrees);
}
return points3D;
}
public static Point3D[] RotateZ(Point3D[] points3D, double degrees)
{
for (int i = 0; i < points3D.Length; i++)
{
points3D[i] = RotateZ(points3D[i], degrees);
}
return points3D;
}
public static Point3D[] Translate(Point3D[] points3D, Point3D oldOrigin, Point3D newOrigin)
{
for (int i = 0; i < points3D.Length; i++)
{
points3D[i] = Translate(points3D[i], oldOrigin, newOrigin);
}
return points3D;
}
}
internal class Cube
{
//Example cube class to demonstrate the use of 3D points and 3D rotation
public int width = 0;
public int height = 0;
public int depth = 0;
double xRotation = 0.0;
double yRotation = 0.0;
double zRotation = 0.0;
Math3D.Camera camera1 = new Math3D.Camera();
Math3D.Point3D cubeOrigin;
public double RotateX
{
get { return xRotation; }
set { xRotation = value; }
}
public double RotateY
{
get { return yRotation; }
set { yRotation = value; }
}
public double RotateZ
{
get { return zRotation; }
set { zRotation = value; }
}
public Cube(int side)
{
width = side;
height = side;
depth = side;
cubeOrigin = new Math3D.Point3D(width / 2, height / 2, depth / 2);
}
public Cube(int side, Math3D.Point3D origin)
{
width = side;
height = side;
depth = side;
cubeOrigin = origin;
}
public Cube(int Width, int Height, int Depth)
{
width = Width;
height = Height;
depth = Depth;
cubeOrigin = new Math3D.Point3D(width / 2, height / 2, depth / 2);
}
public Cube(int Width, int Height, int Depth, Math3D.Point3D origin)
{
width = Width;
height = Height;
depth = Depth;
cubeOrigin = origin;
}
//Finds the othermost points. Used so when the cube is drawn on a bitmap,
//the bitmap will be the correct size
public static Rectangle getBounds(PointF[] points)
{
double left = points[0].X;
double right = points[0].X;
double top = points[0].Y;
double bottom = points[0].Y;
for (int i = 1; i < points.Length; i++)
{
if (points[i].X < left)
left = points[i].X;
if (points[i].X > right)
right = points[i].X;
if (points[i].Y < top)
top = points[i].Y;
if (points[i].Y > bottom)
bottom = points[i].Y;
}
return new Rectangle(0, 0, (int)Math.Round(right - left), (int)Math.Round(bottom - top));
}
public Bitmap drawCube(Point drawOrigin)
{
//FRONT FACE
//Top Left - 7
//Top Right - 4
//Bottom Left - 6
//Bottom Right - 5
//Vars
PointF[] point3D = new PointF[24]; //Will be actual 2D drawing points
Point tmpOrigin = new Point(0, 0);
Math3D.Point3D point0 = new Math3D.Point3D(0, 0, 0); //Used for reference
//Zoom factor is set with the monitor width to keep the cube from being distorted
double zoom = (double)Screen.PrimaryScreen.Bounds.Width / 1.5;
//Set up the cube
Math3D.Point3D[] cubePoints = fillCubeVertices(width, height, depth);
//Calculate the camera Z position to stay constant despite rotation
Math3D.Point3D anchorPoint = (Math3D.Point3D)cubePoints[4]; //anchor point
double cameraZ = -(((anchorPoint.X - cubeOrigin.X) * zoom) / cubeOrigin.X) + anchorPoint.Z;
camera1.Position = new Math3D.Point3D(cubeOrigin.X, cubeOrigin.Y, cameraZ);
//Apply Rotations, moving the cube to a corner then back to middle
cubePoints = Math3D.Translate(cubePoints, cubeOrigin, point0);
cubePoints = Math3D.RotateX(cubePoints, xRotation); //The order of these
cubePoints = Math3D.RotateY(cubePoints, yRotation); //rotations is the source
cubePoints = Math3D.RotateZ(cubePoints, zRotation); //of Gimbal Lock
cubePoints = Math3D.Translate(cubePoints, point0, cubeOrigin);
//Convert 3D Points to 2D
Math3D.Point3D vec;
for (int i = 0; i < point3D.Length; i++)
{
vec = cubePoints[i];
if (vec.Z - camera1.Position.Z >= 0)
{
point3D[i].X = (int)((double)-(vec.X - camera1.Position.X) / (-0.1f) * zoom) + drawOrigin.X;
point3D[i].Y = (int)((double)(vec.Y - camera1.Position.Y) / (-0.1f) * zoom) + drawOrigin.Y;
}
else
{
tmpOrigin.X = (int)((double)(cubeOrigin.X - camera1.Position.X) / (double)(cubeOrigin.Z - camera1.Position.Z) * zoom) + drawOrigin.X;
tmpOrigin.Y = (int)((double)-(cubeOrigin.Y - camera1.Position.Y) / (double)(cubeOrigin.Z - camera1.Position.Z) * zoom) + drawOrigin.Y;
point3D[i].X = (float)((vec.X - camera1.Position.X) / (vec.Z - camera1.Position.Z) * zoom + drawOrigin.X);
point3D[i].Y = (float)(-(vec.Y - camera1.Position.Y) / (vec.Z - camera1.Position.Z) * zoom + drawOrigin.Y);
point3D[i].X = (int)point3D[i].X;
point3D[i].Y = (int)point3D[i].Y;
}
}
//Now to plot out the points
Rectangle bounds = getBounds(point3D);
bounds.Width += drawOrigin.X;
bounds.Height += drawOrigin.Y;
Bitmap tmpBmp = new Bitmap(bounds.Width, bounds.Height);
Graphics g = Graphics.FromImage(tmpBmp);
//Back Face
g.DrawLine(Pens.Black, point3D[0], point3D[1]);
g.DrawLine(Pens.Black, point3D[1], point3D[2]);
g.DrawLine(Pens.Black, point3D[2], point3D[3]);
g.DrawLine(Pens.Black, point3D[3], point3D[0]);
//Front Face
g.DrawLine(Pens.Black, point3D[4], point3D[5]);
g.DrawLine(Pens.Black, point3D[5], point3D[6]);
g.DrawLine(Pens.Black, point3D[6], point3D[7]);
g.DrawLine(Pens.Black, point3D[7], point3D[4]);
//Right Face
g.DrawLine(Pens.Black, point3D[8], point3D[9]);
g.DrawLine(Pens.Black, point3D[9], point3D[10]);
g.DrawLine(Pens.Black, point3D[10], point3D[11]);
g.DrawLine(Pens.Black, point3D[11], point3D[8]);
//Left Face
g.DrawLine(Pens.Black, point3D[12], point3D[13]);
g.DrawLine(Pens.Black, point3D[13], point3D[14]);
g.DrawLine(Pens.Black, point3D[14], point3D[15]);
g.DrawLine(Pens.Black, point3D[15], point3D[12]);
//Bottom Face
g.DrawLine(Pens.Black, point3D[16], point3D[17]);
g.DrawLine(Pens.Black, point3D[17], point3D[18]);
g.DrawLine(Pens.Black, point3D[18], point3D[19]);
g.DrawLine(Pens.Black, point3D[19], point3D[16]);
//Top Face
g.DrawLine(Pens.Black, point3D[20], point3D[21]);
g.DrawLine(Pens.Black, point3D[21], point3D[22]);
g.DrawLine(Pens.Black, point3D[22], point3D[23]);
g.DrawLine(Pens.Black, point3D[23], point3D[20]);
g.Dispose(); //Clean-up
return tmpBmp;
}
public static Math3D.Point3D[] fillCubeVertices(int width, int height, int depth)
{
Math3D.Point3D[] verts = new Math3D.Point3D[24];
//front face
verts[0] = new Math3D.Point3D(0, 0, 0);
verts[1] = new Math3D.Point3D(0, height, 0);
verts[2] = new Math3D.Point3D(width, height, 0);
verts[3] = new Math3D.Point3D(width, 0, 0);
//back face
verts[4] = new Math3D.Point3D(0, 0, depth);
verts[5] = new Math3D.Point3D(0, height, depth);
verts[6] = new Math3D.Point3D(width, height, depth);
verts[7] = new Math3D.Point3D(width, 0, depth);
//left face
verts[8] = new Math3D.Point3D(0, 0, 0);
verts[9] = new Math3D.Point3D(0, 0, depth);
verts[10] = new Math3D.Point3D(0, height, depth);
verts[11] = new Math3D.Point3D(0, height, 0);
//right face
verts[12] = new Math3D.Point3D(width, 0, 0);
verts[13] = new Math3D.Point3D(width, 0, depth);
verts[14] = new Math3D.Point3D(width, height, depth);
verts[15] = new Math3D.Point3D(width, height, 0);
//top face
verts[16] = new Math3D.Point3D(0, height, 0);
verts[17] = new Math3D.Point3D(0, height, depth);
verts[18] = new Math3D.Point3D(width, height, depth);
verts[19] = new Math3D.Point3D(width, height, 0);
//bottom face
verts[20] = new Math3D.Point3D(0, 0, 0);
verts[21] = new Math3D.Point3D(0, 0, depth);
verts[22] = new Math3D.Point3D(width, 0, depth);
verts[23] = new Math3D.Point3D(width, 0, 0);
return verts;
}
}
}
Right now when I run this code in visual studio 2015 it creates a 3D cube but how do i modify it to where I can get a pyramid?
I like the ToolStripProfessionalRenderer style quite a lot, but I do not like the way it renders a ToolStripTextBox. Here, ToolStripSystemRenderer does a better job IMO. Now is there a way to combine both renderers' behaviour to use system style for text boxes and pro style for everything else? I have successfully managed to use pro style for buttons and system style for the rest (by deriving both classes). But text boxes in a ToolStrip don't seem to be handled by the renderer. Using .NET Reflector, those text boxes don't even seem to have a Paint event handler, although it's called by the ToolStrip.OnPaint method. I'm wondering where's the code to paint such a text box at all and how it can be configured to draw a text box like all other text boxes.
If you just want system rendering, the easiest approach is to use ToolStripControlHost instead:
class ToolStripSystemTextBox : ToolStripControlHost
{
public ToolStripSystemTextBox : base(new TextBox()) { }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[TypeConverter(typeof(ExpandableObjectConverter))]
public TextBox TextBox { get { return Control as TextBox; } }
}
I've taken the easy way out here and exposed the underlying TextBox directly to the form designer, instead of delegating all its properties. Obviously you can write all the property delgation code if you want.
On the other hand, if anyone wants to do truly custom rendering, I'll tell you what ToolStripTextBox does. Instead of hosting a TextBox directly, it hosts a private derived class called ToolStripTextBoxControl. This class overrides its WndProc in order to directly handle WM_NCPAINT. And then instead of delegating the actual drawing to the Renderer, it checks the Renderer's Type, and then branches to different rendering code inside of ToolStripTextBoxControl. It's pretty ugly.
It may not be necessary to dive into "WndProc" either. This was done without it:
The Question really is how do you make a "nice looking" TextBox, because as described by j__m, you can just use ToolStripControlHost, to host a custom control in your tool strip.
More here:
http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripcontrolhost.aspx
And as documented, the control you use can be a Custom Control.
Firstly, It's insanely tricky to make a custom TextBox Control. If you want to go:
public partial class TextBoxOwnerDraw : TextBox
You are in for HUGE trouble! But it doesn't have to be. Here is a little trick:
If you make a custom control as a Panel, then add the TextBox to the Panel, then set the Textbox borders to None... you can achieve the result as above, and best of all, its just a regular old TextBox, so cut copy paste all works, right click works!
Ok, here is the code for a nice looking textbox:
public partial class TextBoxOwnerDraw : Panel
{
private TextBox MyTextBox;
private int cornerRadius = 1;
private Color borderColor = Color.Black;
private int borderSize = 1;
private Size preferredSize = new Size(120, 25); // Use 25 for height, so it sits in the middle
/// <summary>
/// Access the textbox
/// </summary>
public TextBox TextBox
{
get { return MyTextBox; }
}
public int CornerRadius
{
get { return cornerRadius; }
set
{
cornerRadius = value;
RestyleTextBox();
this.Invalidate();
}
}
public Color BorderColor
{
get { return borderColor; }
set
{
borderColor = value;
RestyleTextBox();
this.Invalidate();
}
}
public int BorderSize
{
get { return borderSize; }
set
{
borderSize = value;
RestyleTextBox();
this.Invalidate();
}
}
public Size PrefSize
{
get { return preferredSize; }
set
{
preferredSize = value;
RestyleTextBox();
this.Invalidate();
}
}
public TextBoxOwnerDraw()
{
MyTextBox = new TextBox();
this.Controls.Add(MyTextBox);
RestyleTextBox();
}
private void RestyleTextBox()
{
double TopPos = Math.Floor(((double)this.preferredSize.Height / 2) - ((double)MyTextBox.Height / 2));
MyTextBox.BackColor = Color.White;
MyTextBox.BorderStyle = BorderStyle.None;
MyTextBox.Multiline = false;
MyTextBox.Top = (int)TopPos;
MyTextBox.Left = this.BorderSize;
MyTextBox.Width = preferredSize.Width - (this.BorderSize * 2);
this.Height = MyTextBox.Height + (this.BorderSize * 2); // Will be ignored, but if you use elsewhere
this.Width = preferredSize.Width;
}
protected override void OnPaint(PaintEventArgs e)
{
if (cornerRadius > 0 && borderSize > 0)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle cRect = this.ClientRectangle;
Rectangle safeRect = new Rectangle(cRect.X, cRect.Y, cRect.Width - this.BorderSize, cRect.Height - this.BorderSize);
// Background color
using (Brush bgBrush = new SolidBrush(MyTextBox.BackColor))
{
DrawRoundRect(g, bgBrush, safeRect, (float)this.CornerRadius);
}
// Border
using (Pen borderPen = new Pen(this.BorderColor, (float)this.BorderSize))
{
DrawRoundRect(g, borderPen, safeRect, (float)this.CornerRadius);
}
}
base.OnPaint(e);
}
#region Private Methods
private GraphicsPath getRoundRect(int x, int y, int width, int height, float radius)
{
GraphicsPath gp = new GraphicsPath();
gp.AddLine(x + radius, y, x + width - (radius * 2), y); // Line
gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90); // Corner (Top Right)
gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2)); // Line
gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90); // Corner (Bottom Right)
gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height); // Line
gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90); // Corner (Bottom Left)
gp.AddLine(x, y + height - (radius * 2), x, y + radius); // Line
gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner (Top Left)
gp.CloseFigure();
return gp;
}
private void DrawRoundRect(Graphics g, Pen p, Rectangle rect, float radius)
{
GraphicsPath gp = getRoundRect(rect.X, rect.Y, rect.Width, rect.Height, radius);
g.DrawPath(p, gp);
gp.Dispose();
}
private void DrawRoundRect(Graphics g, Pen p, int x, int y, int width, int height, float radius)
{
GraphicsPath gp = getRoundRect(x, y, width, height, radius);
g.DrawPath(p, gp);
gp.Dispose();
}
private void DrawRoundRect(Graphics g, Brush b, int x, int y, int width, int height, float radius)
{
GraphicsPath gp = getRoundRect(x, y, width, height, radius);
g.FillPath(b, gp);
gp.Dispose();
}
private void DrawRoundRect(Graphics g, Brush b, Rectangle rect, float radius)
{
GraphicsPath gp = getRoundRect(rect.X, rect.Y, rect.Width, rect.Height, radius);
g.FillPath(b, gp);
gp.Dispose();
}
#endregion
}
Now for the ToolStripControlHost
public partial class ToolStripTextBoxOwnerDraw : ToolStripControlHost
{
private TextBoxOwnerDraw InnerTextBox
{
get { return Control as TextBoxOwnerDraw; }
}
public ToolStripTextBoxOwnerDraw() : base(new TextBoxOwnerDraw()) { }
public TextBox ToolStripTextBox
{
get { return InnerTextBox.TextBox; }
}
public int CornerRadius
{
get { return InnerTextBox.CornerRadius; }
set
{
InnerTextBox.CornerRadius = value;
InnerTextBox.Invalidate();
}
}
public Color BorderColor
{
get { return InnerTextBox.BorderColor; }
set
{
InnerTextBox.BorderColor = value;
InnerTextBox.Invalidate();
}
}
public int BorderSize
{
get { return InnerTextBox.BorderSize; }
set
{
InnerTextBox.BorderSize = value;
InnerTextBox.Invalidate();
}
}
public override Size GetPreferredSize(Size constrainingSize)
{
return InnerTextBox.PrefSize;
}
}
Then When you want to use it, just add it to the tool bar:
ToolStripTextBoxOwnerDraw tBox = new ToolStripTextBoxOwnerDraw();
this.toolStripMain.Items.Add(tBox);
or however you want to add it. If you are in Visual Studio, the preview window supports rendering this Control.
There is only one thing to remember, when accessing the TextBox with the actual text in it, its:
tBox.ToolStripTextBox.Text;