The task is a simple concept, just not sure about a simple method to do what I'm asking.
Goal
Have a textbox, label, custom User Control, or some other type of control show multiline text and fade it out half way down (as seen in image below). I would like to have it be transparent (as seen in the image) and be editable of course. I was thinking of something like a custom UserControl : label or something similar. Maybe override the label's OnPaint and draw the form contents (everything behind the control) to emulate transparency. Then draw the text but somehow maybe apply some type of gradient filter to it? I honestly have no clue how I would do it but hoping someone else does.
Thanks!
I worked out a solution and it looks perfect, I'll need to spend more time on it later adding support for text align etc. But for now I ended up coming up with this...
Note: Create a new User Control and add this in the code area. Also
keep in mind to make sure the designer of that new control uses the
same namespace "InfinityLabel". And one last thing, don't forget to set your
new label (InfinityLabel) to BackColor=Transparent.
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace InfinityLabel
{
public partial class InfinityLabel : Label
{
public InfinityLabel()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle rect = new Rectangle(0, 0, Width, Height);
LinearGradientBrush brush =
new LinearGradientBrush(
rect,
Color.FromArgb(255, ForeColor),
Color.FromArgb(60, ForeColor),
90f);
e.Graphics.DrawString(Text, Font, brush, rect);
}
}
}
Related
I'm attempting to draw a think underline underneith my header about 10-15 px thick. I've tried adding a picture box and then drawing to that, but it's not being drawn to the screen. Is there a better way to do this, or a way to make my method work?
Thanks!
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
Pen selPen = new Pen(Color.Black);
g.DrawRectangle(selPen, 0, 0, 700, 15);
g.Dispose();
}
}
}
The reason your code doesn't work is because you cannon draw in from 1 load event. Place your code into another event or in a button and it will work fine.
Don't use CreateGraphics() as it is a temporary surface that gets erased when the form refreshes.
Instead, handle the Paint() event of your Form/Control and use the supplied e.Graphics to draw with.
A common trick for having thick lines in WinForms is to create a Label with BorderStyle set to FixedSingle (you can experiment with other borders) and Height = 1 (Width as appropriate). You can draw all this in the designer, or try to use some other "degenerate" controls - Panel with appropriate visual settings.
Other options are of course using a custrom UserControl or handling/overriding the OnPaint event and drawing on the graphics provided by the Control.CreateGraphics method (no need to put PictureBox on the form).
In .NET 3.5 with winforms I'm making an image thumbnail viewer control.
The main control is derived from a FlowLayoutPanel which takes a list of images and displays them. The images which are displayed are made from a CustomControl on which I paint the and the accompanying label as well as the border of the control.
Images can be selected through clicking and yada yada as you would expect for that kind of control.
Here's a screenshote to illustrate:
That part works fine. The problem is then when I scroll the FlowLayoutPanel derived control the border doesn't redraw properly and there are lines remaining as shown in this screenshot:
I have set both the FlowLayoutPanel and the Images to double buffered. And the images and labels do not have the problem, so I suspect it is something else, but can't figure out what it is.
I think the method used to paint the border of the images might be at fault. Here's the code I use:
protected override void OnPaint(PaintEventArgs e)
{
Rectangle captionContainer;
captionContainer = new Rectangle();
if (!string.IsNullOrEmpty(this.Caption))
captionContainer = this.DrawCaption(e.Graphics);
if (this.Image != null)
this.DrawImage(e.Graphics, captionContainer);
this.Size = new Size(this.Padding.Horizontal + this.ImageSize.Width, this.Padding.Vertical + this.ImageSize.Height + captionContainer.Height);
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, this.currentBorderColor, ButtonBorderStyle.Solid);
base.OnPaint(e);
}
I'll post more code if needed, but it is pretty lengthy, so I do not want to put too much code unless it actually is necessary.
Can anybody see where this is going wrong?
I have solved by also drawing the border using the Graphics object. Replacing
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, this.currentBorderColor, ButtonBorderStyle.Solid);
with
e.Graphics.DrawRectangle(new Pen(this.currentBorderColor, 1F), new Rectangle(Point.Empty, new Size(this.Width - 1, this.Height - 1)));
does the trick. No idea why one works and not the other though...
I have a panel control that I want to fill up with gradient. I have the following code:
Brush brush = new LinearGradientBrush(pnlBody.ClientRectangle, Color.Black, Color.White, LinearGradientMode.ForwardDiagonal);
pnlBody.CreateGraphics().FillRectangle(brush, pnlBody.ClientRectangle);
But it has no effect. If I replace pnlBody with form, then it colors the form fine, but not panel. Any ideas what I'm doing wrong? Thanks!
A Panel control will paint itself with its Paint event. Which wipes out anything you paint by using CreateGraphics(). You'll need to use its Paint event instead. This will however produce flicker, you'll see it paint its background first. Panel is also optimized to act as a container control with low impact paint overhead, you'll see it not repaint itself when it is resized. An issue when you anchor it to the right or bottom and resize the form.
To fix these issues, you should derive your own class from Panel. Add a new class to your project and paste this code:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public class GradientPanel : Panel {
public GradientPanel() {
this.ResizeRedraw = true;
}
protected override void OnPaintBackground(PaintEventArgs e) {
using (var brush = new LinearGradientBrush(this.ClientRectangle,
Color.Black, Color.White, LinearGradientMode.ForwardDiagonal)) {
e.Graphics.FillRectangle(brush, this.ClientRectangle);
}
}
protected override void OnScroll(ScrollEventArgs se) {
this.Invalidate();
base.OnScroll(se);
}
}
Build + Build. Drop the new control from the top of the toolbox onto your form, replacing the original panel. You can get creative by adding properties that select the gradient start and end colors, producing a more generally useful control that can be reused in other projects. Do avoid the panel showing a scrollbar, you cannot make the scrolling look decent because of the Windows "Show window content while dragging" feature. The effect is somewhat similar to the pogo.
I am trying to integrate Winforms with a SharpDX project, in order to use Winforms (and eventually WPF via HostElement) in my 3D app.
I need to create or configure a Control or Form such that I can:
a. Render it to a texture (that I can display as a sprite*)
b. Filter its input to remove mouse/keyboard events when the control is not active.
I have tried subclassing Control and Form, to override the OnPaint and OnPaintBackground but these have no effect on the child controls - or for that matter the forms borders (and even if they did they are not sufficient on their own as I am still left with a white square where I presume the 'parent' has been drawn).
How can I stop a Control or Form painting to the screen and instead draw only to a bitmap? (Is there some way I can override Graphics before the tree is painted, for example?)
*It needs to be done this way (as opposed to letting the control render to the screen) as Winforms doesn't support true transparency, so I need to clip colour coded pixels in my pixel shader.
(To confirm, I don't mean a DirectX texture specifically - I am happy with (in fact would prefer) a simple System.Drawing Bitmap)
Here is one way to start going about it:
Create a derived control class so that we can expose InvokePaint which is protected
Call our custom method to get the Control's image
Test form needs a picture box and an instance of Mybutton
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1() { InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e)
{
// create image to which we will draw
var img = new Bitmap(100, 100);
// get a Graphics object via which we will draw to the image
var g = Graphics.FromImage(img);
// create event args with the graphics object
var pea = new PaintEventArgs(g, new Rectangle(new Point(0,0), new Size(100,100)));
// call DoPaint method of our inherited object
btnTarget.DoPaint(pea);
// modify the image with algorithms of your choice...
// display the result in a picture box for testing and proof
pictureBox.BackgroundImage = img;
}
}
public class MyButton : Button
{
// wrapping InvokePaint via a public method
public void DoPaint(PaintEventArgs pea)
{
InvokePaint(this, pea);
}
}
}
is there a way, to make a picture transparent in CF2.0? I have to lay a small Image over a textbox, but it has to be transparent so the User can see the text anyway. Do you have an Idea?
Thank you very much
twickl
Edit:
Thanks for your answers, I will check those links out!
To complete my Post, here is what I´m trying to do:
I want to show a small image (the image does not exist yet and I have to make ist, so I´m totaly open for all formats) that is an X on the right end of a textbox. By clicking that X the Text inside the textbox will be erased...like on the iPhone. But I can not build my own control becuse in my Project are so many TextBoxes that are allready custom Controls with the windows TextBox on it, that it will be to much work and testing to switch all of them to custom controls. So I have the Idea to make a small Panel, Picturebox, whatever, that lays above the Textbox. But it has to be transparent. The OS is Windows CE 5.0 with CF 2.0 on it.
Depending on what kind of transparency you need, you might choose any of these options:
1.) If you have an image with a specific portion that should be entirely transparent, you can use ImageAttributes.SetColorKey() to set a single transparent color and then pass this to Graphics.DrawImage. Your image will need to have one color (e.g. Color.Cyan) that will be drawn completely transparent.
2.) If you'd like the entire image to be partially transparent, e.g. for a fade in/fade out effect, you can P/Invoke the AlphaBlend() function, as demonstrated here.
3.) If you have an image with transparency information built in, e.g. a transparent PNG image that needs to be rendered on a variety of background colors, these previous methods will not work and you need to use the COM based IImage interface.
The COM interop from .NETCF is documented on this page (search for "IImage interface" on that page).
Option 3 is the most flexible, but it also involves the most implementation effort. If you follow up with more information about the kind of image you want to draw transparently and your target platform, we might be able to help more.
I did it by deriving a class from PictureBox and handling OnPaint. The key is the ImageAttributes object passed to DrawImage. I'm assuming pixel 0,0 is the transparent color, but you could handle that differently.
public partial class TransparentPictureBox : PictureBox
{
private Color tColor;
public TransparentPictureBox()
{
InitializeComponent();
}
public new Image Image
{
get { return base.Image; }
set
{
if (value == base.Image)
return;
if (value != null)
{
Bitmap bmp = new Bitmap(value);
tColor = bmp.GetPixel(0, 0);
this.Width = value.Width;
this.Height = value.Height;
}
base.Image = value;
}
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(this.BackColor);
if (Image == null)
return;
ImageAttributes attr = new ImageAttributes();
// Set the transparency color.
attr.SetColorKey(tColor, tColor);
Rectangle dstRect = new Rectangle(0, 0, base.Image.Width, base.Image.Height);
e.Graphics.DrawImage(base.Image, dstRect, 0, 0, base.Image.Width, base.Image.Height, GraphicsUnit.Pixel, attr);
}
}