Al hacer clic en el botón central del mouse (también conocido como: rueda del mouse) y luego mover el mouse hacia abajo, permite a los usuarios desplazarse en IE y en la mayoría de las aplicaciones de Windows. Este comportamiento parece faltar en los controles de WPF por defecto? ¿Hay alguna configuración, una solución alternativa o algo obvio que me falta?¿Cómo puedo hacer que WPF ScrollViewer haga clic con el botón central del mouse?
Respuesta
He encontrado cómo lograr esto usando 3 eventos de mouse (MouseDown
, MouseUp
, MouseMove
). Sus manejadores están unidos al elemento ScrollViewer
en el xaml a continuación:
<Grid>
<ScrollViewer MouseDown="ScrollViewer_MouseDown" MouseUp="ScrollViewer_MouseUp" MouseMove="ScrollViewer_MouseMove">
<StackPanel x:Name="dynamicLongStackPanel">
</StackPanel>
</ScrollViewer>
<Canvas x:Name="topLayer" IsHitTestVisible="False" />
</Grid>
Sería mejor escribir un comportamiento en lugar de los acontecimientos en código subyacente, pero no todos tienen la biblioteca necesaria, y también no hacer saber cómo conectarlo con el Canvas
.
Los controladores de eventos:
private bool isMoving = false; //False - ignore mouse movements and don't scroll
private bool isDeferredMovingStarted = false; //True - Mouse down -> Mouse up without moving -> Move; False - Mouse down -> Move
private Point? startPosition = null;
private double slowdown = 200; //The number 200 is found from experiments, it should be corrected
private void ScrollViewer_MouseDown(object sender, MouseButtonEventArgs e)
{
if (this.isMoving == true) //Moving with a released wheel and pressing a button
this.CancelScrolling();
else if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Pressed)
{
if (this.isMoving == false) //Pressing a wheel the first time
{
this.isMoving = true;
this.startPosition = e.GetPosition(sender as IInputElement);
this.isDeferredMovingStarted = true; //the default value is true until the opposite value is set
this.AddScrollSign(e.GetPosition(this.topLayer).X, e.GetPosition(this.topLayer).Y);
}
}
}
private void ScrollViewer_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Released && this.isDeferredMovingStarted != true)
this.CancelScrolling();
}
private void CancelScrolling()
{
this.isMoving = false;
this.startPosition = null;
this.isDeferredMovingStarted = false;
this.RemoveScrollSign();
}
private void ScrollViewer_MouseMove(object sender, MouseEventArgs e)
{
var sv = sender as ScrollViewer;
if (this.isMoving && sv != null)
{
this.isDeferredMovingStarted = false; //standard scrolling (Mouse down -> Move)
var currentPosition = e.GetPosition(sv);
var offset = currentPosition - startPosition.Value;
offset.Y /= slowdown;
offset.X /= slowdown;
//if(Math.Abs(offset.Y) > 25.0/slowdown) //Some kind of a dead space, uncomment if it is neccessary
sv.ScrollToVerticalOffset(sv.VerticalOffset + offset.Y);
sv.ScrollToHorizontalOffset(sv.HorizontalOffset + offset.X);
}
}
Si para eliminar el método llama AddScrollSign
y RemoveScrollSign
este ejemplo va a funcionar. Pero he ampliado con 2 métodos que establecen icono de desplazamiento:
private void AddScrollSign(double x, double y)
{
int size = 50;
var img = new BitmapImage(new Uri(@"d:\middle_button_scroll.png"));
var adorner = new Image() { Source = img, Width = size, Height = size };
//var adorner = new Ellipse { Stroke = Brushes.Red, StrokeThickness = 2.0, Width = 20, Height = 20 };
this.topLayer.Children.Add(adorner);
Canvas.SetLeft(adorner, x - size/2);
Canvas.SetTop(adorner, y - size/2);
}
private void RemoveScrollSign()
{
this.topLayer.Children.Clear();
}
ejemplo de iconos:
Y una última observación: hay algunos problemas con la forma Press -> Immediately Release -> Move
. Se supone que debe cancelar el desplazamiento si un usuario hace clic con el botón izquierdo del mouse, o cualquier tecla del teclado, o la aplicación pierde el foco. Hay muchos eventos y no tengo tiempo para manejarlos a todos.
Pero la forma estándar Press -> Move -> Release
funciona sin problemas.
+1 para la solución, tengo algunas sugerencias, por favor vea mi respuesta por separado –
vorrtex ha publicado una solución agradable, Por favor, vuélvela él!
Aunque tengo algunas sugerencias para su solución, que son demasiado largas para incluirlas todas en los comentarios, ¡es por eso que publico una respuesta separada y se la dirijo!
Menciona problemas con Presione-> Soltar-> Mover. Debería utilizar MouseCapturing para obtener MouseEvents incluso cuando el mouse ya no esté sobre el ScrollViewer. No lo he probado, pero supongo que su solución también falla en Press->Move->Move outside of ScrollViewer->Release
, Mousecapturing se encargará de eso también.
También menciona usar un Comportamiento. Prefiero sugerir un attached behavior que no necesita dependencias adicionales.
Definitivamente no debe utilizar un lienzo adicional, pero haga esto en un Adorner.
ScrollViewer alberga un ScrollContentPresenter que define AdornerLayer. Deberías insertar el Adorner allí. Esto elimina la necesidad de cualquier dependencia adicional y también mantiene el comportamiento adjunto tan simple como IsMiddleScrollable="true"
.
MouseCapture no es difícil de implementar, lo haré después de algunas horas.Pero otros comentarios no son tan claros. Si utilizo propiedad o comportamiento adjunto, no podré agregar la imagen de desplazamiento al 'Lienzo'. Por otro lado, el control 'ScrollContentPresenter 'se encuentra dentro de la plantilla de' ScrollViewer' y creo que debo crear un control heredado para acceder a las partes internas. Trataré de hacer algo con esto, pero no estoy seguro de si el nuevo control es mejor que un conjunto de controladores de eventos. – vorrtex
Después de capturar el mouse, el evento MouseMove se llama solo una vez. Debo crear un temporizador que activará el método con la funcionalidad de movimiento. Todo se vuelve más y más complejo. – vorrtex
@vorrtex Tendré tiempo mañana por la noche. Como también estoy interesado en una buena solución compacta, ¡me sumergiré en ella! –
- 1. Distinga entre hacer doble clic con el mouse y hacer clic con el mouse en wpf
- 2. Cómo puedo hacer que la rueda del mouse funcione correctamente con Silverlight 4 ScrollViewer
- 3. WPF: botón izquierdo del mouse, haga clic y mantenga presionado el control
- 4. Botón WPF haga clic en C# código
- 5. WPF: hacer que todo el borde haga clic en
- 6. Cómo enlazar con el botón derecho del mouse, haga clic en knockoutJs?
- 7. Hacer que el puntero del mouse se vuelva mano para hacer clic en el botón
- 8. Cómo simular el clic del mouse con el control WebBrowser
- 9. Selenium 2 haga clic con el botón derecho
- 10. Cómo deshabilitar el botón, haga clic en?
- 11. ¿Alerta de Jquery cuando se hace clic en el botón central del mouse?
- 12. Cómo deshabilitar la rueda del mouse, haga clic en el botón?
- 13. Dirigiendo eventos del mouse [DllImport ("user32.dll")] haga clic en, haga doble clic en
- 14. Problema con onClick() y botón central en el mouse
- 15. ¿Cómo puedo hacer que mi scrollviewer de WPF funcione con el zoom?
- 16. Detectar Mouse haga clic en ubicación
- 17. Cierre JFrame con botón haga clic en
- 18. ¿Cómo hacer que el cursor del mouse agarre el mouse?
- 19. Hacer clic y mover el mouse mediante programación con VB.NET
- 20. Triple Mouse Haga clic en C#?
- 21. Cerrar pestaña en el control de pestañas de winforms con el botón central del mouse
- 22. Capturar Haga clic con el botón derecho en HTML DIV
- 23. Ext Js: haga clic en un botón
- 24. Cómo activar programáticamente un mouse, haga clic izquierdo en C#?
- 25. ¿Cómo puedo hacer que ScrollViewer funcione dentro de un StackPanel?
- 26. Hacer que el elemento traducido en 3D haga clic en
- 27. Mostrando un menú emergente en QGraphicsScene, haga clic o haga clic con el botón derecho
- 28. SendInput no realiza clic en el botón del mouse a menos que mueva el cursor
- 29. ¿Cómo hacer que el botón no se pueda hacer clic después de hacer clic en él?
- 30. Cocoa: haga clic con el botón secundario en NSStatusItem
Es posible controlar el evento del botón central del mouse: http://stackoverflow.com/questions/517556/how-to-handle-the-mouse-wheel-click-event-in-wpf. Trataré de manejar y procesar este evento correctamente. – vorrtex