简体   繁体   中英

Clickable control inside draggable control

I have a draggable control (A), within it is a button. There are also other controls within A, ie the button does not fill A.

In order to manage the drag functionality, the control (A) captures any MouseDown events. It later decides whether to start a drag based on how far the mouse has moved.

If the button was clicked, and then a MouseUp event is received before a drag has been started, I'd like the button's Click event to fire.

At the moment, this doesn't happen because the MouseUp event is captured by the parent control (A). I could implement functionality on A to manually handle this:

private void MouseUp(object sender, MouseEventArgs e) {
    if (DragHasStarted) {
        DealWithDrag();
    }
    else {
        DelegateToChildControls();
    }
}

However that's complicated and doesn't scale well since DelegateToChildControls needs to work out which child to delegate to.

Is there a way to let Windows deal with this and call the button's Click method directly if the parent control doesn't handle the MouseUp event?

Edit - More detail on event sequence:

I see the following sequence of events when the button is clicked:

  1. MouseDown on Button
  2. MouseDown on Button (Drag handler)
  3. I forward this to parent of button
  4. MouseDown on parent (Drag handler)
  5. Mouse Captured by parent (Drag handler)
  6. MouseUp on parent
  7. End drag (drag handler)

I never see a MouseUp event on the button.

I don't know what kind of Control as a container you are using, because I've tested with a UserControl and I can interact with all the children of my UserControl , however if you are interested in clicking on the children only, I have this solution:

[DllImport("user32")]
private static extern IntPtr WindowFromPoint(POINT point);
[DllImport("user32")]
private static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
struct POINT
{
  public int x, y;
}
private void MouseUp(object sender, MouseEventArgs e){
   if(DragHasStarted){
      DealWithDrag();
   }
   else {
      Point screenLocation = PointToScreen(e.Location);
      IntPtr childHandle = WindowFromPoint(new POINT{x=screenLocation.X,y=screenLocation.Y });
      if(childHandle != IntPtr.Zero){
         SendMessage(childHandle, 0x201, IntPtr.Zero, IntPtr.Zero);
         SendMessage(childHandle, 0x202, IntPtr.Zero, IntPtr.Zero);
      }
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM