클릭하는 요소에 관계없이 WPF 창을 끌 수 있도록 설정
두 가지 질문이 있습니다. WinForms의 표준 솔루션보다 WPF에서 제공하는 두 가지 솔루션이 더 쉬웠으면 합니다(Christophe Geers가 이 설명을 하기 전에 제공했습니다).
먼저 마우스 클릭+드래그 이벤트를 캡처 및 처리하지 않고 Windows를 드래그할 수 있는 방법이 있습니까?즉, 창은 제목 표시줄로 끌 수 있지만, 창을 표시하지 않도록 설정하고도 끌 수 있도록 하려면 제목 표시줄 끌기를 다루는 대로 이벤트를 다시 지정할 수 있는 방법이 있습니까?
둘째, 창 내의 모든 요소에 이벤트핸들러를 적용하는 방법이 있나요?와 같이 사용자가 클릭+드래그를 하는 요소에 관계없이 창을 끌 수 있도록 합니다.모든 요소에 핸들러를 수동으로 추가하지 않아도 됩니다.어디선가 한 번만 해요?
네, 다음 사항을 적용합니다.MouseDown
이벤트Window
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}
이렇게 하면 사용자는 마우스 다운 이벤트를 먹는 컨트롤을 제외하고 컨트롤을 클릭하거나 끌 때 창을 끌 수 있습니다(마우스 다운 이벤트).e.Handled = true
)
사용할 수 있습니다.PreviewMouseDown
대신MouseDown
단, 드래그이벤트는Click
따라서 왼쪽 클릭 이벤트에 대한 응답이 중지됩니다.컨트롤에서 폼을 클릭하여 드래그할 수 있는 경우PreviewMouseDown
드래그 조작을 개시하는 타이머를 기동해, 조작을 취소합니다.MouseUp
이벤트는 X밀리초 이내에 기동됩니다.
wpf 폼을 클릭하는 장소에 관계없이 드래그 할 필요가 있는 경우, 간단한 회피책은 위임자를 사용하여 Windows onload 이벤트 또는 그리드 로드 이벤트에서 DragMove() 메서드를 트리거하는 것입니다.
private void Grid_Loaded(object sender, RoutedEventArgs
{
this.MouseDown += delegate{DragMove();};
}
경우에 따라서는, 델에서는Window
(예:DevExpress
사용할 수 있는 것은UIElement
.
순서 1: 첨부된 속성 추가
해결책은 다음과 같습니다.
- 에 접속하다
MouseMove
이벤트 - 첫 번째 부모를 찾을 때까지 시각 트리 검색
Window
; - 불러
.DragMove()
새로 발견된 것에 대해서Window
.
코드:
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace DXApplication1.AttachedProperty
{
public class EnableDragHelper
{
public static readonly DependencyProperty EnableDragProperty = DependencyProperty.RegisterAttached(
"EnableDrag",
typeof (bool),
typeof (EnableDragHelper),
new PropertyMetadata(default(bool), OnLoaded));
private static void OnLoaded(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var uiElement = dependencyObject as UIElement;
if (uiElement == null || (dependencyPropertyChangedEventArgs.NewValue is bool) == false)
{
return;
}
if ((bool)dependencyPropertyChangedEventArgs.NewValue == true)
{
uiElement.MouseMove += UIElementOnMouseMove;
}
else
{
uiElement.MouseMove -= UIElementOnMouseMove;
}
}
private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var uiElement = sender as UIElement;
if (uiElement != null)
{
if (mouseEventArgs.LeftButton == MouseButtonState.Pressed)
{
DependencyObject parent = uiElement;
int avoidInfiniteLoop = 0;
// Search up the visual tree to find the first parent window.
while ((parent is Window) == false)
{
parent = VisualTreeHelper.GetParent(parent);
avoidInfiniteLoop++;
if (avoidInfiniteLoop == 1000)
{
// Something is wrong - we could not find the parent window.
return;
}
}
var window = parent as Window;
window.DragMove();
}
}
}
public static void SetEnableDrag(DependencyObject element, bool value)
{
element.SetValue(EnableDragProperty, value);
}
public static bool GetEnableDrag(DependencyObject element)
{
return (bool)element.GetValue(EnableDragProperty);
}
}
}
순서 2: 임의의 요소에 첨부된 속성을 추가하여 창을 드래그할 수 있도록 합니다.
다음 속성을 추가하면 특정 요소를 클릭하여 창 전체를 끌 수 있습니다.
<Border local:EnableDragHelper.EnableDrag="True">
<TextBlock Text="Click me to drag this entire window"/>
</Border>
부록 A: 옵션 상세 예시
DevExpress의 이 예에서는 도킹 창의 제목 표시줄을 회색 직사각형으로 교체하고 사용자가 해당 회색 직각형을 클릭하여 끌면 창이 정상적으로 끌리도록 합니다.
<dx:DXWindow x:Class="DXApplication1.MainWindow" Title="MainWindow" Height="464" Width="765"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:local="clr-namespace:DXApplication1.AttachedProperty"
xmlns:dxdove="http://schemas.devexpress.com/winfx/2008/xaml/docking/visualelements"
xmlns:themeKeys="http://schemas.devexpress.com/winfx/2008/xaml/docking/themekeys">
<dxdo:DockLayoutManager FloatingMode="Desktop">
<dxdo:DockLayoutManager.FloatGroups>
<dxdo:FloatGroup FloatLocation="0, 0" FloatSize="179,204" MaxHeight="300" MaxWidth="400"
local:TopmostFloatingGroupHelper.IsTopmostFloatingGroup="True"
>
<dxdo:LayoutPanel ShowBorder="True" ShowMaximizeButton="False" ShowCaption="False" ShowCaptionImage="True"
ShowControlBox="True" ShowExpandButton="True" ShowInDocumentSelector="True" Caption="TradePad General"
AllowDock="False" AllowHide="False" AllowDrag="True" AllowClose="False"
>
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" MinHeight="15" Background="#FF515151" Margin="0 0 0 0"
local:EnableDragHelper.EnableDrag="True">
<TextBlock Margin="4" Text="General" FontWeight="Bold"/>
</Border>
<TextBlock Margin="5" Grid.Row="1" Text="Hello, world!" />
</Grid>
</dxdo:LayoutPanel>
</dxdo:FloatGroup>
</dxdo:DockLayoutManager.FloatGroups>
</dxdo:DockLayoutManager>
</dx:DXWindow>
면책사항:저는 DevExpress에 소속되어 있지 않습니다.이 기법은 표준 WPF 또는 Telerik(다른 WPF 라이브러리 프로바이더)를 포함한 모든 사용자 요소에서 사용할 수 있습니다.
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}
경우에 따라서는 예외를 발생시키고 있습니다(예를 들어 창에 클릭 가능한 이미지가 있는 경우 클릭 시 메시지 상자가 열립니다.메시지 박스를 종료하면 에러가 발생합니다.사용하는 것이 더 안전합니다.
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
this.DragMove();
}
그 때 왼쪽 버튼이 눌려 있는 것이 확실합니다.
@fjch 1997에서 이미 언급했듯이 동작을 구현하는 것이 편리합니다.여기서 핵심 논리는 @loi.efy의 답변과 동일합니다.
public class DragMoveBehavior : Behavior<Window>
{
protected override void OnAttached()
{
AssociatedObject.MouseMove += AssociatedObject_MouseMove;
}
protected override void OnDetaching()
{
AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
}
private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && sender is Window window)
{
// In maximum window state case, window will return normal state and
// continue moving follow cursor
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
// 3 or any where you want to set window location after
// return from maximum state
Application.Current.MainWindow.Top = 3;
}
window.DragMove();
}
}
}
사용방법:
<Window ...
xmlns:h="clr-namespace:A.Namespace.Of.DragMoveBehavior"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<i:Interaction.Behaviors>
<h:DragMoveBehavior />
</i:Interaction.Behaviors>
...
</Window>
이것만 있으면 돼!
private void UiElement_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (this.WindowState == WindowState.Maximized) // In maximum window state case, window will return normal state and continue moving follow cursor
{
this.WindowState = WindowState.Normal;
Application.Current.MainWindow.Top = 3;// 3 or any where you want to set window location affter return from maximum state
}
this.DragMove();
}
}
제목 표시줄뿐만 아니라 폼의 아무 곳이나 클릭하면 폼을 드래그 앤 드롭할 수 있습니다.이것은 테두리가 없는 양식이 있는 경우에 편리합니다.
Code Project에 관한 이 기사에서는 이를 구현하기 위한 솔루션 중 하나를 소개합니다.
http://www.codeproject.com/KB/cs/DraggableForm.aspx
기본적으로 Form 유형의 하위 항목이 생성되어 마우스의 아래쪽, 위쪽 및 이동 이벤트가 처리됩니다.
- 마우스 아래: 위치 기억
- 마우스 이동: 새 위치 저장
- 마우스 위: 폼을 새 위치에 위치시킵니다.
다음은 비디오 튜토리얼에서 설명한 것과 유사한 솔루션입니다.
http://www.youtube.com/watch?v=tJlY9aX73Vs
사용자가 해당 폼의 컨트롤을 클릭할 때 폼을 드래그하는 것을 허용하지 않습니다.사용자는 다른 컨트롤을 클릭하면 다른 결과를 얻을 수 있습니다.리스트 박스, 버튼, 라벨 등을 클릭했기 때문에 갑자기 폼이 움직이기 시작하면 혼란스러워집니다.
<Window
...
WindowStyle="None" MouseLeftButtonDown="WindowMouseLeftButtonDown"/>
<x:Code>
<![CDATA[
private void WindowMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
]]>
</x:Code>
WPF 형식과 Windows 형식 모두에서 가장 유용한 방법은 WPF 예입니다.
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
public static void StartDrag(Window window)
{
WindowInteropHelper helper = new WindowInteropHelper(window);
SendMessage(helper.Handle, 161, 2, 0);
}
이 항목을 Window 스타일에 추가합니다(속성은 설명이 필요 없습니다).
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome GlassFrameThickness="0" ResizeBorderThickness="3" CornerRadius="0" CaptionHeight="40" />
</Setter.Value>
</Setter>
언급URL : https://stackoverflow.com/questions/7417739/make-wpf-window-draggable-no-matter-what-element-is-clicked
'programing' 카테고리의 다른 글
Postgre 최적화신속한 테스트를 위한 SQL (0) | 2023.04.17 |
---|---|
Linux에서 아이폰 앱 개발을 시작하시겠습니까? (0) | 2023.04.17 |
XmlSerializer에서 오류가 발생한 이유는 무엇입니까? (0) | 2023.04.17 |
Xcode 9의 안전 영역 (0) | 2023.04.17 |
TSQL 변수를 일정하게 하는 방법이 있습니까? (0) | 2023.04.17 |