I want to draw a custom TabControl with custom functionality.
To do this, i inherited the Panel class and overrided OnPaint method to draw with TabRenderer class.
The problem is that TabRenderer working only when visual styles enabled (can be checked with TabRenderer.IsSupported), but what should i do if visual styles disabled?
In this case, I thought using the ControlPaint class to draw tabs without visual styles, but it has no draw methods related to Tabs. I want it basically to behave visually like the regular TabControl.
You have to draw it by yourself, because there is not published API for this. Hopefully this is relatively easy to do it in non-visualstyles way.
You can draw pane border with ControlPaint.DrawBorder3D and use something like the following code for buttons:
int Top = bounds.Top;
int Bottom = bounds.Bottom - 1;
int Sign = 1;
if (tabStrip.EffectiveOrientation == TabOrientation.Bottom)
{
Top = bounds.Bottom - 1;
Bottom = bounds.Top;
Sign = -1;
}
using (Pen OuterLightBorderPen = new Pen(SystemColors.ControlLightLight))
{
e.Graphics.DrawLine(OuterLightBorderPen, bounds.Left, Bottom, bounds.Left, Top + 2 * Sign);
e.Graphics.DrawLine(OuterLightBorderPen, bounds.Left, Top + 2 * Sign, bounds.Left + 2, Top);
e.Graphics.DrawLine(OuterLightBorderPen, bounds.Left + 2, Top, bounds.Right - 3, Top);
}
using (Pen InnerLightBorderPen = new Pen(SystemColors.ControlLight))
{
e.Graphics.DrawLine(InnerLightBorderPen, bounds.Left + 1, Bottom, bounds.Left + 1, Top + 2 * Sign);
e.Graphics.DrawLine(InnerLightBorderPen, bounds.Left + 2, Top + 1 * Sign, bounds.Right - 3, Top + 1 * Sign);
}
using (Pen OuterDarkBorderPen = new Pen(SystemColors.ControlDarkDark))
{
e.Graphics.DrawLine(OuterDarkBorderPen, bounds.Right - 2, Top + 1 * Sign, bounds.Right - 1, Top + 2 * Sign);
e.Graphics.DrawLine(OuterDarkBorderPen, bounds.Right - 1, Top + 2 * Sign, bounds.Right - 1, Bottom);
}
using (Pen InnerDarkBorderPen = new Pen(SystemColors.ControlDark))
e.Graphics.DrawLine(InnerDarkBorderPen, bounds.Right - 2, Top + 2 * Sign, bounds.Right - 2, Bottom);
This is an "out there" answer but is it possible that you could use wpf? As you can see from the answer above it is a pain in the ear to customise controls in winforms where as in WPF each control is lookless. This means that you control what is rendered and how it looks completely.
Related
I am trying to create custom digital signatures using iText (sharp, version 5.5.13) where the user is able to set the image location from a set of four positions (top, bottom, left and right), as shown below:
Rigth:
Left:
Top:
Bottom:
So far I tried working on layer 0 of the signature but I think I doing it wrong because signature details are set in layer 2.
Nevertheless, this is just an initial sketch to set position of the images. In the following code I load the image and put it in a chunk (idea taken from this example)
PdfTemplate pdfTemplate = sap.GetLayer(0);
ColumnText c1 = new ColumnText(pdfTemplate);
Image img = Image.GetInstance(signatureImage);
Phrase elements = new Phrase();
elements.Add(new Chunk(img, 0, 0, true));
//c1.SetSimpleColumn(elements, 0, 0, rectangle.Width, rectangle.Height / 4, 0, Element.ALIGN_CENTER); // align bottom
//c1.SetSimpleColumn(elements, 0, rectangle.Height / 2, rectangle.Width, rectangle.Height, 0, Element.ALIGN_CENTER); // align top
c1.SetSimpleColumn(elements, rectangle.Width/2, 0, rectangle.Width, rectangle.Height, 0, Element.ALIGN_CENTER); // align right
//c1.SetSimpleColumn(elements, 0, 0, rectangle.Width/2, rectangle.Height, 0, Element.ALIGN_CENTER); // align left
c1.Go();
The result is more or less the expected, but there are two problems: the signature information takes over the whole rectangle (this is normal since I do not modify layer 2, and the image in layer 0 is not scaled as it should)
If I scale the image to fit the column, it goes to the top of rectangle:
Is there any way to do this "out of the box" or I need to overload the method that builds the signature appearance (like this) and how can I achieve this?
My initial concert was not to use iText (v7) because we do not have much time to migrate all the projects we have with iText (v5), but I went ahead and tried out with v7. But to be honest is does not seem to be very easy to achieve with v5.
On the other hand, in iText (v7) I was able to do this very quickly with this simple method:
private static void SetCustomSignature(PdfDocument doc, PdfSignatureAppearance sap, SignatureFormat signatureFormat, X509Certificate2 signerCertificate) {
string signatureFont = signatureFormat.Font;
float signatureFontSize = float.Parse(signatureFormat.FontSize);
Rectangle rect = new Rectangle(250, 100, 200, 80);
sap.SetPageRect(rect).SetPageNumber(1);
PdfFormXObject layer2 = sap.GetLayer2();
PdfCanvas canvas = new PdfCanvas(layer2, doc);
float MARGIN = 2;
PdfFont font = PdfFontFactory.CreateFont();
string signingText = GetSignatureInfo(signerCertificate, signatureFormat);
// Signature at left and image at right
//Rectangle dataRect = new Rectangle(rect.GetWidth() / 2 + MARGIN / 2, MARGIN, rect.GetWidth() / 2 - MARGIN, rect.GetHeight() - 2 * MARGIN);
//Rectangle signatureRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() / 2 - 2 * MARGIN, rect.GetHeight() - 2 * MARGIN);
// Signature at right and image at left
//Rectangle dataRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() / 2 - MARGIN, rect.GetHeight() - 2 * MARGIN);
//Rectangle signatureRect = new Rectangle(rect.GetWidth() / 2 + MARGIN / 2, MARGIN, rect.GetWidth() / 2 - 2 * MARGIN, rect.GetHeight() - 2 * MARGIN);
// Signature at top and image at bottom
//Rectangle dataRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
//Rectangle signatureRect = new Rectangle(MARGIN, rect.GetHeight() / 2 + MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
// Signature at bottom and image at top
Rectangle dataRect = new Rectangle(MARGIN, rect.GetHeight() / 2 + MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
Rectangle signatureRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - MARGIN);
try {
Canvas signLayoutCanvas = new Canvas(canvas, doc, signatureRect);
Paragraph paragraph = new Paragraph(signingText).SetFont(font).SetMargin(0).SetMultipliedLeading(0.9f).SetFontSize(10);
Div div = new Div();
div.SetHeight(signatureRect.GetHeight());
div.SetWidth(signatureRect.GetWidth());
div.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE);
div.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.CENTER);
div.Add(paragraph);
signLayoutCanvas.Add(div);
Canvas dataLayoutCanvas = new Canvas(canvas, doc, dataRect);
Image image = new Image(ImageDataFactory.Create(signatureFormat.SignatureImage));
image.SetAutoScale(true);
Div dataDiv = new Div();
dataDiv.SetHeight(dataRect.GetHeight());
dataDiv.SetWidth(dataRect.GetWidth());
dataDiv.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE);
dataDiv.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.CENTER);
dataDiv.Add(image);
dataLayoutCanvas.Add(dataDiv);
}
catch {
throw;
}
}
This will result in the following signatures:
Of course, it still needs some improvements but it may serve as an example for others :-)
I am pretty new to this community.
I was wondering how to export Vertex color of Karamba, Ladybug’s analysis (color mapping) from Grasshopper/Rhino 3D in order to create an AR application (with unity, unreal or other)?
I am trying to visualize the analysis, that I baked in Rhino from other grasshopper plug-in like ladybug, karamba, honeybee, butterfly, in unity or unreal. And also, I would like to understand more deeply how the texture, materials and shaders work in Rhino and Unity within the GPU.
Rhino6 Support Export Vertex Color,
You can also use from Ladybug Texture Mixer from Antonello di Nunzio that can do the work, replacing the colour vertex with Texture and Material.
def makeTexture(size, colorTree):
sb = size * 2 - 1
bm = System.Drawing.Bitmap(size * 2, size * 2)
bmb = System.Drawing.Bitmap(size * 4, size * 4)
count = -1
for x in xrange(size):
for y in xrange(size):
count += 1
if count < len(colorTree):
bm.SetPixel((x * 2) + 0, sb - ((y * 2) + 0), colorTree[count][0])
bm.SetPixel((x * 2) + 1, sb - ((y * 2) + 0), colorTree[count][1])
bm.SetPixel((x * 2) + 1, sb - ((y * 2) + 1), colorTree[count][2])
bm.SetPixel((x * 2) + 0, sb - ((y * 2) + 1), colorTree[count][3])
g = System.Drawing.Graphics.FromImage(bmb)
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
g.DrawImage(bm, 0, 0, size * 4 + 1, size * 4 + 1)
return bmb
using System.Drawing;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication1
{
[Serializable]
public class GMapBaloonTool: GMapToolTip, ISerializable
{
public float Radius = 10f;
public GMapBaloonTool(GMapMarker marker)
: base(marker)
{
Stroke = new Pen(Color.FromArgb(140, Color.Navy));
Stroke.Width = 3;
this.Stroke.LineJoin = LineJoin.Round;
this.Stroke.StartCap = LineCap.RoundAnchor;
Fill = Brushes.Pink;
}
the above code, makes the tooltip change its color.
I am using gMaps.net to create custom google map inside winforms C#. I am working unto adding a marker + onClick event that will display video feeds from the DVR.
Only problem is that, the built in GMapsToolTip only displays strings although I have an activeX that act as a control for the camera.
What I need is to display the camera(activeX) inside the tooltip.
Saw this on a forum in greatmaps. Creator said I can make custom tooltips.
so what I am asking is, is it possible to create/add controls using this system.drawing namespace?
if possible, please do tell me how..
if not, if you know any other way, let know it.
public override void OnRender(Graphics g)
{
System.Drawing.Size st = g.MeasureString(Marker.ToolTipText, Font).ToSize();
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(Marker.ToolTipPosition.X, Marker.ToolTipPosition.Y - st.Height, st.Width + TextPadding.Width, st.Height + TextPadding.Height);
rect.Offset(Offset.X, Offset.Y);
using (GraphicsPath objGP = new GraphicsPath())
{
objGP.AddLine(rect.X + 2 * Radius, rect.Y + rect.Height, rect.X + Radius, rect.Y + rect.Height + Radius);
objGP.AddLine(rect.X + Radius, rect.Y + rect.Height + Radius, rect.X + Radius, rect.Y + rect.Height);
objGP.AddArc(rect.X, rect.Y + rect.Height - (Radius * 2), Radius * 2, Radius * 2, 90, 90);
objGP.AddLine(rect.X, rect.Y + rect.Height - (Radius * 2), rect.X, rect.Y + Radius);
objGP.AddArc(rect.X, rect.Y, Radius * 2, Radius * 2, 180, 90);
objGP.AddLine(rect.X + Radius, rect.Y, rect.X + rect.Width - (Radius * 2), rect.Y);
objGP.AddArc(rect.X + rect.Width - (Radius * 2), rect.Y, Radius * 2, Radius * 2, 270, 90);
objGP.AddLine(rect.X + rect.Width, rect.Y + Radius, rect.X + rect.Width, rect.Y + rect.Height - (Radius * 2));
objGP.AddArc(rect.X + rect.Width - (Radius * 2), rect.Y + rect.Height - (Radius * 2), Radius * 2, Radius * 2, 0, 90); // Corner
objGP.CloseFigure();
g.FillPath(Fill, objGP);
g.DrawPath(Stroke, objGP);
}
g.DrawString(Marker.ToolTipText, Font, Foreground, rect, Format);
g.DrawString(ToolTipText, ToolTipFont, TooltipForeground, rect, ToolTipFormat);
}
#region ISerializable Members
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Radius", this.Radius);
base.GetObjectData(info, context);
}
protected GMapBaloonTool(SerializationInfo info, StreamingContext context)
: base(info, context)
{
this.Radius = Extensions.GetStruct<float>(info, "Radius", 10f);
}
#endregion
}
}
this code makes the balloon on a rounded shape, so I don't know how to add my control to look something like this.. (made from html, but I need it on winforms)
hoping for someone who can help me.
and oh, if you will only redirect me back to the discussion site of greatmaps, please don't. I can't understand much from there, so I asked in here.
You can try using the DrawToBitmap method on your camera control. I'd expect one of three things to happen:
You get a black rectangle
You get one frame of the camera at the moment you called DrawToBitmap
You get a live video feed (thanks to overlay video playback features)
Your best options are number 2 and 3, because they can be used to provide the functionality you want. If you get number 1, the control rendering doesn't use the usual render logic of Winforms, so you'll have to work around it.
In practice, you'll probably want a more direct access to the camera rendering output, because creating 25 bitmaps per second might be a little too much work to be useful. You'll get there :)
Already got this to work for myself. Used an instance of a form to create an infowindow
This is the link..
I'm trying to create step indicator control that will show on which step user currently is.
I found on dribble some concept that I would like to create:
using very simple code I was able to create result like this:
below is my code:
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace StepIndicator
{
public class StepIndicatorOne : Control
{
public StepIndicatorOne()
{
MinimumSize = new Size(300, 50);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
int steps = 3;
int radiusBig = 20;
int radiusSmall = 15;
int bgHeight = 10;
var gradientRect = new Rectangle(ClientRectangle.X + (ClientRectangle.Width - radiusBig*2)/(steps - 1),
ClientRectangle.Y + ClientRectangle.Height/2 - radiusBig - 1, radiusBig*2, radiusBig*2);
var lightGrayBrush = new LinearGradientBrush(ClientRectangle, Color.FromArgb(224, 227, 214), Color.LightGray, LinearGradientMode.Vertical);
var darkGrayBrush = new LinearGradientBrush(gradientRect, Color.DarkGray, Color.Gray, LinearGradientMode.Vertical);
var lightGreenBrush = new LinearGradientBrush(ClientRectangle, Color.FromArgb(206, 217, 79), Color.FromArgb(191, 201, 82), LinearGradientMode.Vertical);
var darkGreenBrush = new LinearGradientBrush(ClientRectangle, Color.YellowGreen, Color.ForestGreen, LinearGradientMode.Vertical);
g.FillRectangle(darkGrayBrush, ClientRectangle.X + radiusBig, ClientRectangle.Y + ClientRectangle.Height/2 - bgHeight/2 - 1,
ClientRectangle.Width - radiusBig*2, bgHeight);
g.FillRectangle(lightGrayBrush, ClientRectangle.X + radiusBig, ClientRectangle.Y + ClientRectangle.Height/2 - bgHeight/2,
ClientRectangle.Width - radiusBig*2, bgHeight);
for (int i = 1; i <= steps; i++)
{
g.FillEllipse(darkGrayBrush, ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1),
ClientRectangle.Y + ClientRectangle.Height/2 - radiusBig - 1, radiusBig*2, radiusBig*2);
g.FillEllipse(lightGrayBrush, ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1),
ClientRectangle.Y + ClientRectangle.Height/2 - radiusBig, radiusBig*2, radiusBig*2);
}
for (int i = 1; i <= steps - 1; i++)
{
g.FillEllipse(darkGreenBrush,
ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1) + radiusBig - radiusSmall,
ClientRectangle.Y + ClientRectangle.Height/2 - radiusSmall - 1, radiusSmall*2, radiusSmall*2);
g.FillEllipse(lightGreenBrush,
ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1) + radiusBig - radiusSmall,
ClientRectangle.Y + ClientRectangle.Height/2 - radiusSmall, radiusSmall*2, radiusSmall*2);
}
}
}
}
My questions are:
Is it possible to create green shape as on design (green bar with circles and hole in one) but with border over it?
I can draw rectangle with border and ellipse above it with border, but how can I combine those two shapes and have border around it (combine those two shapes into one) - is my only option creating complex path?
I know that winforms gdi+ can't use inner shadow, but are there some other options to create nice looking effect simillar to inner glow?
Right now I draw same shape with -1 offset and darker color, but effect isn't what I would like it to look.
I know that propably the best solution would be to switch to WPF and draw it there, I even found sample control on SO - Implementing a wizard progress control in WPF but I must stay in Winforms
Use a GraphicsPath for the complex path. Use a path gradient for the inner shadow.
Sometimes when I set a breakpoint and start debugging its color changes from red to olive:
When it happens debugging doesn't stop at all - breakpoint is ignored.
I want to know why this happens and how to avoid it in the future.
Edit:
It does not happens only when breakpoint is set on commented line of code:
It's open source. Downloading it and finding the relevant code took me about 5 minutes:
public void DrawBreakpoint(Graphics g, int y, bool isEnabled, bool isHealthy)
{
int diameter = Math.Min(iconBarWidth - 2, textArea.TextView.FontHeight);
Rectangle rect = new Rectangle(1,
y + (textArea.TextView.FontHeight -
diameter) / 2,
diameter,
diameter);
using (GraphicsPath path = new GraphicsPath()) {
path.AddEllipse(rect);
using (PathGradientBrush pthGrBrush = new PathGradientBrush(path)) {
pthGrBrush.CenterPoint = new PointF(rect.Left + rect.Width / 3 ,
rect.Top + rect.Height / 3);
pthGrBrush.CenterColor = Color.MistyRose;
Color[] colors = {isHealthy ? Color.Firebrick : Color.Olive};
pthGrBrush.SurroundColors = colors;
if (isEnabled) {
g.FillEllipse(pthGrBrush, rect);
} else {
g.FillEllipse(SystemBrushes.Control, rect);
using (Pen pen = new Pen(pthGrBrush)) {
g.DrawEllipse(pen, new Rectangle(rect.X + 1, rect.Y + 1,
rect.Width - 2,
rect.Height - 2));
}
}
}
}
}
That circle color is "Color.Olive". If you want to know why isHealthy is false, use the source. There's a couple of reasons I could find quickly: the source file has changed or the module isn't loaded, There may be more.
This occurs if you compile the programm as "release".
Your line is commented where the breakpoint is set.