C#: Temporarily capture OnClick event in parent control - c#

I have a Windows Forms application and I want to be able to show a 'post-it note' type thing when the user does a specific action.
For example: The user does something which automatically hides a control.
My application should:
o Pop up a post it note which explains what happened.
o Hide the post it note again when the user clicks anywhere on the form.
I have implemented the post it note as a simple panel with a label in it, which shows and hides when specific things happen.
However, I can't seem to capture the OnClick event of the parent UserControl. The parent control is a nested control, containing a split container, one side of which contains the panel and a tab control, each of which contains a user control with various things in it.
Apart from handling the click event of every single child control, can anyone think of an event that I can capture on the parent control that I can use to hide the post it note when the user clicks anywhere in the parent control?
Thanks,
Rik

That's what the Capture property was designed to do. Set it to true when you pop up the note. Any mouse events will now be directed to your control, even if the mouse moves outside of the window. This is also the way that, for example, the combobox dropdown list works. Keep in mind that it is only good for one click.
If the popup contains any controls itself then mouse capture isn't the solution. Make it an owned form instead and simply call Close() in an event handler for the Deactivate event.

There is bubling of events in windows form, while you click on child event, the event is raised for child, and then for parent. Unless you specify "handleEvnet" property to true. So just leave it false, untill event reaches parent.

Related

How to send mousedown message to a component or control?

Is there a way to send message (like mousedown) to a control?
My purpose is that when you click GridView, prevent mousedown behavior itself and bypass mousedown message to RepositoryItem.
From your question: "My purpose is that when you click GridView, prevent mousedown behavior itself and bypass mousedown message to RepositoryItem."
It sounds like you want to control the behavior of the Mouse Down event on the control. Right?
If that's the case, on the Winforms designer, look at the properties panel. On there is also a selection for the form events for a control. You can scroll down and find the Mouse Down event and add an event handler. Then do whatever filtering you need including not even processing the message at all.
You also mentioned that it's a DevExpress control. I recall that some of their controls were wired up a little differently so the DevExpress website might have some additional clues.

How to determine if User Control is shown or not on WinForms

I have a windows forms application and added a menu to maneuver between few User Controls. I am using the events: Click, MouseEnter and MouseLeave.
In every event I am changing the BackgroudImage and what i want to achieve is that when the image did change after the click event, the image will stay. And I was thinking using the User Control properties to determine if he is Shown or not (as I am using the Show() and Hide() methods).
Tried using the Visible, Focused and Enabled properties but none of them changing after hiding or showing the User Control.
How can i determine if the User Control is shown or not?
The property IsHandleCreated gets true when the control is loaded. Try to use this property.
reference document :https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.ishandlecreated?view=netframework-4.7.2
Apparently when the form loaded, the default Visible property is set to True even though I really don’t see all of the User Controls (they are one on each other).
So I added a show and hide method in the form load event and the visible property works like a Charm.
Thank Franck

Raising event from custom control added dynamically to the form

I have a custom control that can be added multiple times to a form. There can be multiples occurrences of this custom control on the same form. These controls are added and removed by the user. The user can right click on some control inside the custom control to reveal a menu.
When selecting an item from this menu, an event should be raised on the form. I made a custom event and realized that it could't be usable if the control was added dynamically, because the form doesn't know it. I can't add an event handler referring to a control that doesn't exist. Is there some other way to raise an event on the form from custom control that doesn't require the form to know it? By the way, my custom controls are added to a FlowLayoutPanel.
Thanks for the help!
You just wire up the event handler in the code when you add the control e.g.
MyButton.Click += ButonClickEventHandler;
Page.Controls.Add(MyButton)
Agree with Ben - otherwise, there are messy ways of doing it (depending on how your control is set up). For example INotifyPropertChanged Inerface or through Windows API messaging (and listener) - but unless you have a very strange set up, then as Ben said, simply add a handler when you add the control. You can always use a generic callback method and use custom event args to identify which has triggered it.

How does a ComboBox capture mouse when it is dropped-down?

I am trying to model the behavior of a ComboBox dropdown (or other drop downs for that matter, including context menus) where the drop down closes when you click anywhere else, even on something that can't be focused.
I've tried subscribing for events such as MouseCaptureChanged, LostFocus, and Leave. I have a custom UserControl which is acting as a dropdown and I just want to close it up when the user clicks anywhere else.
This seems like something that's done in many controls so I'd be surprised if there wasn't a simple way to do it.
So far the overcomplicated methods I can come up with to do this are using pinvoke and the SetCapture() function, or to create a MessageFilter. If these are the only options I am not sure which is better.
The ComboBox is constructed from 2 controls.
Base - visible when not active (Control)
DropDownList - visible during edit mode or list selection mode (Window or Form)
Normally the Base is visible. When the user clicks onto the ComboBox, the Base control hides and the DropDownList control shows up. This switch is done on the background, so for the user it seems the control just expanded.
The event you want to catch is done through the DropDownList Window. If you click somewhere onto your client area, the DropDownList Window receives the WM_KILLFOCUS event through it's WndProc(Message% m) method. Then sends to the parent window (the Base control) a WM_COMMAND (OCM_COMMAND) message with WParam=526318 (HIWORD(WParam)=8) and the Base control knows he should hide the DropDownList Window.
So, what you need to do is implement the additional DropDown Window and catch the WM_KILLFOCUS event.
The templates of the controls you've mentioned are using for the dropdown lists a popup as a container with the StaysOpen property set on false (which is the default i think).
ComboBox template example

Handling selected objects on the GUI in WPF

I've built several user controls in WPF and they all get added to a canvas. I want to add a behaviour that keep tracks of the currently selected usercontrol. A usercontrol should be selected when:
The mouse clicks on it;
when it recieve focus;
when either of the two above happens to a subcontrol of the usercontrol.
Is there any way to handle this purely by using the focus mechanism of WPF or will I need to take care of this myself with assistance of the focus classes?
I've read up upon the new way of handling focus in WPF, and the problem I'm facing is that the keyboard focus determines what the currently selected object is, but some parts of the my control can't recieve keyboard focus so even though these parts are clicked, the usercontrol doesn't recieve focus.
I'm looking for advice on how to implement this feature and how much I could/should rely on the focus mecanisms. Ultimatively I wouldn't mind if only a single object could be selected, but if it's easily extendable to multi-select then I wouldn't mind this either.
Just to clarify, I know I could build this manually by handling a lot of events and keeping track of states, but I was just hoping an easier approach was available.
Combine UIElement.IsKeyboardFocusWithin with a PreviewMouseDown handler:
When PreviewMouseDown is called, set a flag and schedule callback using Dispatcher.BeginInvoke at DispatcherPriority.Input to set focus to the UserControl if the flag is still set.
Set a handler for UIElement.IsKeyboardFocusWithin property changes in your UserControl. When the handler fires, clear the flag.
The idea here is that if you click anywhere on the UserControl and keyboard focus does not result in the focus being moved into the UserControl, force it into the UserControl.
FYI, here's roughtly what step 1 looks like in code:
public override OnPreviewMouseDown(MouseButtonEventArgs e)
{
_mouseClickedButNoFocus = true;
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
if(_mouseClickedButNoFocus)
Focus();
});
}
You could use the UIElement.IsKeyboardFocusWithin property, which is true when the UIElement or one of its children has keyboard focus. It is a dependency property, so you can easily use it for a trigger in a style
You can set the logical focus to the control when any of the child gets the keyboard focus using FocusManager.IsFocusScope="True". Setting the keyboard focus to the control or trying to do will eat the keys for the child controls.
You can use UIElement.IsKeyboardFocusWithin to set the focus of the control if any of the children has focus.
You can read this article which I think describes the difference between Logical and Keyboard focus quite well:
http://www.pluralsight.com/community/blogs/eburke/archive/2009/03/18/why-is-focus-in-wpf-so-tricky-managing-and-understanding-focus-in-a-wpf-application.aspx

Categories