I have the following custom framework element (which just draws a rectangle and some ellipses) with nested "visuals". Now I want to change some colors when the mouse enters or leaves the control. The code will be called but the color won't change even with InvalidVisual. Any idea what's wrong here:
public class Dummy : FrameworkElement
{
#region Fields
private Ellipse _bottomLeft = new Ellipse();
private Ellipse _bottomRight = new Ellipse();
private ContainerVisual _containerVisual = new ContainerVisual();
private Rectangle _rect = new Rectangle();
private Ellipse _topLeft = new Ellipse();
private Ellipse _topRight = new Ellipse();
#endregion Fields
#region Constructors
public Dummy()
{
Initialize();
_containerVisual.Children.Add(_rect);
_containerVisual.Children.Add(_topLeft);
_containerVisual.Children.Add(_topRight);
_containerVisual.Children.Add(_bottomLeft);
_containerVisual.Children.Add(_bottomRight);
}
#endregion Constructors
#region Properties
protected override int VisualChildrenCount
{
get { return _containerVisual == null ? 0 : 1; }
}
#endregion Properties
#region Methods
private void Initialize()
{
// Rectangle
_rect.Stroke = Brushes.Red;
_rect.StrokeThickness = 1;
_rect.Fill = new SolidColorBrush(Colors.Transparent);
// Ellipses
_topLeft.StrokeThickness = 1;
_topLeft.Stroke = Brushes.Red;
_topLeft.Fill = new SolidColorBrush(Colors.Orange);
//----------------
_topRight.StrokeThickness = 1;
_topRight.Stroke = Brushes.Red;
_topRight.Fill = new SolidColorBrush(Colors.Orange);
//----------------
_bottomLeft.StrokeThickness = 1;
_bottomLeft.Stroke = Brushes.Red;
_bottomLeft.Fill = new SolidColorBrush(Colors.Orange);
//----------------
_bottomRight.StrokeThickness = 1;
_bottomRight.Stroke = Brushes.Red;
_bottomRight.Fill = new SolidColorBrush(Colors.Orange);
}
protected override Size ArrangeOverride(Size finalSize)
{
var diameter = 6;
var radius = diameter / 2;
var rectThicknessOffset = _rect.StrokeThickness / 2;
var rect = new Rect(new Point(0, 0), finalSize);
_rect.Arrange(rect);
_topLeft.Arrange(new Rect(rect.TopLeft.X - radius + rectThicknessOffset,
rect.TopLeft.Y - radius + rectThicknessOffset, diameter, diameter));
_topRight.Arrange(new Rect(rect.TopRight.X - radius - rectThicknessOffset,
rect.TopRight.Y - radius + rectThicknessOffset, diameter, diameter));
_bottomRight.Arrange(new Rect(rect.BottomRight.X - radius - rectThicknessOffset,
rect.BottomRight.Y - radius - rectThicknessOffset, diameter, diameter));
_bottomLeft.Arrange(new Rect(rect.BottomLeft.X - radius + rectThicknessOffset,
rect.BottomLeft.Y - radius - rectThicknessOffset, diameter, diameter));
return base.ArrangeOverride(finalSize);
}
// Provide a required override for the GetVisualChild method.
protected override Visual GetVisualChild(int index)
{
if (_containerVisual == null)
{
throw new ArgumentOutOfRangeException();
}
return _containerVisual;
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
_rect.Stroke = new SolidColorBrush(Colors.Blue);
InvalidateVisual();
Debug.WriteLine("Mouse Enter");
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
_rect.Stroke = new SolidColorBrush(Colors.Green);
InvalidateVisual();
Debug.WriteLine("Mouse Leave");
}
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
#endregion Methods
}
Try to replace the call to InvalidateVisual with calls to Measure and Arrange:
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
_rect.Stroke = new SolidColorBrush(Colors.Green);
Measure(Size.Empty);
Arrange(new Rect(DesiredSize));
Debug.WriteLine("Mouse Leave");
}
Related
I've put together a custom control in WPF in C# based on the Selector primitive:
public class PadControl : Selector
{
private const int padWidth = 28;
private const int padHeight = 18;
private const int padGap = 5;
private double _width;
private double _height;
static PadControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PadControl), new FrameworkPropertyMetadata(typeof(PadControl),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
}
public PadControl()
{
}
protected override Size MeasureOverride(Size constraint)
{
_width = constraint.Width;
_height = constraint.Height;
return base.MeasureOverride(constraint);
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
var numHorz = _width / (padWidth + padGap);
var numVert = Math.Min(_height / (padHeight + padGap), 16);
var pen = new Pen(Brushes.Black, 1.0);
var brush = new SolidColorBrush(Color.FromRgb(192, 192, 192));
for(int bar = 0; bar < numHorz; bar++)
{
for(int track = 0; track < numVert; track++)
{
var rect = GetPadRect(bar, track);
dc.DrawRectangle(brush, pen, rect);
}
}
if (Items == null)
return;
brush = new SolidColorBrush(Colors.LightYellow);
var typeface = new Typeface("Tahoma");
foreach(PadViewModel item in Items)
{
var rect = GetPadRect(item.Bar, item.Track);
dc.DrawRectangle(brush, pen, rect);
var formatted = new FormattedText(item.Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12, Brushes.Black, 1.0)
{
MaxTextWidth = padWidth,
TextAlignment = TextAlignment.Center
};
dc.DrawText(formatted, GetPadPoint(item.Bar, item.Track));
}
}
private Rect GetPadRect(int bar, int track)
{
var rect = new Rect(bar * (padWidth + padGap) + padGap, track * (padHeight + padGap) + padGap, padWidth, padHeight);
return rect;
}
private Point GetPadPoint(int bar, int track)
{
var point = new Point(bar * (padWidth + padGap) + padGap, track * (padHeight + padGap) + padGap);
return point;
}
}
This draws as I'd like it, but it doesn't draw the items until I resize the control.
When the control renders for the first time, it doesn't render any Items as that is empty. Items is populated indirectly with this:
<controls:PadControl Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Pads}"/>
The problem is, I don't see an update come through after ItemsSource has been set. So the question is, how do I attach an event handler to catch this? Do I attach it to Items or to ItemsSource?
The answer is to override OnItemsSourceChanged as described by Keith Stein in the comments above.
I create a code give that allow me to resize a circle and move it
first mouse click give me the center for the circle.
the circle radius will change with the cursor movement (closer to the center smaller radius farther from the center bigger radius).
click second time the radius will not be changed and the circle will be finalized.
This is an image similar to what I want to do:
http://lh6.ggpht.com/_wQH6U92SY04/S_6lAJI7E-I/AAAAAAAAKwE/i-Jkq-nI5Ss/GoogleMapCircle%5B11%5D.gif?imgmax=800
The problems are :
the center is not exactly where I click the mouse first time.
the cursor should be exactly at the circle border when I move it.
the biggest problem is after clicking second time the circle is move farther from the center .
PLEASE HELP
using System;
using System.Drawing;
using System.Windows.Forms;
namespace project
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
Bitmap background;
Graphics scG;
Rectangle rectangleObj;
int clikno = 0;
private Point clickCurrent = Point.Empty;
private Point clickPrev = Point.Empty;
private void Form1_Load(object sender, EventArgs e)
{
background = new Bitmap(this.Width, this.Height);
rectangleObj = new Rectangle(10, 10, 100, 100);
scG = Graphics.FromImage(background);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
clickCurrent = this.PointToClient(Cursor.Position);
clickPrev = clickCurrent;
rectangleObj.X = e.X;
rectangleObj.Y = e.Y;
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.DrawImage(Draw(), 0, 0);
}
public Bitmap Draw()
{
Graphics scG = Graphics.FromImage(background);
Pen myPen = new Pen(System.Drawing.Color.Red, 3);
scG.Clear(SystemColors.Control);
scG.DrawEllipse(myPen, rectangleObj);
return background;
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
clikno = clikno + 1;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
double oradius = Math.Sqrt((Math.Pow(clickPrev.X - e.X, 2)) + (Math.Pow(clickPrev.Y - e.Y, 2)));
int radius = Convert.ToInt32(oradius);
if (clikno == 1)
{
rectangleObj.Height = radius;
rectangleObj.Width = radius;
rectangleObj.X = clickPrev.X;
rectangleObj.Y = clickPrev.Y;
Refresh();
}
if (clikno == 2)
clikno = 0;
Refresh();
}
}
}
I figured it out
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace Project
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
Bitmap background;
Graphics scG;
Rectangle rectangleObj;
Rectangle center;
int clikno = 0;
private Point clickCurrent = Point.Empty;
private Point clickPrev = Point.Empty;
private void Form1_Load(object sender, EventArgs e)
{
background = new Bitmap(this.Width, this.Height);//, this.Width,this.Height);
rectangleObj = new Rectangle(10, 10, 100, 100);
center = new Rectangle(10, 10, 3, 3);
scG = Graphics.FromImage(background);
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
clickCurrent = this.PointToClient(Cursor.Position);
clickPrev = clickCurrent;
if (clickPrev == Point.Empty) return;
Refresh();
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.DrawImage(Draw(), 0, 0);
}
public Bitmap Draw()
{
Graphics scG = Graphics.FromImage(background);
Pen myPen = new Pen(System.Drawing.Color.Red, 3);
scG.Clear(SystemColors.Control);
scG.DrawEllipse(myPen, rectangleObj);
// scG.DrawRectangle(myPen, rectangleObj);
scG.DrawEllipse(myPen, center);
return background;
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
clikno = clikno + 1;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
double oradius = Math.Sqrt((Math.Pow(clickPrev.X - e.X, 2)) + (Math.Pow(clickPrev.Y - e.Y, 2)));
int radius = Convert.ToInt32(oradius);
if (clikno == 1)
{
rectangleObj.Height = radius;
rectangleObj.Width = radius;
rectangleObj.X = clickPrev.X- rectangleObj.Height /2;// +radius;
rectangleObj.Y = clickPrev.Y - rectangleObj.Width / 2;// +radius;
center.X = clickPrev.X - center.Height / 2;// +radius;
center.Y = clickPrev.Y - center.Width / 2;// +radius;
Refresh();
}
if (clikno == 2)
clikno = 0;
Refresh();
}
string myString = 5.ToString();
}
}
I am working on a Adorner for a Line in a drawing program using WPF. The Line is drawn in code-behind and then adorned with my custom Adorner called LineAdorner. I've managed to use a Thumb for the start and end point of the Line. It's working fine for resizing. My problem is i cant able to move (drag & drop) the line, how to do that?
public class ResizingAdorner : Adorner
{
// Resizing adorner uses Thumbs for visual elements.
// The Thumbs have built-in mouse input handling.
//Thumb topLeft, topRight, bottomLeft, bottomRight;
private Thumb startThumb;
private Thumb endThumb;
private Line selectedLine;
private Point startPoint;
private Point endPoint;
// To store and manage the adorner's visual children.
VisualCollection visualChildren;
bool IsControlModeOn = false;
// Override the VisualChildrenCount and GetVisualChild properties to interface with
// the adorner's visual collection.
protected override int VisualChildrenCount { get { return visualChildren.Count; } }
protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
// Initialize the ResizingAdorner.
public ResizingAdorner(UIElement adornedElement)
: base(adornedElement)
{
visualChildren = new VisualCollection(this);
selectedLine = AdornedElement as Line;
startThumb = new Thumb { Cursor = Cursors.Hand, Width = 8, Height = 8, Background = Brushes.Green };
endThumb = new Thumb { Cursor = Cursors.Hand, Width = 8, Height = 8, Background = Brushes.BlueViolet };
startThumb.DragDelta += StartDragDelta;
endThumb.DragDelta += EndDragDelta;
startThumb.DragCompleted += new DragCompletedEventHandler(startThumb_DragCompleted);
endThumb.DragCompleted += new DragCompletedEventHandler(endThumb_DragCompleted);
visualChildren.Add(startThumb);
visualChildren.Add(endThumb);
}
public event EndDragDeltaEvent endDragDeltaEvent;
public delegate void EndDragDeltaEvent(object obj, DragCompletedEventArgs e, bool isEnd);
void startThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
if (endDragDeltaEvent != null)
endDragDeltaEvent(selectedLine, e, false);
}
void endThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
if (endDragDeltaEvent != null)
endDragDeltaEvent(selectedLine, e, true);
}
// Arrange the Adorners.
protected override Size ArrangeOverride(Size finalSize)
{
selectedLine = AdornedElement as Line;
double left = Math.Min(selectedLine.X1, selectedLine.X2);
double top = Math.Min(selectedLine.Y1, selectedLine.Y2);
var startRect = new Rect(selectedLine.X1 - (startThumb.Width / 2), selectedLine.Y1 - (startThumb.Width / 2), startThumb.Width, startThumb.Height);
startThumb.Arrange(startRect);
var endRect = new Rect(selectedLine.X2 - (endThumb.Width / 2), selectedLine.Y2 - (endThumb.Height / 2), endThumb.Width, endThumb.Height);
endThumb.Arrange(endRect);
return finalSize;
}
private void StartDragDelta(object sender, DragDeltaEventArgs e)
{
Point position = Mouse.GetPosition(this);
selectedLine.X1 = position.X;
selectedLine.Y1 = position.Y;
}
// Event for the Thumb End Point
private void EndDragDelta(object sender, DragDeltaEventArgs e)
{
Point position = Mouse.GetPosition(this);
selectedLine.X2 = position.X;
selectedLine.Y2 = position.Y;
}
protected override void OnRender(DrawingContext drawingContext)
{
if (AdornedElement is Line)
{
selectedLine = AdornedElement as Line;
startPoint = new Point(selectedLine.X1, selectedLine.Y1);
endPoint = new Point(selectedLine.X2, selectedLine.Y2);
}
}
}
You'll need to handle the MouseDown, MouseMove and MouseUp events on the line to be able to do that:
Add handlers for those events in the constructor
selectedLine.MouseLeftButtonDown += SelectedLineOnMouseLeftButtonDown;
selectedLine.MouseMove += SelectedLineOnMouseMove;
selectedLine.MouseLeftButtonUp += SelectedLineOnMouseLeftButtonUp;
And the implementation is something like this
private Point origin;
private void SelectedLineOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
Line line = (Line) sender;
line.CaptureMouse();
startPoint = new Point(line.X1, line.Y1);
endPoint = new Point(line.X2, line.Y2);
origin = e.GetPosition(line);
base.OnMouseLeftButtonDown(e);
}
private void SelectedLineOnMouseMove(object sender, MouseEventArgs e)
{
base.OnMouseMove(e);
Line line = (Line) sender;
if (e.MouseDevice.LeftButton == MouseButtonState.Pressed)
{
Point position = e.GetPosition(this);
e.Handled = true;
double horizontalDelta = position.X - origin.X;
double verticalDelta = position.Y - origin.Y;
line.X1 = startPoint.X + horizontalDelta;
line.X2 = endPoint.X + horizontalDelta;
line.Y1 = startPoint.Y + verticalDelta;
line.Y2 = endPoint.Y + verticalDelta;
InvalidateArrange();
}
else
{
line.ReleaseMouseCapture();
}
}
private void SelectedLineOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Line line = (Line) sender;
line.ReleaseMouseCapture();
e.Handled = true;
base.OnMouseLeftButtonUp(e);
}
I also added some InvalidateArrange() calls in the StartDragDelta and EndDragDelta handlers to makes sure the Thumbs move when being dragged.
I faced with the problem with custom DataGridView. I want to draw a bottom line, but I can't avoid of drawing this line that remain on cells when I scrolling the grid.
public partial class GridTest : DataGridView
{
private static Color _gridColor = Color.FromArgb(219, 225, 232);
private int gridHeight;
private bool resizing;
private const int Xoffset = 5;
private const int Yoffset = 10;
Color cl1 = Color.FromArgb(255, 255, 255);
Color cl2 = Color.FromArgb(229, 233, 238);
Color cl3 = Color.FromArgb(234, 237, 242);
Color cl4 = Color.FromArgb(170, 186, 208);
private Color _clrColumnHeader;
public Color ColorColumnHeader
{
get { return _clrColumnHeader; }
set { _clrColumnHeader = value; }
}
public GridTest()
{
InitializeComponent();
Init();
}
public GridTest(IContainer container)
{
container.Add(this);
InitializeComponent();
Init();
}
private void Init()
{
var _headerHeight = 50;
ColumnHeadersHeight = _headerHeight;
BackgroundColor = Color.White;
RowTemplate.Height += 5;
AllowUserToAddRows = false;
AllowUserToDeleteRows = false;
AllowUserToResizeColumns = false;
AllowUserToResizeRows = false;
AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders);
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal;
RowHeadersVisible = false;
MultiSelect = false;
ReadOnly = true;
AutoGenerateColumns = false;
EnableHeadersVisualStyles = false;
ShowCellErrors = false;
ShowEditingIcon = false;
ShowRowErrors = false;
}
private Blend gradientBlend()
{
float[] myFactors = { 0.0f, .00f, .8f, 1.0f };
float[] myPositions = { 0.0f, .4f, .8f, 1.0f };
var myBlend = new Blend {Factors = myFactors, Positions = myPositions};
return myBlend;
}
private void DrawGradientOnHeader(DataGridViewCellPaintingEventArgs e)
{
var newRect = new Rectangle(e.CellBounds.X+1, e.CellBounds.Y, e.CellBounds.Width -1, e.CellBounds.Height-1);
var gradient = new LinearGradientBrush(newRect, cl1, cl2, LinearGradientMode.Vertical);
gradient.Blend = gradientBlend();
e.Graphics.FillRectangle(gradient, newRect);
gradient.Dispose();
}
private static void DrawWhiteLine(DataGridViewCellPaintingEventArgs e, int x, int offset)
{
var brush = new SolidBrush(Color.White);
var pen = new Pen(brush);
int y = e.CellBounds.Y;
int x1 = x + offset;
int y1 = e.CellBounds.Height - 1;
var pt1 = new Point(x1, y);
var pt2 = new Point(x1, y1);
e.Graphics.DrawLine(pen, pt1, pt2);
brush.Dispose();
pen.Dispose();
}
private void DrawSeparators(DataGridViewCellPaintingEventArgs e)
{
DrawWhiteLine(e,e.CellBounds.Right,-1);
DrawWhiteLine(e, e.CellBounds.Left,1);
int x = e.CellBounds.X;
int y = e.CellBounds.Y;
int y1 = e.CellBounds.Height - 1;
var newRect2 = new Rectangle(x, y, 1, y1);
var gradient = new LinearGradientBrush(newRect2, cl3, cl4, LinearGradientMode.Vertical);
gradient.Blend = gradientBlend();
e.Graphics.FillRectangle(gradient, newRect2);
gradient.Dispose();
}
private static void DrawLines(DataGridViewCellPaintingEventArgs e)
{
var brush= new SolidBrush(Color.FromArgb(170, 186, 208));
var pen = new Pen(brush);
//Верхняя линяя над хидером
e.Graphics.DrawLine(pen, e.CellBounds.X, e.CellBounds.Top , e.CellBounds.Right, e.CellBounds.Top );
//Нижняя линия под хидером
e.Graphics.DrawLine(pen, e.CellBounds.X, e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom-1);
brush.Dispose();
pen.Dispose();
}
private void DrawText(DataGridViewCellPaintingEventArgs e)
{
var clr_font = _clrColumnHeader;
var rect = new Rectangle(e.CellBounds.X + Xoffset, e.CellBounds.Y + Yoffset, e.CellBounds.Width,
e.CellBounds.Height);
var formatFlags = TextFormatFlags.WordBreak;
if (e.Value != null)
{
try
{
TextRenderer.DrawText(e.Graphics, (String)e.Value, e.CellStyle.Font, rect, clr_font, formatFlags);
}
catch
{
TextRenderer.DrawText(e.Graphics, "", e.CellStyle.Font, rect, clr_font, formatFlags);
}
}
}
private void EraseTheCell(DataGridViewCellPaintingEventArgs e)
{
using (Brush backColorBrush = new SolidBrush(e.CellStyle.BackColor))
{
e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
}
}
protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
{
base.OnColumnWidthChanged(e);
Invalidate();
}
private int oldRowIndex = 0;
protected override void OnCurrentCellChanged(EventArgs e)
{
base.OnCurrentCellChanged(e);
if (oldRowIndex != -1)
{
InvalidateRow(oldRowIndex);
}
oldRowIndex = CurrentCellAddress.Y;
}
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
base.OnCellPainting(e);
if (e.RowIndex == -1) // Рисуем ColumnHeader
{
EraseTheCell(e);
DrawGradientOnHeader(e);
DrawSeparators(e);
DrawText(e);
DrawLines(e);
e.Handled = true;
}
//e.CellStyle.BackColor = Color.White;
}
protected override void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds)
{
base.PaintBackground(graphics, clipBounds, gridBounds);
var brush = new SolidBrush(Color.Black);
var pen = new Pen(brush);
var y_crd = clipBounds.Bottom - 10;
var x_crd = clipBounds.Right;
graphics.FillRectangle(brush, clipBounds);
var newbounds = new Rectangle
{
X = clipBounds.X,
Y = clipBounds.Y,
Width = clipBounds.Width,
Height = clipBounds.Height - 1
};
var brushWhite = new SolidBrush(Color.White);
graphics.FillRectangle(brushWhite, newbounds);
//graphics.DrawLine(pen, 0, y_crd, x_crd, y_crd);
brush.Dispose();
pen.Dispose();
}
}
I would like to create a control the floats (potentially) outside the bounds of it's containing form. Is this possible? How may I do it?
This would function much like Context Menu's only I need to be able to add other controls to it such as buttons and images.
You want a Form with it's FormBorderStyle set to None, if you want it to behave like a context menu then you'll need to tie showing it to the appropriate event handler in your main form. Simple example below of setting the location and calling show from a mouse click event handler.
MyForm form = new MyForm();
form.Location = PointToScreen(new Point(e.X, e.Y));
form.Show();
It is possible, the TopLevel property controls this. However, the designer doesn't support them well, hard to keep control over controls that are also top-level windows at design time.
Beyond components like ToolTip and ContextMenuStrip, there is exactly one class that is top-level by design, the Form class. Set its FormBorderStyle to None and ControlBox to False to create a basic top-level window that you can use and populate with other controls.
Take a look at the DockPanel Suite source and adopt the technique.
here is u can made for all Control floating Style
private void Panel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Panel.Left += e.X - PanelMouseDownLocation.X;
Panel.Top += e.Y - PanelMouseDownLocation.Y;
}
}
private void Panel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) PanelMouseDownLocation = e.Location;
}
public Point PanelMouseDownLocation { get; set; }
It would need to be a separate window (much like a context menu actually is) -- you could wrap it as a control, that displays a modeless form (which would even give you the option for non rectangular windows if you really wanted to). As you could create the window from a non-visible control from the parent form, you can maintain a reference to the child for handling inter-form communication.
Have your UserControl override CreateParams. For example:
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
cp.ExStyle &= 0x00080000; // WS_EX_LAYERED
cp.Style = 0x40000000 | 0x4000000; // WS_CHILD | WS_CLIPSIBLINGS
cp.Parent = GetDesktopWindow();
return cp;
}
}
This may have unintended effects (including not working well with Designer). I am choosing to follow one of the above patterns, but I thought it was worth mentioning here. Lookup CreateParams to see its purpose. (This option was gleaned from this page.)
This worked for me
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using LollipopUIControls.UIManagers;
namespace Gamasis.Apps.Controls
{
public class FloatingButton : Button
{
public FloatingButton()
{
SetStyle((ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint), true);
DoubleBuffered = true;
Size = new Size(50, 50);
BackColor = Color.Transparent;
SF.Alignment = StringAlignment.Center;
SF.LineAlignment = StringAlignment.Center;
AnimationTimer.Tick += new EventHandler(AnimationTick);
}
#region Variables
Timer AnimationTimer = new Timer { Interval = 1 };
FontManager font = new FontManager();
StringFormat SF = new StringFormat();
Rectangle StringRectangle;
bool Focus = false;
int margintop = 0, marginleft = 0, marginright = 0, marginBottom = 0;
int xx;
int yy;
float SizeAnimation = 0;
float SizeIncNum;
string fontcolor = "#FAFAFA";
string Backcolor = "#039BE5";
Color EnabledBGColor;
Color EnabledBorderColor;
Color StringColor;
Color DisabledBGColor = ColorTranslator.FromHtml("#B0BEC5");
Color DisabledStringColor = ColorTranslator.FromHtml("#FAFAFA");
Color NonColor = ColorTranslator.FromHtml("#e3e5e7");
Image bGImage = null;
#endregion
#region Properties
[Category("Custom")]
public string BGColor
{
get { return Backcolor; }
set
{
Backcolor = value;
Invalidate();
}
}
[Category("Custom")]
public string FontColor
{
get { return fontcolor; }
set
{
fontcolor = value;
Invalidate();
}
}
[Browsable(false)]
public Font Font
{
get { return base.Font; }
set { base.Font = value; }
}
[Browsable(false)]
public Color ForeColor
{
get { return base.ForeColor; }
set { base.ForeColor = value; }
}
[Category("Custom")]
public Image BGImage
{
get { return bGImage; }
set { bGImage = value; }
}
ImageSizeLevel bGimgSize = ImageSizeLevel.peque2;
public ImageSizeLevel BGimgSize
{
get { return bGimgSize; }
set { bGimgSize = value; }
}
#endregion
#region Events
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
EnabledBGColor = Color.FromArgb(30, ColorTranslator.FromHtml(BGColor));//StringColor);
EnabledBorderColor = Color.FromArgb(20, ColorTranslator.FromHtml(BGColor));//StringColor);
Refresh();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
EnabledBGColor = ColorTranslator.FromHtml(BGColor);
EnabledBorderColor = ColorTranslator.FromHtml(BGColor);
Refresh();
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
EnabledBGColor = Color.FromArgb(30, StringColor);
Refresh();
xx = e.X;
yy = e.Y;
Focus = true;
AnimationTimer.Start();
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
Focus = false;
AnimationTimer.Start();
Invalidate();
}
protected override void OnTextChanged(System.EventArgs e)
{
base.OnTextChanged(e);
Invalidate();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
//StringRectangle = new Rectangle(3, 0, Width - 6, Height - 6);
}
#endregion
protected override void OnResize(System.EventArgs e)
{
base.OnResize(e);
//SizeIncNum = Width / 34;
SizeIncNum = Width / 10;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var G = e.Graphics;
#region Default rectangle
//G.SmoothingMode = SmoothingMode.HighQuality | SmoothingMode.AntiAlias;
//G.Clear(Parent.BackColor);
//StringColor = ColorTranslator.FromHtml(fontcolor);
//var BG = DrawHelper.CreateRoundRect(1, 1, Width - 3, Height - 3, 1);
//Region region = new Region(BG);
//G.FillPath(new SolidBrush(Enabled ? EnabledBGColor : Color.White), BG);
//G.DrawPath(new Pen(Enabled ? EnabledBorderColor : Color.White), BG);
//G.SetClip(region, CombineMode.Replace);
////The Ripple Effect
//G.FillEllipse(new SolidBrush(Color.FromArgb(30, StringColor)), xx - (SizeAnimation / 2), yy - (SizeAnimation / 2), SizeAnimation, SizeAnimation);
//G.DrawString(Text, font.Roboto_Medium10, new SolidBrush(Enabled ? StringColor : DisabledStringColor), R, SF);
#endregion
#region Circle
//G.SmoothingMode = SmoothingMode.AntiAlias;
//G.Clear(BackColor);
//GraphicsPath bgbtn = new GraphicsPath();
//bgbtn.AddEllipse(0, 0, Width - 5, Height - 5);
//GraphicsPath bgShadow = new GraphicsPath();
//bgShadow.AddEllipse(0, 0, Width - 2, Height - 2);
//G.FillPath(new SolidBrush(NonColor), bgShadow);
//G.DrawPath(new Pen(NonColor), bgShadow);
//G.FillPath(new SolidBrush(Color.DeepSkyBlue), bgbtn);
//G.DrawPath(new Pen(Color.DeepSkyBlue), bgbtn);
#endregion
///----------------------------
G.SmoothingMode = SmoothingMode.AntiAlias;
G.Clear(Parent.BackColor);
StringColor = ColorTranslator.FromHtml(fontcolor);
//var BG = DrawHelper.CreateRoundRect(1, 1, Width - 3, Height - 3, 1);
//Círculo principal
GraphicsPath bgbtn = new GraphicsPath();
bgbtn.AddEllipse(2, 0, Width - 6, Height - 6);
//Círculo para la sombra
GraphicsPath bgShadow = new GraphicsPath();
bgShadow.AddEllipse(2, 4, Width - 6, Height - 6);
// se dibuja la sombra
G.FillPath(new SolidBrush(NonColor), bgShadow);
G.DrawPath(new Pen(NonColor), bgShadow);
//sedibuja el círculo principal sobre la sombra
G.FillPath(new SolidBrush(Enabled ? ColorTranslator.FromHtml(BGColor) : DisabledBGColor), bgbtn);
G.DrawPath(new Pen(Enabled ? ColorTranslator.FromHtml(BGColor) : DisabledBGColor), bgbtn);
// Se da a la región forma de círculo/elipse
Region region = new Region(bgbtn);//BG);
G.SetClip(region, CombineMode.Replace);
//The Ripple Effect
if (Enabled)
G.FillEllipse(new SolidBrush(Color.FromArgb(30, EnabledBGColor)), xx - (SizeAnimation / 2), yy - (SizeAnimation / 2), SizeAnimation, SizeAnimation);
StringRectangle = new Rectangle((int)bgbtn.GetBounds().Location.X, (int)bgbtn.GetBounds().Location.Y,
(int)bgbtn.GetBounds().Size.Width, (int)bgbtn.GetBounds().Size.Height);
G.DrawString(Text, font.Roboto_Medium15, new SolidBrush(Enabled ? StringColor : DisabledStringColor), StringRectangle, SF);
if (bGImage != null)
{
float imgX = 0, imgY = 0;
imgY = (bgbtn.GetBounds().Size.Height - (int)bGimgSize) / 2;
imgX = ((bgbtn.GetBounds().Size.Width - (int)bGimgSize) + 2) / 2;
G.DrawImage(bGImage, imgX, imgY, (float)bGimgSize, (float)bGimgSize);
}
}
protected void AnimationTick(object sender, EventArgs e)
{
if (Focus)
{
if (SizeAnimation < Width + 250)
{
SizeAnimation += SizeIncNum;
this.Invalidate();
}
}
else
{
if (SizeAnimation > 0)
{
SizeAnimation = 0;
this.Invalidate();
}
}
}
public enum ImageSizeLevel
{
peque = 12, peque1 = 24, peque2 = 32,
maso = 48, maso1 = 56, maso2 = 64,
grande = 72, grande1 = 86, grande2 = 96,
monstruo = 128, monstruo1 = 256, monstruo2 = 512
}
}
}