So having trying for a while with no luck, i eventually decided to ask about a way to make a transparent controls display each others.
As you see in the picture i have 2 transparent picture boxes, they show the background very well but when it comes to the selected picturebox as you can see in the picture it only renders the background image of the form but not the other picture box below it. I know that there are a common circumstances in winforms due to the lack of proper rendering but the question is :
Is there a way to get around this rendering glitch, is there a way to make the transparent controls render each others ?
Well this is the Answer : Transparent images with C# WinForms
The transparency of a control depends on its parent control .You can however, use a custom container control instead of a picture box for the parent image.and maybe this code is usfull
using System;
using System.Windows.Forms;
using System.Drawing;
public class TransparentControl : Control
{
private readonly Timer refresher;
private Image _image;
public TransparentControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.Transparent;
refresher = new Timer();
refresher.Tick += TimerOnTick;
refresher.Interval = 50;
refresher.Enabled = true;
refresher.Start();
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
RecreateHandle();
}
protected override void OnPaint(PaintEventArgs e)
{
if (_image != null)
{
e.Graphics.DrawImage(_image, (Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2));
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Do not paint background
}
//Hack
public void Redraw()
{
RecreateHandle();
}
private void TimerOnTick(object source, EventArgs e)
{
RecreateHandle();
refresher.Stop();
}
public Image Image
{
get
{
return _image;
}
set
{
_image = value;
RecreateHandle();
}
}
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Im trying to code a simple slideshow program.
I have a class named SlideShowText.
I want it to be scalable by mouse like scaling the control in Visual Studio.
I want it to have dotted borders.
Any help?
(I didn't try anything since im such a noob)
You can make any control sizeable with the mouse, overriding its CreateParams property.
For example
class SizeableRichTextBox : RichTextBox
{
protected override CreateParams CreateParams
{
get
{
const int WS_SIZEBOX = 0x40000;
var cp = base.CreateParams;
cp.Style |= WS_SIZEBOX;
return cp;
}
}
}
class SizeablePictureBox : PictureBox
{
protected override CreateParams CreateParams
{
get
{
const int WS_SIZEBOX = 0x40000;
var cp = base.CreateParams;
cp.Style |= WS_SIZEBOX;
return cp;
}
}
}
Now they have a thick border and can be resized with the mouse.
The image scale in the SizeablePictureBox will change automatically, if you set the ImageLayout.Zoom parameter.
var pictureBox = new SizeablePictureBox { Parent = this, Width = 500, Height = 500 };
pictureBox.BackgroundImageLayout = ImageLayout.Zoom;
pictureBox.BackgroundImage = Image.FromFile("pic.jpg");
To change the text scale in the TextBox you have to manually calculate the aspect ratio and change the font size. Or you can try to change the value of ZoomFactor property.
Here is a Resizer control:
public partial class Resizer : Control
{
public Resizer()
{
InitializeComponent();
Size = new System.Drawing.Size(12, 12);
}
public Control control { get; set; }
Point mDown = Point.Empty;
public Resizer(Control ctl)
{
InitializeComponent();
control = ctl;
Size = new System.Drawing.Size(12, 12);
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (control != null)
{
BackColor = Color.DarkOrange;
Location = new Point(control.Width - Size.Width,
control.Height - Size.Height);
Parent = control;
BringToFront();
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
mDown = e.Location;
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
Hide();
base.OnMouseUp(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button.HasFlag(MouseButtons.Left))
{
Left += -(mDown.X - e.X);
Top += -(mDown.Y - e.Y);
control.Size = new Size(Right, Bottom);
}
base.OnMouseMove(e);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
}
After adding it to the project you can use it maybe like this:
Resizer rz = null;
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
if (rz == null) rz = new Resizer(pictureBox1); else rz.Show();
}
Result:
I've created a transparent control as suggested here
public partial class TransparentControl : UserControl
{
private readonly Timer refresher;
private Image _image;
public TransparentControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.Transparent;
refresher = new Timer();
refresher.Tick += TimerOnTick;
refresher.Interval = 50;
refresher.Enabled = true;
refresher.Start();
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
RecreateHandle();
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(_image, new Rectangle((Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2), _image.Width, _image.Height));
}
protected override void OnPaintBackground(PaintEventArgs e)
{}
public void Redraw()
{
RecreateHandle();
}
private void TimerOnTick(object source, EventArgs e)
{
RecreateHandle();
refresher.Stop();
}
public Image Image
{
get { _image; }
set { _image = value; RecreateHandle(); }
}
}
The problem is that if i overlap two TransparentControl object, the one that stays on top is not being rendered (or maybe it's being rendered but is not visible at all).
Is there something to add to the control to fix this?
Because using PictureBox for the top image works, but on Linux with Mono its not rendering alpha pixels. That's why I need to use this TransparentControl.
Thanks everyone.
I have listview control. I need to add semi-transparent button with image to listview. Something like this:
I found several projects that use semi-transparent buttons on the form. But when I transfer them to the ListView, they do not work.
Necessary to use .net 2.0 framework.
I found some solution.
Making Transparent Controls - No Flickering
I inherit my TransparentToggleButton class from TranspControl class:
public class TransparentToggleButton : TranspControl
{
private Image _normalState;
private Image _mouseUpState;
private Image _activateState;
private bool _state;
private bool _mouseUnder;
public event EventHandler StateChanged;
public bool ToggleState
{
get { return _state; }
set
{
_state = value;
SetImage();
}
}
public void SetImages(Image normalState, Image mouseUpState, Image activateState)
{
BackImage = normalState;
_normalState = normalState;
_mouseUpState = mouseUpState;
_activateState = activateState;
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (e.Button == MouseButtons.Left)
{
_state = !_state;
if (StateChanged != null)
StateChanged(this, e);
SetImage();
}
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
_mouseUnder = true;
SetImage();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
_mouseUnder = false;
SetImage();
}
private void SetImage()
{
try
{
if (_state)
BackImage = _activateState;
else
BackImage = _mouseUnder ? _mouseUpState : _normalState;
}
catch (Exception)
{
}
}
}
Function SetImages loads the 3 images that used for normal state, normal state when cursor over the button, activate state.
Besides need catch listview scroll event and Invalidate() TransparentToggleButton.
I'd like to create a custom context menu. The idea is to create a panel with a textBox a button and a list of labels and be able to show it on right click and make it behave exactly like a contextMenu. I can probably use a form without borders but I was thinking there might be a class I can derive from that would help me handle the positionnig of the context menu and the shading. Any ideas?
Thank you
Edit: An example to clear a few ideas: Say you have a label on your form, when you right click on it (or even left click) a menu appears. This menu is NOT the classic context menu but rather a custom panel with controls that I created personnaly. An example is search box ont top with a list of items. As you enter letters the list is trimmed to the matching items and when an item is clicked the context menu disappears and the value selected is wrtitten in the label we first clicked on.
You can use the method described here:
http://www.codeproject.com/Articles/22780/Super-Context-Menu-Strip
Since it uses ContextMenuStrip you can set its position:
contextMenuStrip1.Show(Cursor.Position);
and shadow effect:
http://msdn.microsoft.com/en-us/library/system.windows.controls.contextmenu.hasdropshadow.aspx
The simplest way (since this doesn't appear to be an actual menu) would be to create a borderless form and add shadow to it:
public class ShadowForm : Form
{
// Define the CS_DROPSHADOW constant
private const int CS_DROPSHADOW = 0x00020000;
// Override the CreateParams property
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_DROPSHADOW;
return cp;
}
}
}
Regarding position, there is not much to it. Just check Cursor.Position or set coordinates using the arguments in your MouseUp event handler.
Complete code would look something like:
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
protected override OnMouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
var menu = new CustomMenu();
menu.Location = PointToScreen(e.Location);
menu.Show(this);
}
}
}
and for the "menu" form:
public partial class CustomMenu : Form
{
public CustomMenu()
{
InitializeComponent();
this.StartPosition = FormStartPosition.Manual;
}
private const int CS_DROPSHADOW = 0x00020000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_DROPSHADOW;
return cp;
}
}
protected override void OnLostFocus(EventArgs e)
{
this.Close();
base.OnLostFocus(e);
}
}
When you click outside the ContextMenu it disappears. Yes. With this CustomMenu also you can do that.
protected override void OnDeactivate(EventArgs e)
{
this.Close();
base.OnDeactivate(e);
}
I tested this and it worked fine for me. OnLeave and OnLostFocus did not fire when you click outside the form.
Could someone please show me a example of how to create a custom control based on a picturebox?
I just want this: If the picturebox gets clicked (OnKeyDown) the image should be moved by 3 pixels down and 3px to the right. Afterwards at an OnKeyUp event I want to restore the original image.
Can someone tell me how to do this?
"Gets clicked" is OnMouseX, not OnKeyX.
public partial class UserControl1 : PictureBox
{
public UserControl1()
{
InitializeComponent();
}
private bool shifted = false;
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && this.Image != null)
{
this.shifted = true;
this.Invalidate();
}
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && this.Image != null)
{
this.shifted = false;
this.Invalidate();
}
base.OnMouseUp(e);
}
protected override void OnPaint(PaintEventArgs pe)
{
if (this.shifted)
{
pe.Graphics.TranslateTransform(3, 3, System.Drawing.Drawing2D.MatrixOrder.Append);
}
base.OnPaint(pe);
}
}
I know it is an old post but I have found it and was very usefull.
But I spent about one working day with solving an issue that my DrawRectangle was drawn below image that I loaded.
The solution was to move base.OnPaint(pe); method on the begining of OnPaint method.
Hope this helps.
Adam