Related
I have made a program where you ask the number of ellipses and it makes them in a different window in c#,but I want to have a mouse over effect-which I understood is called : MouseEnter and an onclick event,which I understood is called MouseDown, but I made an array of ellipses and I tried the following :
namespace WpfApp1
{
/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>
public partial class Window2 : Window
{
int numOfElipses;
public Window2()
{
InitializeComponent();
numOfElipses= MainWindow.numOfElipse;
Ellipse[] ellipsePoints = new Ellipse[numOfElipses];
Random rnd = new Random();
for (int i=0;i<numOfElipses; i++)
{
SolidColorBrush brush =
new SolidColorBrush(
Color.FromRgb(
(byte)rnd.Next(255),
(byte)rnd.Next(255),
(byte)rnd.Next(255)
));
var top = rnd.Next(0, 280);
var left = rnd.Next(0, 450);
ellipsePoints[i] = new Ellipse();
ellipsePoints[i].Width = 40;
ellipsePoints[i].Height = 40;
Canvas.SetTop(ellipsePoints[i], i);
Canvas.SetLeft(ellipsePoints[i], i*45);
ellipsePoints[i].Fill = brush;
c1.Children.Add(ellipsePoints[i]);
}
}
private void E1_MouseEnter(object sender, MouseEventArgs e)
{
Random r = new Random();
Ellipse ellipsePoints = (Ellipse)sender;
ellipsePoints.Fill = new
SolidColorBrush(Color.FromRgb((byte)r.Next(255), (byte)r.Next(255),
(byte)r.Next(255)));
}
private void E1_MouseDown(object sender, MouseButtonEventArgs e)
{
c1.Children.Remove((Ellipse)sender);
}
}
}
but it doesn't work.Can anyone explain why and how do I make it change color on a mouse over(hover) randomly,and disappear/be removed on a mouse click?
I would really appreciate any help!
As mentioned in the comments, you need to actually hook up the events to the ellipses you are creating:
...
ellipsePoints[i].MouseEnter += E1_MouseEnter; // "hook up" the Mouse Enter event
ellipsePoints[i].MouseDown += E1_MouseDown; // "hook up" the Mouse Down event
c1.Children.Add(ellipsePoints[i]);
...
Simply creating the E1_MouseEnter and E1_MouseDown methods does not automatically wire them up, and that makes sense when we think about it. There could be any number of objects on the Window that have those events - how is the code supposed to know who should listen to?
I am looking to allow a user to drag a custom control around a Grid control smoothly, and I am not sure exactly what I am missing. All controls have AllowDrop set to true.
On MouseMove I do the following in the control that is being dragged:
DataObject dataObj = new DataObject("PersistentObject",this);
DragDrop.DoDragDrop(this, dataObj, DragDropEffects.Move);
On the Grid's DragEnter, DragOver, and DragDrop events, I set the effects of the DragEventArg to all.
The feedback shows that it the new location on the grid is a valid drop target, but it never seems to move.
Is there a way to do this on a Grid, or I am trying to do this on the wrong control (I am using a grid because the designer started with one)?
Are there other events that I have to fix, and/or are my current ones broken?
Edit: It would also be appreciated if it showed the control being dragged as it was happening. I am not sure if that is supposed to happen with my current approach, but that is the goal.
You can easily do this without using the built-in drag-drop stuff.
Point mouseOffset = new Point();
userControl.PreviewMouseLeftButtonDown += (sender, e) =>
{
mouseOffset = Mouse.GetPosition(userControl);
userControl.CaptureMouse();
};
userControl.PreviewMouseMove += (sender, e) =>
{
if (userControl.IsMouseCaptured)
{
Point mouseDelta = Mouse.GetPosition(userControl);
mouseDelta.Offset(-mouseOffset.X, -mouseOffset.Y);
userControl.Margin = new Thickness(
userControl.Margin.Left + mouseDelta.X,
userControl.Margin.Top + mouseDelta.Y,
userControl.Margin.Right - mouseDelta.X,
userControl.Margin.Bottom - mouseDelta.Y);
}
};
userControl.PreviewMouseLeftButtonUp += (sender, e) =>
{
userControl.ReleaseMouseCapture();
};
So the demo code I wrote up for this looks something like the following:
<Window x:Class="StackOverflowScratchpad.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="350"
Width="525">
<Grid>
<!-- I am using a Button here just for simplicity. The code
will function the same no matter what control is used. -->
<Button x:Name="userControl" Width="75" Height="23" />
</Grid>
</Window>
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object obj, RoutedEventArgs args)
{
// Add the above C# here.
}
I would suggest using a Canvas control instead. Here is an example Canvas control that anything you put in it will allow the user to drag around as well as resize:
Not the original code is NOT mine, although I have done some modifications to it, this was something I found on the web. (would love to quote the source here but I've long since forgotten unfortunately.)
Hopefully this helps, or at least points you in the right direction for what your looking for.
SuperCanvas:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using Meld.Helpers;
namespace Meld.Controls
{
public class SuperCanvas : Canvas
{
private AdornerLayer aLayer;
private bool isDown;
private bool isDragging;
private double originalLeft;
private double originalTop;
private bool selected;
private UIElement selectedElement;
private Point startPoint;
private bool locked;
public SuperCanvas()
{
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
MouseLeftButtonDown += WorkspaceWindow_MouseLeftButtonDown;
MouseLeftButtonUp += DragFinishedMouseHandler;
MouseMove += WorkspaceWindow_MouseMove;
MouseLeave += Window1_MouseLeave;
PreviewMouseLeftButtonDown += myCanvas_PreviewMouseLeftButtonDown;
PreviewMouseLeftButtonUp += DragFinishedMouseHandler;
}
// Handler for drag stopping on leaving the window
private void Window1_MouseLeave(object sender, MouseEventArgs e)
{
StopDragging();
e.Handled = true;
}
// Handler for drag stopping on user choice
private void DragFinishedMouseHandler(object sender, MouseButtonEventArgs e)
{
StopDragging();
e.Handled = true;
}
// Method for stopping dragging
private void StopDragging()
{
if (isDown)
{
isDown = false;
isDragging = false;
}
}
// Hanler for providing drag operation with selected element
private void WorkspaceWindow_MouseMove(object sender, MouseEventArgs e)
{
if (locked) return;
if (isDown)
{
if ((isDragging == false) &&
((Math.Abs(e.GetPosition(this).X - startPoint.X) >
SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(e.GetPosition(this).Y - startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
isDragging = true;
if (isDragging)
{
Point position = Mouse.GetPosition(this);
SetTop(selectedElement, position.Y - (startPoint.Y - originalTop));
SetLeft(selectedElement, position.X - (startPoint.X - originalLeft));
}
}
}
// Handler for clearing element selection, adorner removal
private void WorkspaceWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (locked) return;
if (selected)
{
selected = false;
if (selectedElement != null)
{
aLayer.Remove(aLayer.GetAdorners(selectedElement)[0]);
selectedElement = null;
}
}
}
// Handler for element selection on the canvas providing resizing adorner
private void myCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//add code to lock dragging and dropping things.
if (locked)
{
e.Handled = true;
return;
}
// Remove selection on clicking anywhere the window
if (selected)
{
selected = false;
if (selectedElement != null)
{
// Remove the adorner from the selected element
aLayer.Remove(aLayer.GetAdorners(selectedElement)[0]);
selectedElement = null;
}
}
// If any element except canvas is clicked,
// assign the selected element and add the adorner
if (e.Source != this)
{
isDown = true;
startPoint = e.GetPosition(this);
selectedElement = e.Source as UIElement;
originalLeft = GetLeft(selectedElement);
originalTop = GetTop(selectedElement);
aLayer = AdornerLayer.GetAdornerLayer(selectedElement);
aLayer.Add(new ResizingAdorner(selectedElement));
selected = true;
e.Handled = true;
}
}
}
}
And the ResizingAdorner:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace Meld.Helpers
{
internal class ResizingAdorner : Adorner
{
// Resizing adorner uses Thumbs for visual elements.
// The Thumbs have built-in mouse input handling.
Thumb topLeft, topRight, bottomLeft, bottomRight;
// To store and manage the adorner's visual children.
VisualCollection visualChildren;
// Initialize the ResizingAdorner.
public ResizingAdorner(UIElement adornedElement) : base(adornedElement)
{
visualChildren = new VisualCollection(this);
// Call a helper method to initialize the Thumbs
// with a customized cursors.
BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);
BuildAdornerCorner(ref topRight, Cursors.SizeNESW);
BuildAdornerCorner(ref bottomLeft, Cursors.SizeNESW);
BuildAdornerCorner(ref bottomRight, Cursors.SizeNWSE);
// Add handlers for resizing.
bottomLeft.DragDelta += new DragDeltaEventHandler(HandleBottomLeft);
bottomRight.DragDelta += new DragDeltaEventHandler(HandleBottomRight);
topLeft.DragDelta += new DragDeltaEventHandler(HandleTopLeft);
topRight.DragDelta += new DragDeltaEventHandler(HandleTopRight);
}
// Handler for resizing from the bottom-right.
void HandleBottomRight(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;
// Ensure that the Width and Height are properly initialized after the resize.
EnforceSize(adornedElement);
// Change the size by the amount the user drags the mouse, as long as it's larger
// than the width or height of an adorner, respectively.
adornedElement.Width = Math.Max(adornedElement.Width + args.HorizontalChange, hitThumb.DesiredSize.Width);
adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
}
// Handler for resizing from the top-right.
void HandleTopRight(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;
// Ensure that the Width and Height are properly initialized after the resize.
EnforceSize(adornedElement);
// Change the size by the amount the user drags the mouse, as long as it's larger
// than the width or height of an adorner, respectively.
adornedElement.Width = Math.Max(adornedElement.Width + args.HorizontalChange, hitThumb.DesiredSize.Width);
//adornedElement.Height = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
double height_old = adornedElement.Height;
double height_new = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
double top_old = Canvas.GetTop(adornedElement);
adornedElement.Height = height_new;
Canvas.SetTop(adornedElement, top_old - (height_new - height_old));
}
// Handler for resizing from the top-left.
void HandleTopLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
// Ensure that the Width and Height are properly initialized after the resize.
EnforceSize(adornedElement);
// Change the size by the amount the user drags the mouse, as long as it's larger
// than the width or height of an adorner, respectively.
//adornedElement.Width = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
//adornedElement.Height = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
double width_old = adornedElement.Width;
double width_new = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
double left_old = Canvas.GetLeft(adornedElement);
adornedElement.Width = width_new;
Canvas.SetLeft(adornedElement, left_old - (width_new - width_old));
double height_old = adornedElement.Height;
double height_new = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
double top_old = Canvas.GetTop(adornedElement);
adornedElement.Height = height_new;
Canvas.SetTop(adornedElement, top_old - (height_new - height_old));
}
// Handler for resizing from the bottom-left.
void HandleBottomLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement adornedElement = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
// Ensure that the Width and Height are properly initialized after the resize.
EnforceSize(adornedElement);
// Change the size by the amount the user drags the mouse, as long as it's larger
// than the width or height of an adorner, respectively.
//adornedElement.Width = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
double width_old = adornedElement.Width;
double width_new = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
double left_old = Canvas.GetLeft(adornedElement);
adornedElement.Width = width_new;
Canvas.SetLeft(adornedElement, left_old - (width_new - width_old));
}
// Arrange the Adorners.
protected override Size ArrangeOverride(Size finalSize)
{
// desiredWidth and desiredHeight are the width and height of the element that's being adorned.
// These will be used to place the ResizingAdorner at the corners of the adorned element.
double desiredWidth = AdornedElement.DesiredSize.Width;
double desiredHeight = AdornedElement.DesiredSize.Height;
// adornerWidth & adornerHeight are used for placement as well.
double adornerWidth = this.DesiredSize.Width;
double adornerHeight = this.DesiredSize.Height;
topLeft.Arrange(new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
topRight.Arrange(new Rect(desiredWidth - adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
bottomLeft.Arrange(new Rect(-adornerWidth / 2, desiredHeight - adornerHeight / 2, adornerWidth, adornerHeight));
bottomRight.Arrange(new Rect(desiredWidth - adornerWidth / 2, desiredHeight - adornerHeight / 2, adornerWidth, adornerHeight));
// Return the final size.
return finalSize;
}
// Helper method to instantiate the corner Thumbs, set the Cursor property,
// set some appearance properties, and add the elements to the visual tree.
void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
{
if (cornerThumb != null) return;
cornerThumb = new Thumb();
// Set some arbitrary visual characteristics.
cornerThumb.Cursor = customizedCursor;
cornerThumb.Height = cornerThumb.Width = 5;
cornerThumb.Opacity = 0.40;
cornerThumb.Background = new SolidColorBrush(Colors.White);
visualChildren.Add(cornerThumb);
}
// This method ensures that the Widths and Heights are initialized. Sizing to content produces
// Width and Height values of Double.NaN. Because this Adorner explicitly resizes, the Width and Height
// need to be set first. It also sets the maximum size of the adorned element.
void EnforceSize(FrameworkElement adornedElement)
{
if (adornedElement.Width.Equals(Double.NaN))
adornedElement.Width = adornedElement.DesiredSize.Width;
if (adornedElement.Height.Equals(Double.NaN))
adornedElement.Height = adornedElement.DesiredSize.Height;
FrameworkElement parent = adornedElement.Parent as FrameworkElement;
if (parent != null)
{
adornedElement.MaxHeight = parent.ActualHeight;
adornedElement.MaxWidth = parent.ActualWidth;
}
}
// 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]; }
}
}
you have to handle the code own Drop event
Drop event Occurs when an object is dropped within the bounds of an element that is acting as a drop target.
private void grid_Drop(object sender, DragEventArgs eventarg)
{
// check data is present returns a bool
if (eventarg.Data.GetDataPresent("PersistentObject"))
{
var yourdata=eventarg.Data.GetData("PersistentObject")as Model(T) ;
if (yourdata!= null)
{
// add to gird or whatever.
// place the object as you desire
}
}
Some Drag&Drop Reference
I created a DragDropBehaviour class a few years back. You should be able to copy-paste it and just change the OnDrop function.
public static class DragDropBehaviour
{
#region CanDrag attached dependancy property
/// <summary>
/// The CanDrag attached property'str name.
/// </summary>
public const string CanDragPropertyName = "CanDrag";
/// <summary>
/// Gets the value of the CanDrag attached property
/// for a given dependency object.
/// </summary>
/// <param name="obj">The object for which the property value
/// is read.</param>
/// <returns>The value of the CanDrag property of the specified object.</returns>
public static bool GetCanDrag(DependencyObject obj)
{
return (bool)obj.GetValue(CanDragProperty);
}
/// <summary>
/// Sets the value of the CanDrag attached property
/// for a given dependency object.
/// </summary>
/// <param name="obj">The object to which the property value
/// is written.</param>
/// <param name="value">Sets the CanDrag value of the specified object.</param>
public static void SetCanDrag(DependencyObject obj, bool value)
{
obj.SetValue(CanDragProperty, value);
}
/// <summary>
/// Identifies the CanDrag attached property.
/// </summary>
public static readonly DependencyProperty CanDragProperty = DependencyProperty.RegisterAttached(
CanDragPropertyName,
typeof(bool),
typeof(DragDropBehaviour),
new UIPropertyMetadata(false, OnCanDragChanged));
#endregion
#region CanDrop attached dependancy property
/// <summary>
/// The CanDrop attached property'str name.
/// </summary>
public const string CanDropPropertyName = "CanDrop";
/// <summary>
/// Gets the value of the CanDrop attached property
/// for a given dependency object.
/// </summary>
/// <param name="obj">The object for which the property value
/// is read.</param>
/// <returns>The value of the CanDrop property of the specified object.</returns>
public static bool GetCanDrop(DependencyObject obj)
{
return (bool)obj.GetValue(CanDropProperty);
}
/// <summary>
/// Sets the value of the CanDrop attached property
/// for a given dependency object.
/// </summary>
/// <param name="obj">The object to which the property value
/// is written.</param>
/// <param name="value">Sets the CanDrop value of the specified object.</param>
public static void SetCanDrop(DependencyObject obj, bool value)
{
obj.SetValue(CanDropProperty, value);
}
/// <summary>
/// Identifies the CanDrop attached property.
/// </summary>
public static readonly DependencyProperty CanDropProperty = DependencyProperty.RegisterAttached(
CanDropPropertyName,
typeof(bool),
typeof(DragDropBehaviour),
new UIPropertyMetadata(false, OnCanDropChanged));
#endregion
#region DragDropAction attached dependancy property
/// <summary>
/// The DragDropAction attached property'str name.
/// </summary>
public const string DragDropActionPropertyName = "DragDropAction";
/// <summary>
/// Gets the value of the DragDropAction attached property
/// for a given dependency object.
/// </summary>
/// <param name="obj">The object for which the property value
/// is read.</param>
/// <returns>The value of the DragDropAction property of the specified object.</returns>
public static DragDropAction GetDragDropAction(DependencyObject obj)
{
return (DragDropAction)obj.GetValue(DragDropActionProperty);
}
/// <summary>
/// Sets the value of the DragDropAction attached property
/// for a given dependency object.
/// </summary>
/// <param name="obj">The object to which the property value
/// is written.</param>
/// <param name="value">Sets the DragDropAction value of the specified object.</param>
public static void SetDragDropAction(DependencyObject obj, DragDropAction value)
{
obj.SetValue(DragDropActionProperty, value);
}
/// <summary>
/// Identifies the DragDropAction attached property.
/// </summary>
public static readonly DependencyProperty DragDropActionProperty = DependencyProperty.RegisterAttached(
DragDropActionPropertyName,
typeof(DragDropAction),
typeof(DragDropBehaviour),
new UIPropertyMetadata(null));
#endregion
static void OnCanDragChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = depObj as FrameworkElement;
if (element != null)
{
if ((bool)e.NewValue)
{
GetOrCreateAction(depObj).DragBehaviour(element, true);
}
else
{
GetOrCreateAction(depObj).DragBehaviour(element, false);
}
}
}
static void OnCanDropChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = depObj as FrameworkElement;
if (element != null)
{
if ((bool)e.NewValue)
{
GetOrCreateAction(depObj).DropBehaviour(element, true);
}
else
{
GetOrCreateAction(depObj).DropBehaviour(element, false);
}
}
}
static DragDropAction GetOrCreateAction(DependencyObject depObj)
{
DragDropAction action = depObj.GetValue(DragDropActionProperty) as DragDropAction;
if (action == null)
{
action = new DragDropAction();
depObj.SetValue(DragDropActionProperty, action);
}
return action;
}
}
public class DragDropAction
{
Point _start;
FrameworkElement _dragged;
public void DragBehaviour(FrameworkElement element, bool enable)
{
if (enable)
{
element.PreviewMouseLeftButtonDown += OnPreviewMouseLeftButtonDown;
element.PreviewMouseMove += OnPreviewMouseMove;
}
else
{
element.PreviewMouseLeftButtonDown -= OnPreviewMouseLeftButtonDown;
element.PreviewMouseMove -= OnPreviewMouseMove;
}
}
public void DropBehaviour(FrameworkElement element, bool enable)
{
if (enable)
{
element.Drop += OnDrop;
element.AllowDrop = true;
}
else
{
element.Drop -= OnDrop;
element.AllowDrop = false;
}
}
void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element != null)
{
int[] position = Win32Mouse.GetMousePosition();
_start = new Point(position[0], position[1]);
_dragged = element;
}
}
void OnPreviewMouseMove(object sender, MouseEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element != null && _dragged != null)
{
int[] position = Win32Mouse.GetMousePosition();
Point currentPosition = new Point(position[0], position[1]);
Vector diff = _start - currentPosition;
if (e.LeftButton == MouseButtonState.Pressed &&
Math.Abs(diff.X) > (SystemParameters.MinimumHorizontalDragDistance) &&
Math.Abs(diff.Y) > (SystemParameters.MinimumVerticalDragDistance))
{
DragDropEffects effects = DragDrop.DoDragDrop(element, _dragged.DataContext, DragDropEffects.Move);
_dragged = null;
e.Handled = true;
}
}
}
void OnDrop(object sender, DragEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element != null)
{
TabViewModel tab = element.DataContext as TabViewModel;
if (tab == null)
{
// TabViewModel not found it element, it's possible that the drop was done on the lastOpened 'Canvas' element.
var tabControls = element.FindVisualChildren<TabControl>();
var menus = element.FindVisualChildren<Menu>();
var itemControls = element.FindVisualChildren<ItemsControl>();
if (tabControls.Count > 0 && tabControls[0].Visibility == Visibility.Visible)
{
// If currently in 'horizontal mode' add to the active tab. If there is no active tab
// just add to the bottom tab.
tab = tabControls[0].SelectedItem as TabViewModel;
if (tab == null)
tab = tabControls[0].Items.GetItemAt(tabControls[0].Items.Count - 1) as TabViewModel;
}
else if (menus.Count > 0 && menus[0].Visibility == Visibility.Visible)
{
// If currently in 'vertical mode' add to the default tab, there is no 'active' menu item after all.
var tabs = menus[0].Items.SourceCollection as ObservableCollection<TabViewModel>;
tab = tabs.SingleOrDefault(obj => obj.Title == Configuration.DefaultTab) ?? tabs.LastOrDefault();
}
else if (itemControls.Count > 0 && itemControls[0].Visibility == Visibility.Visible)
{
var window = element.FindVisualParent<Window>();
if (window != null && window.DataContext is MainViewModel)
{
// Add the currently expanded tab.
MainViewModel mainViewModel = (MainViewModel)window.DataContext;
tab = mainViewModel.ExpandedTab;
// If no tab is expanded, add to the default tab or the bottom tab.
if (tab == null)
{
tab = mainViewModel.Tabs.SingleOrDefault(obj => obj.Title == Configuration.DefaultTab)
?? mainViewModel.Tabs.LastOrDefault();
}
}
}
}
if (tab != null)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
DispatcherHelper.UIDispatcher.BeginInvoke(new Action(() =>
{
string[] droppedFilePaths = e.Data.GetData(DataFormats.FileDrop, true) as string[];
foreach (string fileName in droppedFilePaths)
{
try
{
ApplicationModel model = ApplicationModel.FromFile(fileName, tab.Title);
ApplicationViewModel application = new ApplicationViewModel(model);
Messenger.Default.Send<ApplicationMessage>(ApplicationMessage.Add(application, tab));
}
catch (FileNotFoundException ex)
{
ServiceManager.GetService<IMessageBoxService>().Show(
"Could not add application - " + ex.Message, "Astounding Dock", MessageIcon.Error);
}
}
}));
e.Handled = true;
}
else if (e.Data.GetDataPresent<ApplicationViewModel>())
{
DispatcherHelper.UIDispatcher.BeginInvoke(new Action(() =>
{
ApplicationViewModel application = e.Data.GetData<ApplicationViewModel>();
Messenger.Default.Send<ApplicationMessage>(ApplicationMessage.Move(application, tab));
}));
e.Handled = true;
}
else
{
Debug.WriteLine("DragDropBehaviour: Unknown data droppped - " + String.Join(",", e.Data.GetFormats()));
}
}
}
}
}
https://github.com/notsonormal/AstoundingDock/blob/master/src/AstoundingDock/Ui/DragDropBehaviour.cs
You can enable dropping on a control like
<Canvas ui:DragDropBehaviour.CanDrop="True">
</Canvas>
And enable dragging and dropping like this
<Button ui:DragDropBehaviour.CanDrag="True" ui:DragDropBehaviour.CanDrop="True">
</Button>
https://github.com/notsonormal/AstoundingDock/blob/master/src/AstoundingDock/Views/MainWindow.xaml
It seems pretty generic but I only ever used it for one specific case so...
In the code below I am trying to zoom the image via a mouse wheel. But the code is not working properly, it is just refreshing the panel but it does not resize it. Actually I am taking the image from memory stream that is created by another class called as decrypt. Complete Image is displayed properly but I am not able to performing zooming of the image using mousewheel event.
Plz help Me.
private void Form2_Load(object sender, EventArgs e)
{
this.Width = Screen.PrimaryScreen.WorkingArea.Width;
this.Height = Screen.PrimaryScreen.WorkingArea.Height;
this.CenterToScreen();
PicturePanel= new PictureBox();
PicturePanel.Dock = DockStyle.Fill;
//PicturePanel.SizeMode = PictureBoxSizeMode.AutoSize;
//PicturePanel.SizeMode = PictureBoxSizeMode.CenterImage;
PicturePanel.Focus();
//PicturePanel.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.OnMouseWheel);
this.Controls.Add(PicturePanel);
View_codee v = new View_codee();
try
{
PicturePanel.Image = Image.FromStream(Decrypt.ms1);
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
this.Name = "";
}
protected override void OnMouseWheel(MouseEventArgs mea)
{
// Override OnMouseWheel event, for zooming in/out with the scroll wheel
if (PicturePanel.Image != null)
{
// If the mouse wheel is moved forward (Zoom in)
if (mea.Delta > 0)
{
// Check if the pictureBox dimensions are in range (15 is the minimum and maximum zoom level)
if ((PicturePanel.Width < (15 * this.Width)) && (PicturePanel.Height < (15 * this.Height)))
{
// Change the size of the picturebox, multiply it by the ZOOMFACTOR
PicturePanel.Width = (int)(PicturePanel.Width * 1.25);
PicturePanel.Height = (int)(PicturePanel.Height * 1.25);
// Formula to move the picturebox, to zoom in the point selected by the mouse cursor
PicturePanel.Top = (int)(mea.Y - 1.25 * (mea.Y - PicturePanel.Top));
PicturePanel.Left = (int)(mea.X - 1.25 * (mea.X - PicturePanel.Left));
}
}
else
{
// Check if the pictureBox dimensions are in range (15 is the minimum and maximum zoom level)
if ((PicturePanel.Width > (this.Width / 15)) && (PicturePanel.Height > (this.Height / 15)))
{
// Change the size of the picturebox, divide it by the ZOOMFACTOR
PicturePanel.Width = (int)(PicturePanel.Width / 1.25);
PicturePanel.Height = (int)(PicturePanel.Height / 1.25);
// Formula to move the picturebox, to zoom in the point selected by the mouse cursor
PicturePanel.Top = (int)(mea.Y - 0.80 * (mea.Y - PicturePanel.Top));
PicturePanel.Left = (int)(mea.X - 0.80 * (mea.X - PicturePanel.Left));
}
}
}
}
Source
Updated code by adding a new ImageProperty so you can set directly the Image;
public class PictureBox : System.Windows.Forms.UserControl
{
#region Members
private System.Windows.Forms.PictureBox PicBox;
private Panel OuterPanel;
private Container components = null;
private string m_sPicName = "";
#endregion
#region Constants
private double ZOOMFACTOR = 1.25; // = 25% smaller or larger
private int MINMAX = 5; // 5 times bigger or smaller than the ctrl
#endregion
#region Designer generated code
private void InitializeComponent()
{
this.PicBox = new System.Windows.Forms.PictureBox();
this.OuterPanel = new System.Windows.Forms.Panel();
this.OuterPanel.SuspendLayout();
this.SuspendLayout();
//
// PicBox
//
this.PicBox.Location = new System.Drawing.Point(0, 0);
this.PicBox.Name = "PicBox";
this.PicBox.Size = new System.Drawing.Size(150, 140);
this.PicBox.TabIndex = 3;
this.PicBox.TabStop = false;
//
// OuterPanel
//
this.OuterPanel.AutoScroll = true;
this.OuterPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.OuterPanel.Controls.Add(this.PicBox);
this.OuterPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.OuterPanel.Location = new System.Drawing.Point(0, 0);
this.OuterPanel.Name = "OuterPanel";
this.OuterPanel.Size = new System.Drawing.Size(210, 190);
this.OuterPanel.TabIndex = 4;
//
// PictureBox
//
this.Controls.Add(this.OuterPanel);
this.Name = "PictureBox";
this.Size = new System.Drawing.Size(210, 190);
this.OuterPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
#region Constructors
public PictureBox()
{
InitializeComponent();
InitCtrl(); // my special settings for the ctrl
}
#endregion
#region Properties
private Image _pictureImage;
public Image PictureImage
{
get { return _pictureImage; }
set
{
if (null != value)
{
try
{
PicBox.Image = value;
_pictureImage = value;
}
catch (OutOfMemoryException ex)
{
RedCross();
}
}
else
{
RedCross();
}
}
}
/// <summary>
/// Property to select the picture which is displayed in the picturebox. If the
/// file doesn´t exist or we receive an exception, the picturebox displays
/// a red cross.
/// </summary>
/// <value>Complete filename of the picture, including path information</value>
/// <remarks>Supported fileformat: *.gif, *.tif, *.jpg, *.bmp</remarks>
///
[Browsable(false)]
public string Picture
{
get { return m_sPicName; }
set
{
if (null != value)
{
if (System.IO.File.Exists(value))
{
try
{
PicBox.Image = Image.FromFile(value);
m_sPicName = value;
}
catch (OutOfMemoryException ex)
{
RedCross();
}
}
else
{
RedCross();
}
}
}
}
/// <summary>
/// Set the frametype of the picturbox
/// </summary>
[Browsable(false)]
public BorderStyle Border
{
get { return OuterPanel.BorderStyle; }
set { OuterPanel.BorderStyle = value; }
}
#endregion
#region Other Methods
/// <summary>
/// Special settings for the picturebox ctrl
/// </summary>
private void InitCtrl()
{
PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
PicBox.Location = new Point(0, 0);
OuterPanel.Dock = DockStyle.Fill;
OuterPanel.Cursor = System.Windows.Forms.Cursors.NoMove2D;
OuterPanel.AutoScroll = true;
OuterPanel.MouseEnter += new EventHandler(PicBox_MouseEnter);
PicBox.MouseEnter += new EventHandler(PicBox_MouseEnter);
OuterPanel.MouseWheel += new MouseEventHandler(PicBox_MouseWheel);
}
/// <summary>
/// Create a simple red cross as a bitmap and display it in the picturebox
/// </summary>
private void RedCross()
{
Bitmap bmp = new Bitmap(OuterPanel.Width, OuterPanel.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
Graphics gr;
gr = Graphics.FromImage(bmp);
Pen pencil = new Pen(Color.Red, 5);
gr.DrawLine(pencil, 0, 0, OuterPanel.Width, OuterPanel.Height);
gr.DrawLine(pencil, 0, OuterPanel.Height, OuterPanel.Width, 0);
PicBox.Image = bmp;
gr.Dispose();
}
#endregion
#region Zooming Methods
/// <summary>
/// Make the PictureBox dimensions larger to effect the Zoom.
/// </summary>
/// <remarks>Maximum 5 times bigger</remarks>
private void ZoomIn()
{
if ((PicBox.Width < (MINMAX * OuterPanel.Width)) &&
(PicBox.Height < (MINMAX * OuterPanel.Height)))
{
PicBox.Width = Convert.ToInt32(PicBox.Width * ZOOMFACTOR);
PicBox.Height = Convert.ToInt32(PicBox.Height * ZOOMFACTOR);
PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
/// <summary>
/// Make the PictureBox dimensions smaller to effect the Zoom.
/// </summary>
/// <remarks>Minimum 5 times smaller</remarks>
private void ZoomOut()
{
if ((PicBox.Width > (OuterPanel.Width / MINMAX)) &&
(PicBox.Height > (OuterPanel.Height / MINMAX)))
{
PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
PicBox.Width = Convert.ToInt32(PicBox.Width / ZOOMFACTOR);
PicBox.Height = Convert.ToInt32(PicBox.Height / ZOOMFACTOR);
}
}
#endregion
#region Mouse events
/// <summary>
/// We use the mousewheel to zoom the picture in or out
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PicBox_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta < 0)
{
ZoomIn();
}
else
{
ZoomOut();
}
}
/// <summary>
/// Make sure that the PicBox have the focus, otherwise it doesn´t receive
/// mousewheel events !.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PicBox_MouseEnter(object sender, EventArgs e)
{
if (PicBox.Focused == false)
{
PicBox.Focus();
}
}
#endregion
#region Disposing
/// <summary>
/// Die verwendeten Ressourcen bereinigen.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
}
private void Form2_Load(object sender, EventArgs e)
{
pictureBox1.PictureImage = Image.FromStream(Decrypt.ms1);
}
I have a usercontrol that has a textbox and a listbox, and it uses them to provides autocomplete functionality to the users.
However, I want the listbox to be drawn outside of the boundaries of the user control so that it doesn't get cutoff when the listbox has to be drawn near the edge of the user control. Any tips on how to do that? Essentially I want a listbox floating outside the boundaries of its container control.
The only way I can think off is to pass a reference to an outside listbox to the user control on instantiation and then manipulate that listbox instead of having it inside the user control, but I dont like this approach. Thanks in advance.
Problem is, you can't escape your container form bounds, but you can host your control somewhere else.
Here's what I got working by abusing the ToolstripDropDown class (I use it to display datepickers in a large enterprise application):
/// <summary>
/// PopupHelper
/// </summary>
public sealed class PopupHelper : IDisposable
{
private readonly Control m_control;
private readonly ToolStripDropDown m_tsdd;
private readonly Panel m_hostPanel; // workarround - some controls don't display correctly if they are hosted directly in ToolStripControlHost
public PopupHelper(Control pControl)
{
m_hostPanel = new Panel();
m_hostPanel.Padding = Padding.Empty;
m_hostPanel.Margin = Padding.Empty;
m_hostPanel.TabStop = false;
m_hostPanel.BorderStyle = BorderStyle.None;
m_hostPanel.BackColor = Color.Transparent;
m_tsdd = new ToolStripDropDown();
m_tsdd.CausesValidation = false;
m_tsdd.Padding = Padding.Empty;
m_tsdd.Margin = Padding.Empty;
m_tsdd.Opacity = 0.9;
m_control = pControl;
m_control.CausesValidation = false;
m_control.Resize += MControlResize;
m_hostPanel.Controls.Add(m_control);
m_tsdd.Padding = Padding.Empty;
m_tsdd.Margin = Padding.Empty;
m_tsdd.MinimumSize = m_tsdd.MaximumSize = m_tsdd.Size = pControl.Size;
m_tsdd.Items.Add(new ToolStripControlHost(m_hostPanel));
}
private void ResizeWindow()
{
m_tsdd.MinimumSize = m_tsdd.MaximumSize = m_tsdd.Size = m_control.Size;
m_hostPanel.MinimumSize = m_hostPanel.MaximumSize = m_hostPanel.Size = m_control.Size;
}
private void MControlResize(object sender, EventArgs e)
{
ResizeWindow();
}
/// <summary>
/// Display the popup and keep the focus
/// </summary>
/// <param name="pParentControl"></param>
public void Show(Control pParentControl)
{
if (pParentControl == null) return;
// position the popup window
var loc = pParentControl.PointToScreen(new Point(0, pParentControl.Height));
m_tsdd.Show(loc);
m_control.Focus();
}
public void Close()
{
m_tsdd.Close();
}
public void Dispose()
{
m_control.Resize -= MControlResize;
m_tsdd.Dispose();
m_hostPanel.Dispose();
}
}
Usage:
private PopupHelper m_popup;
private void ShowPopup()
{
if (m_popup == null)
m_popup = new PopupHelper(yourListControl);
m_popup.Show(this);
}
I'm trying to display a tooltip when mouse hovers over a disabled control. Since a disabled control does not handle any events, I have to do that in the parent form. I chose to do this by handling the MouseMove event in the parent form. Here's the code that does the job:
void Form1_MouseMove(object sender, MouseEventArgs e)
{
m_toolTips.SetToolTip(this, "testing tooltip on " + DateTime.Now.ToString());
string tipText = this.m_toolTips.GetToolTip(this);
if ((tipText != null) && (tipText.Length > 0))
{
Point clientLoc = this.PointToClient(Cursor.Position);
Control child = this.GetChildAtPoint(clientLoc);
if (child != null && child.Enabled == false)
{
m_toolTips.ToolTipTitle = "MouseHover On Disabled Control";
m_toolTips.Show(tipText, this, 10000);
}
else
{
m_toolTips.ToolTipTitle = "MouseHover Triggerd";
m_toolTips.Show(tipText, this, 3000);
}
}
}
The code does handles the tooltip display for the disabled control. The problem is that when mouse hovers over a disabled control, the tooltip keeps closing and redisplay again. From the display time I added in the tooltip, when mouse is above the parent form, the MouseMove event gets called roughly every 3 seconds, so the tooltip gets updated every 3 seconds. But when mouse is over a disabled control, the tooltip refreshes every 1 second. Also, when tooltip refreshes above form, only the text gets updated with a brief flash. But when tooltip refreshes above a disabled control, the tooltip windows closes as if mouse is moving into a enabled control and the tooltip is supposed to be closed. but then the tooltip reappears right away.
Can someone tell me why is this? Thanks.
you can show the tooltip only once when mouse hits the disbled control and then hide it when mouse leaves it. Pls, take a look at the code below, it should be showing a tooltip message for all the disabled controls on the form
private ToolTip _toolTip = new ToolTip();
private Control _currentToolTipControl = null;
public Form1()
{
InitializeComponent();
_toolTip.SetToolTip(this.button1, "My button1");
_toolTip.SetToolTip(this.button2, "My button2");
_toolTip.SetToolTip(this.textBox1, "My text box");
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Control control = GetChildAtPoint(e.Location);
if (control != null)
{
if (!control.Enabled && _currentToolTipControl == null)
{
string toolTipString = _toolTip.GetToolTip(control);
// trigger the tooltip with no delay and some basic positioning just to give you an idea
_toolTip.Show(toolTipString, control, control.Width/2, control.Height/2);
_currentToolTipControl = control;
}
}
else
{
if (_currentToolTipControl != null) _toolTip.Hide(_currentToolTipControl);
_currentToolTipControl = null;
}
}
hope this helps, regards
The answer turned out to be a bit simpler, but needed to be applied at all times.
void OrderSummaryDetails_MouseMove(object sender, MouseEventArgs e)
{
Control control = GetChildAtPoint(e.Location);
if (control != null)
{
string toolTipString = mFormTips.GetToolTip(control);
this.mFormTips.ShowAlways = true;
// trigger the tooltip with no delay and some basic positioning just to give you an idea
mFormTips.Show(toolTipString, control, control.Width / 2, control.Height / 2);
}
}
In case of TextBox control, making it as readonly solved the issue.
I tried many but ended up using this simple trick which I think it is more effective.
Create a subclass(CustomControl with just base control in it) which extends UserControl
then instead of setting "Enabled" property to false create a Method which disables just basecontrol in it instead of whole CustomControl.
Set the tool tip on CustomControl still will be able to fire eventhandlers setting the basecontrol disabled. This works wherever CustomControl is in use rather than coding on every form you use with.
Here is the hint.. :)
public partial class MyTextBox : UserControl
{
...
...
...
public void DisableMyTextBox()
{
this.txt.Enabled = false; //txt is the name of Winform-Textbox from my designer
this.Enabled = true;
}
public void EnableMyTextBox()
{
this.txt.Enabled = true;
this.Enabled = true;
}
//set the tooltip from properties tab in designer or wherever
}
Since no one ever pointed this out, this works for any control that exposes ToolTipService:
ToolTipService.ShowOnDisabled="True"
As in this example:
<Button Content="OK"
ToolTipService.ShowOnDisabled="True" />
/*
Inspired by the suggestions above in this post, i wrapped it up as an extended ToolTip control specially works for disabled control.
// Reference example
var td = new ToolTipOnDisabledControl();
this.checkEdit3.Enabled = false;
td.SetTooltip(this.checkEdit3, "tooltip for disabled 3333333333333");
*/
using System;
using System.Windows.Forms;
namespace TestApp1
{
public class ToolTipOnDisabledControl
{
#region Fields and Properties
private Control enabledParentControl;
private bool isShown;
public Control TargetControl { get; private set; }
public string TooltipText { get; private set; }
public ToolTip ToolTip { get; }
#endregion
#region Public Methods
public ToolTipOnDisabledControl()
{
this.ToolTip = new ToolTip();
}
public void SetToolTip(Control targetControl, string tooltipText = null)
{
this.TargetControl = targetControl;
if (string.IsNullOrEmpty(tooltipText))
{
this.TooltipText = this.ToolTip.GetToolTip(targetControl);
}
else
{
this.TooltipText = tooltipText;
}
if (targetControl.Enabled)
{
this.enabledParentControl = null;
this.isShown = false;
this.ToolTip.SetToolTip(this.TargetControl, this.TooltipText);
return;
}
this.enabledParentControl = targetControl.Parent;
while (!this.enabledParentControl.Enabled && this.enabledParentControl.Parent != null)
{
this.enabledParentControl = this.enabledParentControl.Parent;
}
if (!this.enabledParentControl.Enabled)
{
throw new Exception("Failed to set tool tip because failed to find an enabled parent control.");
}
this.enabledParentControl.MouseMove += this.EnabledParentControl_MouseMove;
this.TargetControl.EnabledChanged += this.TargetControl_EnabledChanged;
}
public void Reset()
{
if (this.TargetControl != null)
{
this.ToolTip.Hide(this.TargetControl);
this.TargetControl.EnabledChanged -= this.TargetControl_EnabledChanged;
this.TargetControl = null;
}
if (this.enabledParentControl != null)
{
this.enabledParentControl.MouseMove -= this.EnabledParentControl_MouseMove;
this.enabledParentControl = null;
}
this.isShown = false;
}
#endregion
#region Private Methods
private void EnabledParentControl_MouseMove(object sender, MouseEventArgs e)
{
if (e.Location.X >= this.TargetControl.Left &&
e.Location.X <= this.TargetControl.Right &&
e.Location.Y >= this.TargetControl.Top &&
e.Location.Y <= this.TargetControl.Bottom)
{
if (!this.isShown)
{
this.ToolTip.Show(this.TooltipText, this.TargetControl, this.TargetControl.Width / 2, this.TargetControl.Height / 2, this.ToolTip.AutoPopDelay);
this.isShown = true;
}
}
else
{
this.ToolTip.Hide(this.TargetControl);
this.isShown = false;
}
}
private void TargetControl_EnabledChanged(object sender, EventArgs e)
{
if (TargetControl.Enabled)
{
TargetControl.EnabledChanged -= TargetControl_EnabledChanged;
enabledParentControl.MouseMove -= EnabledParentControl_MouseMove;
}
}
#endregion
}
}
Here is how I solved this problem
I have an application that generates code automatically for a PIC32MX.
The application has 3 Tab Pages text = PWM, ADC and UART.
On each Tab Page I have one Check Box text = RPA0
The intention is, when a peripheral uses RPA0, the other peripheral is prevented
from using that pin, by disabling it on the other pages, and a tooltip text must pop up
on the disabled check boxs saying (example "Used by PWM")
what peripheral is using that pin.
The problem is that the tooltip text won't pop up on a disabled check box.
To solve the problem, I just removed the text of the check boxes and inserted labels with the text the check box should have.
When a check box is checked, the other check boxes are disabled and the label next to it takes a tool tip text.
As the label is enabled, the tooltip text pops up, even on a disabled check box.
Double the work, half the complexity.
Here is the code and the designer for C# 2010
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void cb_ADC_RPA0_CheckedChanged(object sender, EventArgs e)
{
/* Disable pin on other peripherals */
cb_UART_RPA0.Enabled = !((CheckBox)sender).Checked;
cb_PWM_RPA0.Enabled = !((CheckBox)sender).Checked;
SetTootTip((CheckBox)sender, lbl_PWM_RPA0, lbl_UART_RPA0, "ADC");
}
private void cb_PWM_RPA0_CheckedChanged(object sender, EventArgs e)
{
/* Disable pin on other peripherals */
cb_UART_RPA0.Enabled = !((CheckBox)sender).Checked;
cb_ADC_RPA0.Enabled = !((CheckBox)sender).Checked;
SetTootTip((CheckBox)sender, lbl_ADC_RPA0, lbl_UART_RPA0, "PWM");
}
private void cb_UART_RPA0_CheckedChanged(object sender, EventArgs e)
{
/* Disable pin on other peripherals */
cb_ADC_RPA0.Enabled = !((CheckBox)sender).Checked;
cb_PWM_RPA0.Enabled = !((CheckBox)sender).Checked;
SetTootTip((CheckBox)sender, lbl_ADC_RPA0, lbl_PWM_RPA0, "UART");
}
void SetTootTip(CheckBox sender, Label lbl1, Label lbl2, string text)
{
/* Update tooltip on the other labels */
if (sender.Checked)
{
toolTip1.SetToolTip(lbl1, "Used by " + text);
toolTip1.SetToolTip(lbl2, "Used by " + text);
}
else
{
toolTip1.SetToolTip(lbl1, "");
toolTip1.SetToolTip(lbl2, "");
}
}
}
}
namespace WindowsFormsApplication1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tpPWM = new System.Windows.Forms.TabPage();
this.tpUART = new System.Windows.Forms.TabPage();
this.tpADC = new System.Windows.Forms.TabPage();
this.cb_PWM_RPA0 = new System.Windows.Forms.CheckBox();
this.cb_ADC_RPA0 = new System.Windows.Forms.CheckBox();
this.lbl_PWM_RPA0 = new System.Windows.Forms.Label();
this.lbl_ADC_RPA0 = new System.Windows.Forms.Label();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.lbl_UART_RPA0 = new System.Windows.Forms.Label();
this.cb_UART_RPA0 = new System.Windows.Forms.CheckBox();
this.tabControl1.SuspendLayout();
this.tpPWM.SuspendLayout();
this.tpUART.SuspendLayout();
this.tpADC.SuspendLayout();
this.SuspendLayout();
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tpPWM);
this.tabControl1.Controls.Add(this.tpUART);
this.tabControl1.Controls.Add(this.tpADC);
this.tabControl1.Location = new System.Drawing.Point(12, 12);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(629, 296);
this.tabControl1.TabIndex = 0;
//
// tpPWM
//
this.tpPWM.Controls.Add(this.lbl_PWM_RPA0);
this.tpPWM.Controls.Add(this.cb_PWM_RPA0);
this.tpPWM.Location = new System.Drawing.Point(4, 22);
this.tpPWM.Name = "tpPWM";
this.tpPWM.Padding = new System.Windows.Forms.Padding(3);
this.tpPWM.Size = new System.Drawing.Size(621, 270);
this.tpPWM.TabIndex = 0;
this.tpPWM.Text = "PWM";
this.tpPWM.UseVisualStyleBackColor = true;
//
// tpUART
//
this.tpUART.Controls.Add(this.cb_UART_RPA0);
this.tpUART.Controls.Add(this.lbl_UART_RPA0);
this.tpUART.Location = new System.Drawing.Point(4, 22);
this.tpUART.Name = "tpUART";
this.tpUART.Padding = new System.Windows.Forms.Padding(3);
this.tpUART.Size = new System.Drawing.Size(621, 270);
this.tpUART.TabIndex = 1;
this.tpUART.Text = "UART";
this.tpUART.UseVisualStyleBackColor = true;
//
// tpADC
//
this.tpADC.Controls.Add(this.lbl_ADC_RPA0);
this.tpADC.Controls.Add(this.cb_ADC_RPA0);
this.tpADC.Location = new System.Drawing.Point(4, 22);
this.tpADC.Name = "tpADC";
this.tpADC.Padding = new System.Windows.Forms.Padding(3);
this.tpADC.Size = new System.Drawing.Size(621, 270);
this.tpADC.TabIndex = 2;
this.tpADC.Text = "ADC";
this.tpADC.UseVisualStyleBackColor = true;
//
// cb_PWM_RPA0
//
this.cb_PWM_RPA0.AutoSize = true;
this.cb_PWM_RPA0.Location = new System.Drawing.Point(17, 65);
this.cb_PWM_RPA0.Name = "cb_PWM_RPA0";
this.cb_PWM_RPA0.Size = new System.Drawing.Size(15, 14);
this.cb_PWM_RPA0.TabIndex = 0;
this.cb_PWM_RPA0.UseVisualStyleBackColor = true;
this.cb_PWM_RPA0.CheckedChanged += new System.EventHandler(this.cb_PWM_RPA0_CheckedChanged);
//
// cb_ADC_RPA0
//
this.cb_ADC_RPA0.AutoSize = true;
this.cb_ADC_RPA0.Location = new System.Drawing.Point(17, 65);
this.cb_ADC_RPA0.Name = "cb_ADC_RPA0";
this.cb_ADC_RPA0.Size = new System.Drawing.Size(15, 14);
this.cb_ADC_RPA0.TabIndex = 1;
this.cb_ADC_RPA0.UseVisualStyleBackColor = true;
this.cb_ADC_RPA0.CheckedChanged += new System.EventHandler(this.cb_ADC_RPA0_CheckedChanged);
//
// lbl_PWM_RPA0
//
this.lbl_PWM_RPA0.AutoSize = true;
this.lbl_PWM_RPA0.Location = new System.Drawing.Point(38, 65);
this.lbl_PWM_RPA0.Name = "lbl_PWM_RPA0";
this.lbl_PWM_RPA0.Size = new System.Drawing.Size(35, 13);
this.lbl_PWM_RPA0.TabIndex = 1;
this.lbl_PWM_RPA0.Text = "RPA0";
//
// lbl_ADC_RPA0
//
this.lbl_ADC_RPA0.AutoSize = true;
this.lbl_ADC_RPA0.Location = new System.Drawing.Point(38, 66);
this.lbl_ADC_RPA0.Name = "lbl_ADC_RPA0";
this.lbl_ADC_RPA0.Size = new System.Drawing.Size(35, 13);
this.lbl_ADC_RPA0.TabIndex = 2;
this.lbl_ADC_RPA0.Text = "RPA0";
//
// lbl_UART_RPA0
//
this.lbl_UART_RPA0.AutoSize = true;
this.lbl_UART_RPA0.Location = new System.Drawing.Point(37, 65);
this.lbl_UART_RPA0.Name = "lbl_UART_RPA0";
this.lbl_UART_RPA0.Size = new System.Drawing.Size(35, 13);
this.lbl_UART_RPA0.TabIndex = 4;
this.lbl_UART_RPA0.Text = "RPA0";
//
// cb_UART_RPA0
//
this.cb_UART_RPA0.AutoSize = true;
this.cb_UART_RPA0.Location = new System.Drawing.Point(16, 65);
this.cb_UART_RPA0.Name = "cb_UART_RPA0";
this.cb_UART_RPA0.Size = new System.Drawing.Size(15, 14);
this.cb_UART_RPA0.TabIndex = 5;
this.cb_UART_RPA0.UseVisualStyleBackColor = true;
this.cb_UART_RPA0.CheckedChanged += new System.EventHandler(this.cb_UART_RPA0_CheckedChanged);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(758, 429);
this.Controls.Add(this.tabControl1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.tabControl1.ResumeLayout(false);
this.tpPWM.ResumeLayout(false);
this.tpPWM.PerformLayout();
this.tpUART.ResumeLayout(false);
this.tpUART.PerformLayout();
this.tpADC.ResumeLayout(false);
this.tpADC.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tpPWM;
private System.Windows.Forms.Label lbl_PWM_RPA0;
private System.Windows.Forms.CheckBox cb_PWM_RPA0;
private System.Windows.Forms.TabPage tpUART;
private System.Windows.Forms.TabPage tpADC;
private System.Windows.Forms.Label lbl_ADC_RPA0;
private System.Windows.Forms.CheckBox cb_ADC_RPA0;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.CheckBox cb_UART_RPA0;
private System.Windows.Forms.Label lbl_UART_RPA0;
}
}
I created a new UserControl which only contains a button.
public partial class TooltipButton : UserControl
{
public TooltipButton()
{
InitializeComponent();
}
public new bool Enabled
{
get { return button.Enabled; }
set { button.Enabled = value; }
}
[Category("Appearance")]
[Description("The text displayed by the button.")]
[EditorBrowsable(EditorBrowsableState.Always)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public override string Text
{
get { return button.Text; }
set { button.Text = value; }
}
[Category("Action")]
[Description("Occurs when the button is clicked.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new event EventHandler Click;
private void button_Click(object sender, EventArgs e)
{
// Bubble event up to parent
Click?.Invoke(this, e);
}
}
I found Serge_Yubenko's code worked on disabled buttons , but in order to stop the flashing make sure the tooltip pops up away from the button - just don't position it half way down the control but do this:
mFormTips.Show(toolTipString, control, control.Width / 2, control.Height);
instead of
mFormTips.Show(toolTipString, control, control.Width / 2, control.Height / 2);
This seems to follow the usual tooltip placement too...
So, I came across this post in my efforts to do the same thing, being the top result on Google. I had already considered the mouse move event and while the answers here did help, they didn't provide me with exactly what I wanted - that being a perfect recreation of the original show tooltip event.
The problem I discovered was this: For whatever reason in the API, ToolTip.Show turns the Mouse Move Event into effectively a Mouse Hover Event. Which is why the tooltip keeps flashing.
The workaround as suggested was to keep the tooltip on always show, or to display the tooltip away from the control, but that wouldn't be a faithful recreation, from the show to the timed fade. The answer would suggest that a block to prevent further execution of the code is needed - the reality was 2 blocks in the event code (One of which has no earthly reason existing and yet without it a timed event fires twice ***), a double delclaration of the control location, one inside the event, one class wide, and another class wide to check if the mouse is over a control, a class wide timer, and a Mouse Leave event to clean up due to too fast mouse movement away from the panel housing the control.
As you will see there are two events on the timer, both functions for them are in the event code as they need to reference variables get/set in the code. They can be moved out, but would then need class wide declarations on the variables, and they cause no harm where they are. FYI: "ToolTips" in the code is referencing the ToolTip control I have on the form.
*** Just to expand. If you look at the code you'll see that IsTipReset could be replaced with IsShown - after all they end up at the same value as each other. The reason for IsTipRest is this: If IsShown is used then while moving the mouse inside the control while the tootip is showing will cause a slight hiccup when the tooltip fades and very very very briefly another tooltip will popup. Using IsTipReset stops that. I have no idea why and maybe someone will spot it because I sure can't! Lol.
This is my first post here, and I realise it is an old thread, but I just wanted to share the fruits of my labour. As I said, my goal was a faithful recreation of tooltip and I think I achieved it. Enjoy!
using Timer = System.Windows.Forms.Timer;
private readonly Timer MouseTimer = new();
private Control? Ctrl;
private bool IsControl = false;
private void TopMenuMouseMove (object sender, MouseEventArgs e) {
Panel Pnl = (Panel)sender;
Control Area = Pnl.GetChildAtPoint (e.Location);
bool IsShown = false;
bool IsTipReset = false;
if (Area != null && Area.Enabled == false && Area.Visible == true) {
Ctrl = Pnl.GetChildAtPoint (e.Location);
Point Position = e.Location;
if (IsControl) { IsShown = true; } else if (!IsControl) { IsControl = true; IsShown = false; }
if (!IsShown) {
MouseTimer.Interval = ToolTips.InitialDelay;
MouseTimer.Tick += new EventHandler (TimerToolTipShow!);
MouseTimer.Start ();
}
void TimerToolTipShow (object sender, EventArgs e) {
if (!IsTipReset) {
MouseTimer.Dispose ();
string Txt = ToolTips.GetToolTip (Ctrl) + " (Disabled)";
Position.Offset (-Ctrl.Left, 16);
ToolTips.Show (Txt, Ctrl, Position);
MouseTimer.Interval = ToolTips.AutoPopDelay;
MouseTimer.Tick += new EventHandler (TimerToolTipReset!);
MouseTimer.Start ();
IsShown = true;
IsTipReset = true;
}
}
void TimerToolTipReset (object sender, EventArgs e) {
if (IsShown) {
MouseTimer.Dispose ();
IsShown = false;
ToolTips.Hide (Ctrl);
}
}
}
else if (Area == null) {
if (Ctrl != null) {
MouseTimer.Dispose ();
IsShown = false;
IsControl = false;
ToolTips.Hide (Ctrl);
Ctrl = null;
}
}
}
private void TopMenuMouseLeave (object sender, EventArgs e) {
if (Ctrl != null) {
MouseTimer.Dispose ();
IsControl = false;
ToolTips.Hide (Ctrl);
Ctrl = null;
}
}