Jak przeciągnąć kontrolkę użytkownika na ekran jak okno
Moja aplikacja WPF maUserControl
który ma wyglądać i zachowywać się jak wyskakujące okienko, ale nie jest to okno. Powód, dla którego sterowanie nie pochodzi odWindow
klasa polega na tym, że zawiera wirtualną klawiaturę ekranową innej firmy i ta kontrola musi znajdować się w tym samym oknie coTextBox
kontroluje, czy wysyła znaki wejściowe po kliknięciu jego przycisków. Jeśli sterowanie klawiaturą nie jest w tym samym oknie, nie może nawet zobaczyćTextBox
sterownica.
Problem, który mam, to wydajność beznadziejna podczas przeciągania okna dialogowego. Jest wystarczająco wolny, aby mysz opuściła obszar przeciągania i przestaje podążać za myszą. Potrzebuję lepszego sposobu.
Oto fragment xamla do kontroli:
<Grid Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Background="{DynamicResource PopupBackground}"
BorderBrush="{DynamicResource PopupBorder}"
BorderThickness="5,5,5,0"
MouseLeftButtonDown="Grid_MouseLeftButtonDown"
MouseLeftButtonUp="Grid_MouseLeftButtonUp"
MouseMove="Grid_MouseMove">
. . .
</Border>
</Grid>
Oto obsługa zdarzeń myszy:
private void Grid_MouseLeftButtonDown( object sender, MouseButtonEventArgs e ) {
Canvas canvas = Parent as Canvas;
if ( canvas == null ) {
throw new InvalidCastException( "The parent of a KeyboardPopup control must be a Canvas." );
}
DraggingControl = true;
CurrentMousePosition = e.GetPosition( canvas );
e.Handled = true;
}
private void Grid_MouseLeftButtonUp( object sender, MouseButtonEventArgs e ) {
Canvas canvas = Parent as Canvas;
if ( canvas == null ) {
throw new InvalidCastException( "The parent of a KeyboardPopup control must be a Canvas." );
}
if ( DraggingControl ) {
Point mousePosition = e.GetPosition( canvas );
// Correct the mouse coordinates in case they go off the edges of the control
if ( mousePosition.X < 0.0 ) mousePosition.X = 0.0; else if ( mousePosition.X > canvas.ActualWidth ) mousePosition.X = canvas.ActualWidth;
if ( mousePosition.Y < 0.0 ) mousePosition.Y = 0.0; else if ( mousePosition.Y > canvas.ActualHeight ) mousePosition.Y = canvas.ActualHeight;
// Compute the new Left & Top coordinates of the control
Canvas.SetLeft( this, Left += mousePosition.X - CurrentMousePosition.X );
Canvas.SetTop( this, Top += mousePosition.Y - CurrentMousePosition.Y );
}
e.Handled = true;
}
private void Grid_MouseMove( object sender, MouseEventArgs e ) {
Canvas canvas = Parent as Canvas;
if ( canvas == null ) {
// It is not. Throw an exception
throw new InvalidCastException( "The parent of a KeyboardPopup control must be a Canvas." );
}
if ( DraggingControl && e.LeftButton == MouseButtonState.Pressed ) {
Point mousePosition = e.GetPosition( canvas );
// Correct the mouse coordinates in case they go off the edges of the control
if ( mousePosition.X < 0.0 ) mousePosition.X = 0.0; else if ( mousePosition.X > canvas.ActualWidth ) mousePosition.X = canvas.ActualWidth;
if ( mousePosition.Y < 0.0 ) mousePosition.Y = 0.0; else if ( mousePosition.Y > canvas.ActualHeight ) mousePosition.Y = canvas.ActualHeight;
// Compute the new Left & Top coordinates of the control
Canvas.SetLeft( this, Left += mousePosition.X - CurrentMousePosition.X );
Canvas.SetTop ( this, Top += mousePosition.Y - CurrentMousePosition.Y );
CurrentMousePosition = mousePosition;
}
e.Handled = true;
}
Zauważ, że formant musi być umieszczony wewnątrzCanvas
w oknie, które go używa.
Nie mogę użyćDragMove
jak to jest metodaWindow
klasa i ta klasa pochodzi odUserControl
. Jak poprawić wydajność przeciągania tego formantu? Czy muszę uciekać się do API Win32?