未验证 提交 c148ea19 编写于 作者: J Jan Karger ツ ☀ 提交者: GitHub

Merge pull request #444 from dmg-hamann/develop

fix touch support 
...@@ -1660,5 +1660,34 @@ public static void SetDropTargetItemsSorter(DependencyObject element, IDropTarge ...@@ -1660,5 +1660,34 @@ public static void SetDropTargetItemsSorter(DependencyObject element, IDropTarge
{ {
element.SetValue(DropTargetItemsSorterProperty, value); element.SetValue(DropTargetItemsSorterProperty, value);
} }
/// <summary>
/// Gets or sets the mouse move triggered by a timer.
/// </summary>
public static readonly DependencyProperty MouseMoveTimerTriggeredProperty
= DependencyProperty.RegisterAttached("MouseMoveTimerTriggered",
typeof(bool),
typeof(DragDrop),
new PropertyMetadata(false));
/// <summary>Helper for getting <see cref="MouseMoveTimerTriggeredProperty"/> from <paramref name="element"/>.</summary>
/// <param name="element"><see cref="DependencyObject"/> to read <see cref="MouseMoveTimerTriggeredProperty"/> from.</param>
/// <remarks>Gets the mouse move triggered by a timer.</remarks>
/// <returns>MouseMoveTimerTriggered property value.</returns>
[AttachedPropertyBrowsableForType(typeof(UIElement))]
public static bool GetMouseMoveTimerTriggered(DependencyObject element)
{
return (bool)element.GetValue(MouseMoveTimerTriggeredProperty);
}
/// <summary>Helper for setting <see cref="MouseMoveTimerTriggeredProperty"/> on <paramref name="element"/>.</summary>
/// <param name="element"><see cref="DependencyObject"/> to set <see cref="MouseMoveTimerTriggeredProperty"/> on.</param>
/// <param name="value">MouseMoveTimerTriggered property value.</param>
/// <remarks>Sets the mouse move triggered by a timer.</remarks>
[AttachedPropertyBrowsableForType(typeof(UIElement))]
public static void SetMouseMoveTimerTriggered(DependencyObject element, bool value)
{
element.SetValue(MouseMoveTimerTriggeredProperty, value);
}
} }
} }
\ No newline at end of file
...@@ -639,11 +639,12 @@ private static void DoDragSourceMove(object sender, Func<IInputElement, Point> g ...@@ -639,11 +639,12 @@ private static void DoDragSourceMove(object sender, Func<IInputElement, Point> g
DragDropPreview?.Move(getPosition(DragDropPreview.PlacementTarget)); DragDropPreview?.Move(getPosition(DragDropPreview.PlacementTarget));
} }
hookId = MouseHelper.HookMouseMove(point => hookId = MouseHelper.HookMouseMove(DragDrop.GetMouseMoveTimerTriggered(dragInfo.VisualSource),
{ point =>
DragDropPreview?.Move(CursorHelper.GetCurrentCursorPosition(DragDropPreview.PlacementTarget, point)); {
DragDropEffectPreview?.Move(CursorHelper.GetCurrentCursorPosition(DragDropEffectPreview.PlacementTarget, point)); DragDropPreview?.Move(CursorHelper.GetCurrentCursorPosition(DragDropPreview.PlacementTarget, point));
}); DragDropEffectPreview?.Move(CursorHelper.GetCurrentCursorPosition(DragDropEffectPreview.PlacementTarget, point));
});
var dragDropHandler = dragInfo.DragDropHandler ?? System.Windows.DragDrop.DoDragDrop; var dragDropHandler = dragInfo.DragDropHandler ?? System.Windows.DragDrop.DoDragDrop;
var dragDropEffects = dragDropHandler(dragInfo.VisualSource, dataObject, dragInfo.Effects); var dragDropEffects = dragDropHandler(dragInfo.VisualSource, dataObject, dragInfo.Effects);
......
...@@ -11,29 +11,50 @@ internal static class MouseHelper ...@@ -11,29 +11,50 @@ internal static class MouseHelper
private const int WH_MOUSE_LL = 14; private const int WH_MOUSE_LL = 14;
private static IntPtr _hookID = IntPtr.Zero; private static bool _timerTriggered;
private static Action<System.Windows.Point> _mouseMoveHandler; private static Action<System.Windows.Point> _mouseMoveHandler;
// wee need to keep the variable to prevent the GarbageCollector to remove the HookCallback // wee need to keep the variable to prevent the GarbageCollector to remove the HookCallback
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/68fdc3dc-8d77-48c4-875c-5312baa56aee/how-to-fix-callbackoncollecteddelegate-exception?forum=netfxbcl // https://social.msdn.microsoft.com/Forums/vstudio/en-US/68fdc3dc-8d77-48c4-875c-5312baa56aee/how-to-fix-callbackoncollecteddelegate-exception?forum=netfxbcl
private static LowLevelMouseProc _proc = HookCallback; private static LowLevelMouseProc _proc = HookCallback;
private static System.Windows.Threading.DispatcherTimer _timer;
internal static IntPtr HookMouseMove(Action<System.Windows.Point> mouseMoveHandler) internal static IntPtr HookMouseMove(bool timerTriggered, Action<System.Windows.Point> mouseMoveHandler)
{ {
_mouseMoveHandler = mouseMoveHandler; _mouseMoveHandler = mouseMoveHandler;
_timerTriggered = timerTriggered;
using (var process = Process.GetCurrentProcess()) if (_timerTriggered)
{ {
using (var module = process.MainModule) _timer = new System.Windows.Threading.DispatcherTimer(System.Windows.Threading.DispatcherPriority.Input);
{ _timer.Tick += (_, _) =>
return SetWindowsHookEx(WH_MOUSE_LL, _proc, GetModuleHandle(module.ModuleName), 0); {
} if (TryGetCursorPos(out var lpPoint))
{
_mouseMoveHandler?.Invoke(new System.Windows.Point(lpPoint.x, lpPoint.y));
}
};
_timer.Interval = new TimeSpan(1);
_timer.Start();
return IntPtr.Zero;
} }
using var process = Process.GetCurrentProcess();
using var module = process.MainModule;
return module != null ? SetWindowsHookEx(WH_MOUSE_LL, _proc, GetModuleHandle(module.ModuleName), 0) : IntPtr.Zero;
} }
internal static void RemoveHook(IntPtr hookId) internal static void RemoveHook(IntPtr hookId)
{ {
UnhookWindowsHookEx(hookId); if (_timerTriggered)
{
_timer.Stop();
}
else
{
UnhookWindowsHookEx(hookId);
}
} }
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
...@@ -41,12 +62,11 @@ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) ...@@ -41,12 +62,11 @@ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam) if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
{ {
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
//Debug.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
var mousePosScreen = new System.Windows.Point(hookStruct.pt.x, hookStruct.pt.y); var mousePosScreen = new System.Windows.Point(hookStruct.pt.x, hookStruct.pt.y);
_mouseMoveHandler?.Invoke(mousePosScreen); _mouseMoveHandler?.Invoke(mousePosScreen);
} }
return CallNextHookEx(_hookID, nCode, wParam, lParam); return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
} }
private enum MouseMessages private enum MouseMessages
...@@ -88,5 +108,25 @@ private struct MSLLHOOKSTRUCT ...@@ -88,5 +108,25 @@ private struct MSLLHOOKSTRUCT
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName); private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", EntryPoint = "GetCursorPos", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool _GetCursorPos(out POINT lpPoint);
private static bool TryGetCursorPos(out POINT pt)
{
var returnValue = _GetCursorPos(out pt);
// Sometimes Win32 will fail this call, such as if you are
// not running in the interactive desktop. For example,
// a secure screen saver may be running.
if (!returnValue)
{
Trace.WriteLine("GetCursorPos failed!");
pt.x = 0;
pt.y = 0;
}
return returnValue;
}
} }
} }
\ No newline at end of file
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
dd:DragDrop.IsDragSource="True" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" dd:DragDrop.IsDropTarget="True"
dd:DragDrop.UseDefaultEffectDataTemplate="True" dd:DragDrop.UseDefaultEffectDataTemplate="True"
dd:DragDrop.MouseMoveTimerTriggered="True"
ItemsSource="{Binding Data.Collection1}" /> ItemsSource="{Binding Data.Collection1}" />
<ListBox x:Name="RightBoundListBox" <ListBox x:Name="RightBoundListBox"
Grid.Column="1" Grid.Column="1"
......
...@@ -11,32 +11,45 @@ ...@@ -11,32 +11,45 @@
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource DefaultTextBlockStyle}" <TextBlock Style="{StaticResource DefaultTextBlockStyle}"
Text="{Binding ElementName=This, Path=Caption, Mode=OneWay}" /> Text="{Binding ElementName=This, Path=Caption, Mode=OneWay}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="IsDragSource" Content="IsDragSource"
ToolTip="Sets whether the control can be used as drag source."
IsChecked="{Binding Path=(dd:DragDrop.IsDragSource), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.IsDragSource), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="IsDropTarget" Content="IsDropTarget"
ToolTip="Sets whether the control can be used as drop target."
IsChecked="{Binding Path=(dd:DragDrop.IsDropTarget), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.IsDropTarget), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="DragDirectlySelectedOnly" Content="DragDirectlySelectedOnly"
ToolTip="Sets whether the drag action should be started only directly on a selected item or also on the free control space (e.g. in a ListBox)."
IsChecked="{Binding Path=(dd:DragDrop.DragDirectlySelectedOnly), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.DragDirectlySelectedOnly), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="ShowAlwaysDropTargetAdorner" Content="ShowAlwaysDropTargetAdorner"
ToolTip="Sets whether to show the DropTargetAdorner (DropTargetInsertionAdorner) on an empty target too."
IsChecked="{Binding Path=(dd:DragDrop.ShowAlwaysDropTargetAdorner), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.ShowAlwaysDropTargetAdorner), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="SelectDroppedItems" Content="SelectDroppedItems"
ToolTip="Sets whether if the dropped items should be select again (should keep the selection)."
IsChecked="{Binding Path=(dd:DragDrop.SelectDroppedItems), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.SelectDroppedItems), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="CanDragWithMouseRightButton" Content="CanDragWithMouseRightButton"
ToolTip="Sets whether the control can be used as drag source together with the right mouse."
IsChecked="{Binding Path=(dd:DragDrop.CanDragWithMouseRightButton), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.CanDragWithMouseRightButton), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="UseDefaultDragAdorner" Content="UseDefaultDragAdorner"
ToolTip="Sets whether if the default DragAdorner should be use."
IsChecked="{Binding Path=(dd:DragDrop.UseDefaultDragAdorner), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.UseDefaultDragAdorner), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="UseVisualSourceItemSizeForDragAdorner" Content="UseVisualSourceItemSizeForDragAdorner"
ToolTip="Use descendant bounds of the VisualSourceItem as MinWidth for the DragAdorner."
IsChecked="{Binding Path=(dd:DragDrop.UseVisualSourceItemSizeForDragAdorner), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.UseVisualSourceItemSizeForDragAdorner), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 5 5 5" <CheckBox Margin="10 2 2 2"
Content="UseDefaultEffectDataTemplate" Content="UseDefaultEffectDataTemplate"
ToolTip="Sets whether if the default DataTemplate for the effects should be use."
IsChecked="{Binding Path=(dd:DragDrop.UseDefaultEffectDataTemplate), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> IsChecked="{Binding Path=(dd:DragDrop.UseDefaultEffectDataTemplate), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="10 2 2 2"
Content="MouseMoveTimerTriggered"
ToolTip="Sets the mouse move triggered by a timer."
IsChecked="{Binding Path=(dd:DragDrop.MouseMoveTimerTriggered), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel> </StackPanel>
</UserControl> </UserControl>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册