Is there a way to determine if the mouse is within the LinkArea of a LinkLabel control in C#?
Any help would be greatly appreciated.
You can use Mouse Enter Event
linkLabel1.MouseEnter += new EventHandler(linkLabel1_MouseEnter);
private void linkLabel1_MouseEnter(object sender, EventArgs e)
{
MessageBox.Show("Mouse is within link area");
}
This cannot be done. The MouseEnter event suggested in the other answer at the time of this writing will fire any time the mouse enters the control area, regardless of whether it is actually over link text or not.
If your LinkLabel control's boundaries are small relative to its content, then the MouseEnter event may work well enough. But in the case where (for example) you want your link to change color when the mouse hovers over the link text and there is a lot of area within the control around the text, then this approach will not work.
On a somewhat unrelated note, this also prevents you from detecting which link within the LinkLabel is currently being hovered over if you have multiple, as mentioned here.
One more detail in case anybody is wondering: the LinkLabel.LinkArea property is not what you are looking for, either. That only determines which characters within the LinkLabel are actually part of a link, and not the actual area they occupy onscreen.
To wrap up, the only way you may be able to get the functionality you are looking for is to implement your own custom control which behaves similarly to the Label or LinkLabel control, but adds the methods and/or properties that you need.
Since the original LinkLabel has a protected function PointInLink this is not hard to do:
using System;
using System.Windows.Forms;
namespace MyControlNameSpace
{
/// <summary>
/// Data for a HoveredLinkChanged-Handler.
/// </summary>
public class HoveredLinkChangedEventArgs : EventArgs
{
private readonly LinkLabel.Link m_Link;
/// <summary>
/// Creates data for a HoveredLinkChanged-Handler
/// </summary>
/// <param name="link">the Link, with the mouse pointer over it</param>
public HoveredLinkChangedEventArgs(LinkLabel.Link link)
{
m_Link = link;
}
/// <summary>
/// Returns the hovered Link
/// </summary>
public LinkLabel.Link HoveredLink
{
get { return m_Link; }
}
}
/// <summary>
/// The structure of a HoveredLinkChanged-Handler
/// </summary>
public delegate void HoveredLinkChangedEventHandler(
object sender, HoveredLinkChangedEventArgs e);
/// <summary>
/// Adds to LinkLabel the possiblity to react on changes
/// of the hovered Link (e.g. to alter a TooltipText).
/// </summary>
public class LinkLabelEx : LinkLabel
{
private Link m_HoveredLink;
/// <summary>
/// Occurs, when another Link is hovered.
/// </summary>
public event HoveredLinkChangedEventHandler HoveredLinkChanged;
/// <summary>
/// Raises the HoveredLinkChanged event
/// </summary>
/// <param name="hoveredLink">the hovered Link</param>
protected virtual void OnHoveredLinkChanged(Link hoveredLink)
{
if (HoveredLinkChanged != null)
HoveredLinkChanged(this,
new HoveredLinkChangedEventArgs(hoveredLink));
}
/// <summary>
/// Raises the Control.OnMouseMove(MouseEventArgs) event.
/// </summary>
/// <param name="e">a MouseEventArgs containing the event data</param>
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
Link currentLink = PointInLink(e.X, e.Y);
if (Equals(currentLink, m_HoveredLink)) return;
m_HoveredLink = currentLink;
OnHoveredLinkChanged(m_HoveredLink);
}
}
}
Then there are only two things left to do:
Add an eventhandler to your LinkLabelEx, e.g.:
linkLabelEx1.HoveredLinkChanged += linkLabelEx1_HoveredLinkChanged;
Set the tooltiptext according to the link given in the eventArgs, e.g.:
void linkLabelEx1_HoveredLinkChanged(object sender, HoveredLinkChangedEventArgs e)
{
string ttt = e.Link == null
? string.Empty
: e.Link.Description;
toolTip1.SetToolTip((Control)sender, ttt);
}
Related
Im having a UIManager class, that is static. In this class, I tried to make functions that I can call wherever I want, and they shows or hides the UI elements of which name i gave it to the function.
My class looks like this:
public static class UIManager
{
//If you deactivate a gameobject at the Editor, you cant activate it later. This is where UI handler comes in.
//It hides or shows the UI elements the game has
/// <summary>
/// Shows the UI element of the given name
/// </summary>
/// <param name="name"></param>
public static void ShowUIElement(string name)
{
GameObject.Find(name).SetActive(true);
}
/// <summary>
/// Shows the UI Elements that are in the array
/// </summary>
/// <param name="names"></param>
public static void ShowUIElement(params string[] name)
{
foreach (var item in name)
{
GameObject.Find(item).SetActive(true);
}
}
/// <summary>
/// Hides the UI element of the given name
/// </summary>
public static void HideUIElement(string name)
{
GameObject.Find(name).SetActive(false);
}
/// <summary>
/// Hides the UI Elements that are in the array
/// </summary>
/// <param name="name"></param>
public static void HideUIElement(params string[] name)
{
foreach (var item in name)
{
GameObject.Find(item).SetActive(false);
}
}
Somehow it is not working. Maybe if I deactivate a UI element, I can't activate it, because it does not exist anymore. In Unity, the UI elements has a ".enabled" property that is changeable, but I have to know what type of UI element (button, text, panel, canvas) is, to make it disabled. This is my problem. I need a generic solution for all type of UI element, so for the function, I just pass the name of the UI element that i need to activate or deactivate, plus the type of it, so I dont have to make a function for every UI element type. Can you help me?
If you need to enable or disable components, then you can use Behaviour class, because all components that can be enabled or disabled derives from it. This can be applied to all components, not only UI.
private Image image;
private Button button;
private Text text;
private Canvas canvas;
private void Start()
{
DisableUIElement(image);
DisableUIElement(button);
DisableUIElement(text);
DisableUIElement(canvas);
}
void DisableUIElement(Behaviour uiElement)
{
uiElement.enabled = false;
}
But don't use find by name, it is very slow. Make references to your elements and pass them.
Does anyone have an idea how I can disable Drag & Drop for all my TextBox Elements?
I found something here, but that would need me to run a loop for all Elements.
Use the following after InitializeComponent()
DataObject.AddCopyingHandler(textboxName, (sender, e) => { if (e.IsDragDrop) e.CancelCommand(); });
You can easily wrap what this article describes into a attached property/behaviours...
ie. TextBoxManager.AllowDrag="False" (For more information check out these 2 CodeProject articles - Drag and Drop Sample and Glass Effect Samplelink text)
Or try out the new Blend SDK's Behaviors
UPDATE
Also read this article by Bill Kempf about attached behaviors
And as kek444 pointed out in the comments, you then just create a default style for textbxo whit this attached property set!
Personally I created a custom TextBox control that does not allow drag as follows:
/// <summary>
/// Represents a <see cref="TextBox"/> control that does not allow drag on its contents.
/// </summary>
public class NoDragTextBox:TextBox
{
/// <summary>
/// Initializes a new instance of the <see cref="NoDragTextBox"/> class.
/// </summary>
public NoDragTextBox()
{
DataObject.AddCopyingHandler(this, NoDragCopyingHandler);
}
private void NoDragCopyingHandler(object sender, DataObjectCopyingEventArgs e)
{
if (e.IsDragDrop)
{
e.CancelCommand();
}
}
}
Instead of using TextBox use local:NoDragTextBox where "local" being the alias to the location of the NoDragTextBox assembly. The same above logic also can be extended to prevent Copy/Paste on TextBox .
For more info check the reference to the above code at http://jigneshon.blogspot.be/2013/10/c-wpf-snippet-disabling-dragging-from.html
Create your owner user control ex MyTextBox: TextBox and override:
protected override void OnDragEnter(DragEventArgs e)
{
e.Handled = true;
}
protected override void OnDrop(DragEventArgs e)
{
e.Handled = true;
}
protected override void OnDragOver(DragEventArgs e)
{
e.Handled = true;
}
I want to create costume Gridview. I found very nice open source one but the problem is that it uses DataGrid and when I change the inherited class to GridView, I get the following error
AADGridView.OnItemDataBound(DataGridItemEventArgs
e):not suitable method found to override
I have override here :
//public class AADGridView : DataGrid, IPostBackEventHandler
public class AADGridView : GridView, IPostBackEventHandler
{
/// <summary>
/// Gets or sets a value that indicates whether the auto filter is displayed in the AADGrid.AADGridControl.
/// </summary>
[Bindable(true), Category("Appearance"), Description("Whether to show the control's auto filter."), DefaultValue(true),]
/// <summary>
/// Override the DataGrid constructor.
/// </summary>
public AADGridView() : base()
{
// create the ArrayList to contain the DropDownList controls and the SortedList objects added to the header items;
//list = new ArrayList();
sort = new ArrayList();
filter = true;
}
/// <summary>
/// Override the OnItemDataBound event.
/// </summary>
/// <param name="e"></param>
override protected void OnItemDataBound(DataGridItemEventArgs e)
{
//Some Code
base.OnItemDataBound(e);
}
as you see in the code, I just change DataGrid to GridView. Both of them has OnItemDataBound,So whats the problem?
Thanks
The event arguments are of type DataGridItemEventArgs. You have to change the parameter type to the new base class' parameter.
I need to create a Windows Form application that able to send data and to receive data from another Form instance. what mean, the Form is a publisher and a subscriber, both of them.
Unfortunately, I was sick that day, and I couldn't be in the lecture that day.
I'll explain again:
I have a small chat Form,
who have: new Instance button, received messages, and send message.
as you can see right below:
When I send a message, it will be shown in the "Recieved" textbox of ALL INSTANCES.
I guess that I need to use delegates and events.
How to do so? thanks!!
Here's a quick solution.. Let me know if you have any questions or if you find the comments confusing..
Here's the Form class (code behind). Notice that once the form is instantiated, it "subscribes" to an event by "wiring" an event handler to the HandleMessage event inside the Message class. Within the Form class, this is where the ListView's item collection is populated.
Whenever the New Form button is clicked, the same Form get's created and displayed (this allows for code re-use, since the same logic will be exactly the same for all instances of the Form)
public partial class Form1 : Form
{
Messages _messages = Messages.Instance; // Singleton reference to the Messages class. This contains the shared event
// and messages list.
/// <summary>
/// Initializes a new instance of the <see cref="Form1"/> class.
/// </summary>
public Form1()
{
InitializeComponent();
// Subscribe to the message event. This will allow the form to be notified whenever there's a new message.
//
_messages.HandleMessage += new EventHandler(OnHandleMessage);
// If there any existing messages that other forms have sent, populate list with them.
//
foreach (var messages in _messages.CurrentMessages)
{
listView1.Items.Add(messages);
}
}
/// <summary>
/// Handles the Click event of the buttonNewForm control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void buttonNewForm_Click(object sender, EventArgs e)
{
// Create a new form to display..
//
var newForm = new Form1();
newForm.Show();
}
/// <summary>
/// Handles the Click event of the buttonSend control. Adds a new message to the "central" message list.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void buttonSend_Click(object sender, EventArgs e)
{
string message = String.Format("{0} -- {1}", DateTime.UtcNow.ToLongTimeString(), textBox1.Text);
textBox1.Clear();
_messages.AddMessage(message);
}
/// <summary>
/// Called when [handle message].
/// This is called whenever a new message has been added to the "central" list.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
public void OnHandleMessage(object sender, EventArgs args)
{
var messageEvent = args as MessageEventArgs;
if (messageEvent != null)
{
string message = messageEvent.Message;
listView1.Items.Add(message);
}
}
}
Here's a Messages class that I created to handle a "central" list of messages that are sent between Forms. The Messages class is a singleton (meaning, it can be instantiated only once), which allow one list to be persisted throughout all instances of a Form. All Forms will share the same list, and get notified whenever a list has been updated. As you can see, the "HandleMessage" event is the Event that each Form will subscribe to whenever it has been created/shown.
If you take a look at the NotifyNewMessage function, this is called by the Messages class to notify the subscribes that there was a change. Since EventArgs are used to pass data to the subscribers, I've created a special EventArgs to pass the newly added messages to all subscribers.
class Messages
{
private List<string> _messages = new List<string>();
private static readonly Messages _instance = new Messages();
public event EventHandler HandleMessage;
/// <summary>
/// Prevents a default instance of the <see cref="Messages"/> class from being created.
/// </summary>
private Messages()
{
}
/// <summary>
/// Gets the instance of the class.
/// </summary>
public static Messages Instance
{
get
{
return _instance;
}
}
/// <summary>
/// Gets the current messages list.
/// </summary>
public List<string> CurrentMessages
{
get
{
return _messages;
}
}
/// <summary>
/// Notifies any of the subscribers that a new message has been received.
/// </summary>
/// <param name="message">The message.</param>
public void NotifyNewMessage(string message)
{
EventHandler handler = HandleMessage;
if (handler != null)
{
// This will call the any form that is currently "wired" to the event, notifying them
// of the new message.
handler(this, new MessageEventArgs(message));
}
}
/// <summary>
/// Adds a new messages to the "central" list
/// </summary>
/// <param name="message">The message.</param>
public void AddMessage(string message)
{
_messages.Add(message);
NotifyNewMessage(message);
}
}
/// <summary>
/// Special Event Args used to pass the message data to the subscribers.
/// </summary>
class MessageEventArgs : EventArgs
{
private string _message = string.Empty;
public MessageEventArgs(string message)
{
_message = message;
}
public String Message
{
get
{
return _message;
}
}
}
Also.. in order for the messages to be "displayed" correctly, don't forget the set the "View" property of the ListView control to "List". An easier (and preferred way) would simply be using the ObservableCollection list type, which already provides an event you can subscribe to.
Hope this helps.
I am visiting some old code, and there are quite a few events declared with delegates manually rather than using EventHandler<T>, like this:
/// <summary>
/// Delegate for event Added
/// </summary>
/// <param name="index">Index of the item</param>
/// <param name="item">The item itself</param>
public delegate void ItemAdded(int index, T item);
/// <summary>
/// Added is raised whenever an item is added to the collection
/// </summary>
public event ItemAdded Added;
All well and good, until I come to use sandcastle to document the library, because it then can't find any XML comments for the private Added field that is generated by the event declaration. I want to try and sort that out, but what I would like to do is either:
Get sandcastle to ignore the auto-generated private field without telling it to ignore all private fields entirely
or
Get XML comments generated for the private field
Is there any way of achieving this without re-factoring the code to look like this:
/// <summary>
/// Delegate for event <see cref="Added"/>
/// </summary>
/// <param name="index">Index of the item</param>
/// <param name="item">The item itself</param>
public delegate void ItemAdded(int index, T item);
/// <summary>
/// Private storage for the event firing delegate for the <see cref="Added"/> event
/// </summary>
private ItemAdded _added;
/// <summary>
/// Added is raised whenever an item is added to the collection
/// </summary>
public event ItemAdded Added
{
add
{
_added += value;
}
remove
{
_added -= value;
}
}
Although sub-optimal, I found a way around this, which was to manually put the XML comments into the file that contains namespace-level documentation for the project, along these lines:
<member name="F:myCompany.Common.Collections.Generic.EventableCollection`1.Added">
<summary>
Auto-generated backing field for the <see cref="E:myCompany.Common.Collections.Generic.EventableSortedList`1.Added">Added</see> event
</summary>
</member>
This then gives roughly what I needed.