Adding Click Handler On UserControl Breaks Click On Children - c#

I have a user control that I'm trying to make draggable. The whole control should be draggable except when you click on buttons or text boxes. I'm handling the mousedown, mouseup and mousemove events on the usercontrol itself and I can drag by clicking anywhere. The only issue is now I can't click any buttons on the user control. Any clue what's going on?
Code is something like this:
<UserControl PreviewMouseLeftButtonDown="Popup_PreviewMouseLeftButtonDown" ....STUFF...>
<!-- CAN'T CLICK THIS -->
<Button />
<UserControl>
Code Behind:
public void Popup_PreviewMouseLeftButtonDown(object sender, MouseEventArgs e)
{
mouseDown = true;
oldMousePosition = this.PointToScreen(e.GetPosition(this));
this.Popup.Child.CaptureMouse();
}

The issue arises when you use CaptureMouse() - this permanently captures all your mouse input on the window, and makes it so that you're unable to click on anything within the Window. I don't know if it's different for you, or if you checked, but it's not (just) that the Button is unclickable - it's that literally everything on the Window is unclickable.
You have to actually do something with the mouse after you've captured it, and then once you finish that, you have to return normal control by calling Mouse.Capture(null). For you, this would probably be best to do in your MouseUp() method.
However, this still leaves the child problem. I can't really think of any way you're going to be able to both capture all mouse click events on a parent control and allow them to get to the child control. I suppose you could check the mouse position against the button position, both relative to the UserControl, then route the click event to the Button every time, but this seems a little overelaborate. Is there a reason you can't just add a full-sized Grid to the UserControl with a lower ZIndex than the Button, and just use that to detect if a click was made inside the UserControl but not on the Button?

Related

c# Prevent dragging box over another

I am using visual studio. In my program I have the option for a user to activate certain widgets that they want to have. Each widget is a UserControl, so when they click to show a widget, it is activating the corresponding user control. Once they activate the control, they can drag the boxes wherever they wish so that they can customize how their screen looks. However, whenever you drag one widget over another, it just stacks them on top of each other, and this is not what I want. If I am dragging a box and it touches another one, I want it to stop and not be able to overlap it. How can I do this? I suspect it has something to do with the "DragOver" event, but not for sure.
The DragOver event will be raised on these case :
[+] If the user moves out of a window, the DragLeave event is raised.
[+] If the mouse enters another control, the DragEnter for that control is raised.
[+]If the mouse moves but stays within the same control, the DragOver event is raised.
If this is the event that you want, so try to terminate the widget (User Control) on UserControl_DragOver.
You can terminate your UserControl like this :
private void Btn_Cancel_Click(object sender, EventArgs e)
{
this.Parent.Controls.Remove(this);
}
(If you mean sth else, tell in comment)

Click on form does not click underlying control

I have a windows forms application. When I click on a window this activates the form and then I need to click again to call the particular control click event. For example if I click on a button this activates the form and then I need to click the button again.
Is there a way to perform the control click and window activation in one click? Preferably I would want this to work with whatever the clickable control is (menu,button, label etc)
So far I have managed to activate the win form on mouse over and then the control click works. I would like to have the win form activated on click and also run the click command on an underlying control if this has a click event.
Well, here's a way to accomplish what You want (just attach a similar method to Your from's MouseClick event):
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
var c = this.GetChildAtPoint(e.Location);
this.InvokeOnClick(c, e);
}
This method has it's drawbacks though - for example the control will be clicked even though it's disabled etc., so You have to make sure the control under the cursor is "clickable" by yourself...

WinForms Event Parent scroll

I have two FlowLayoutPanels on a form: PanelA and PanelB. Each will be populated at run-time with multiple controls, such that the panel will scroll (i.e AutoScroll is true).
Here's the issue: The controls that the panels are populated with each contain a ComboBox. Thus, MouseWheel events are consumed by the combo box instead of by the panel. I want MouseWheel events to be consumed by the panel.
If there's no scrollable control on the child controls, then the MouseWheel event skips the child control (which doesn't handle it) and hits the panel, which does handle it. How can I set my child control's combo box to ignore the MouseWheel event? Can I tell it to re-raise the event?
I tried just applying Focus to the Parent whenever one of the child controls ticks the 'MouseEnter' event; this fixed the scrolling issues, but also left the child controls completely un-editable.
Something else I've found from digging around involves fiddling with the Windows API directly, but I find it hard to believe that something like that is required for this.
I tested the following code and it seems like a solution to your issue. Basically you need to focus the 'FlowLayoutPanel' when you click on it, or your mouse enters it:
private void newCheckListQuestionPanel_Click(object sender, EventArgs e)
{
newCheckListQuestionPanel.Focus(); //allows the mouse wheel to work after the panel is clicked
}
private void newCheckListQuestionPanel_MouseEnter(object sender, EventArgs e)
{
newCheckListQuestionPanel.Focus(); //allows the mouse wheel to work after the panel has had the mouse move over it
}
Source

Moving button stops click event happening

I have a button, contained in a panel, with a click event, that works fine. However when a users presses another button, I need to move this button into another panel (this is actually a panel with a modalpopupextender), so I this code to do so:
newPanel.Controls.Add(buttonPanel)
It all get's moved and looks fine. However now when the button is clicked it doesn't fire the associated event. I have tried re-adding the event in the page_init, with this code
((Button)this.FindControl("serverModalSave")).Command += new CommandEventHandler(modalSave_Click);
But with no luck. How can I get this button to fire it's click event when moved, and why does it stop working when it's moved?
EDIT:
This Button needs to be added to a panel specified by the user at run time, so there is not a way to determine where the button will go in advance.
I could instead of moving this button, create a new one, but because this button is not created in the page_init I am having issues getting that to fire an event either.
Instead of moving the button, have another button on the other panel set to hidden.
Hide the button you wanted to move and show the hidden one when needed.
Moving the control changes the naming hierarchy and now the button can't be found and the click event can't fire.
This is due to how the page life cycle works. Here is a good (if somewhat dated) article about how view state works - if you understand this, you will understand what went wrong.
If you are creating the button in the new panel, when this button is then clicked do you re-create it in the postback ?
You must re-create all controls on each postback see here

How to get system tray functionality WITHOUT using NotifyIcon.ContextMenu?

I'm trying to get my application to display a popup context menu when a user right-clicks on my notify icon in the system tray... but there's a twist.
I'm aware that the NotifyIcon class I'm using to get the icon in the system tray has a ContextMenu property. I don't want to use that to get a right-click popup menu, because it ALWAYS displays a right-click popup menu, and never does anything else. When my main form is displaying a modal dialog, I want right-click to activate the main form, NOT display a popup menu.
So, I'm guessing I need to use the NotifyIcon.MouseClick event, and manually pop up the menu in that event? Here's where I've got to so far:
private NotifyIcon trayIcon;
private ContextMenu iconMenu;
private void frmMain_Load(object sender, EventArgs e) {
// [...]
this.trayIcon.MouseClick += new MouseEventHandler(trayIcon_MouseClick);
iconMenu = new ContextMenu();
// [...]
}
private void trayIcon_MouseClick(object sender, MouseEventArgs ea) {
this.iconMenu.Show(Program.instanceFrmMain, new Point(System.Windows.Forms.Cursor.Position.X - Program.instanceFrmMain.Left, System.Windows.Forms.Cursor.Position.Y - Program.instanceFrmMain.Top));
}
Notice how in iconMenu.Show, because it takes popup co-ordinates relative to the parent control (my main form here), I'm annoyingly having to subtract the parent control's co-ordinates from popup co-ordinates, something I already don't want to have to do.
Apart from that, here are the problems I'm having:
Although the menu does popup on right-click, it doesn't close if I click somewhere else on the screen outside the menu - and it should.
The menu doesn't quite popup in the right location; for other system tray apps, it pops up so its bottom-right or bottom-left corner are at the tip of the mouse cursor. For mine, the popup menu is at the base of the screen, to the side of the mouse cursor.
Any ideas how I can get this to work better? I know it's possible, plenty of other apps manually handle the displaying of a popup menu manually instead of using some NotifyIcon.ContextMenu property.
Use the ContextMenuStrip property rather than ContextMenu. The ContextMenuStrip class has an Opening event, which you can cancel by setting e.Cancel = true. That way you don't have to worry about the location of the menu, since it is automatically handled
OK, well I didn't manage to get the functionality I wanted as I described in the original question, but I have managed to find a way to achieve the desired effect using a different method.
I DO attach a ContextMenu to the trayIcon.ContextMenu property, but I attach event handler code to the Popup property of the context menu itself. If, in that handler, I .Clear the ContextMenu, it actually doesn't appear at all, allowing my code to elect to effectively stop the trayicon's popup menu from showing if it wants to. This was the effect I was looking to achieve. If I populate the ContextMenu in the Popup event handler code instead, the menu pops up as usual containing what I populated it with.
Sooo, I managed to solve the problem a different way. :-)

Categories