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:
Related
How do we make a Panel control scroll whatever's inside of it? I'm not talking about controls or user controls or custom controls. I'm talking only about pixels; drawn with GDI+:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GDITEST
{
public partial class Form1 : Form
{
public class Item
{
public int Height { get; set; }
public int Width { get; set; }
public int Top { get; set; }
}
internal List<Item> items = new List<Item>();
public Form1()
{
InitializeComponent();
}
private void panel_Paint(object sender, PaintEventArgs e)
{
if (items != null)
{
if (items.Count >= 1)
{
foreach (Item item in items)
{
using (Pen pen = new Pen(Color.Blue, 1))
{
int count;
count = items.Count;
count = count >= 1 ? count : 1;
e.Graphics.DrawRectangle(pen, 0, item.Top, (item.Width - SystemInformation.VerticalScrollBarWidth), item.Height);
}
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
items.Add(new Item() { Width = this.Width, Height = 25, Top = (items.Count * 25) });
panel.Refresh();
}
}
}
The above code draws a blue rectangle (kinda like a vertical list). When the number of rectangles extends the height of the panel, I want the panel to scroll.
I've not been able to find out how to do this, since most of the results only return stuff related to scrolling custom controls.
I did read somewhere (which I can no longer find) that you can use some translateX or translateY methods... Yet I am having a hard time trying to find out anything more about those methods.
There's a simple bug in your code, you forgot to offset what you draw by the scroll amount. The Panel class has two other quirks, it was optimized to be a container control and cuts corners on the way it paints. You get rid of all three issues by creating your derived class from Panel. Project > Add Class > paste the code shown below. Build > Build and drop the new control from the top of the toolbox onto your form.
using System;
using System.Windows.Forms;
class MyPanel : Panel {
public MyPanel() {
this.DoubleBuffered = this.ResizeRedraw = true;
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
base.OnPaint(e);
}
}
You can further optimize your Paint event handler by paying attention to the e.ClipRectangle property and skip drawing an item when it is clipped. Just in case: assign the AutoScrollMinSize property to fit the items.
Here's a rough example on how to manually show the scrollbars. The panel contains a red rectangle, which can be clicked and dragged. If the rectangle is moved outside the viewable area, the scrollbars appear.
public class DrawPanel : Panel {
public Rectangle rect = new Rectangle(0, 0, 200, 100);
int offsetX = 0;
int offsetY = 0;
bool grabbing = false;
public DrawPanel() {
Dock = DockStyle.Fill;
AutoScroll = true;
}
protected override void OnMouseDown(MouseEventArgs e) {
base.OnMouseDown(e);
var p = e.Location;
if (rect.Contains(p)) {
grabbing = true;
offsetX = rect.X - p.X;
offsetY = rect.Y - p.Y;
}
}
protected override void OnMouseUp(MouseEventArgs e) {
base.OnMouseUp(e);
grabbing = false;
}
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
if (grabbing) {
var p = e.Location;
rect.Location = new Point(p.X + offsetX, p.Y + offsetY);
Invalidate();
int right = rect.X + rect.Width;
int bottom = rect.Y + rect.Height;
if (right > Width || bottom > Height) {
this.AutoScrollMinSize = new Size(right + 1, bottom + 1);
}
}
}
protected override void OnScroll(ScrollEventArgs se) {
base.OnScroll(se);
Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
var g = e.Graphics;
var p = AutoScrollPosition;
Rectangle r = rect;
r.X += p.X;
r.Y += p.Y;
g.DrawRectangle(Pens.Red, r);
}
}
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.
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();
}
}
}
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