添加项目文件。
This commit is contained in:
59
Util/CommonCode.cs
Normal file
59
Util/CommonCode.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using GeekDesk.ViewModel;
|
||||
|
||||
/// <summary>
|
||||
/// 提取一些代码
|
||||
/// </summary>
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
class CommonCode
|
||||
{
|
||||
private static string appConfigFilePath = AppDomain.CurrentDomain.BaseDirectory.Trim() + "\\config";
|
||||
/// <summary>
|
||||
/// 获取app配置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static AppConfig GetAppConfig()
|
||||
{
|
||||
AppConfig config;
|
||||
if (!File.Exists(appConfigFilePath))
|
||||
{
|
||||
using (FileStream fs = File.Create(appConfigFilePath)) { }
|
||||
config = new AppConfig();
|
||||
SaveAppConfig(config);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
using (FileStream fs = new FileStream(appConfigFilePath, FileMode.Open))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
string json = bf.Deserialize(fs) as string;
|
||||
config = JsonConvert.DeserializeObject<AppConfig>(json);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存app配置
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
public static void SaveAppConfig(AppConfig config)
|
||||
{
|
||||
using (FileStream fs = new FileStream(appConfigFilePath, FileMode.Create))
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
string json = JsonConvert.SerializeObject(config);
|
||||
bf.Serialize(fs, json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
105
Util/ConsoleManager.cs
Normal file
105
Util/ConsoleManager.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static class ConsoleManager
|
||||
{
|
||||
private const string Kernel32_DllName = "kernel32.dll";
|
||||
|
||||
[DllImport(Kernel32_DllName)]
|
||||
private static extern bool AllocConsole();
|
||||
|
||||
[DllImport(Kernel32_DllName)]
|
||||
private static extern bool FreeConsole();
|
||||
|
||||
[DllImport(Kernel32_DllName)]
|
||||
private static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[DllImport(Kernel32_DllName)]
|
||||
private static extern int GetConsoleOutputCP();
|
||||
|
||||
public static bool HasConsole
|
||||
{
|
||||
get { return GetConsoleWindow() != IntPtr.Zero; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new console instance if the process is not attached to a console already.
|
||||
/// </summary>
|
||||
public static void Show()
|
||||
{
|
||||
//#if DEBUG
|
||||
if (!HasConsole)
|
||||
{
|
||||
AllocConsole();
|
||||
InvalidateOutAndError();
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
|
||||
/// </summary>
|
||||
public static void Hide()
|
||||
{
|
||||
//#if DEBUG
|
||||
if (HasConsole)
|
||||
{
|
||||
SetOutAndErrorNull();
|
||||
FreeConsole();
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
public static void Toggle()
|
||||
{
|
||||
if (HasConsole)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
Show();
|
||||
}
|
||||
}
|
||||
|
||||
static void InvalidateOutAndError()
|
||||
{
|
||||
Type type = typeof(System.Console);
|
||||
|
||||
System.Reflection.FieldInfo _out = type.GetField("_out",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
|
||||
System.Reflection.FieldInfo _error = type.GetField("_error",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
|
||||
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
|
||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||
|
||||
Debug.Assert(_out != null);
|
||||
Debug.Assert(_error != null);
|
||||
|
||||
Debug.Assert(_InitializeStdOutError != null);
|
||||
|
||||
_out.SetValue(null, null);
|
||||
_error.SetValue(null, null);
|
||||
|
||||
_InitializeStdOutError.Invoke(null, new object[] { true });
|
||||
}
|
||||
|
||||
static void SetOutAndErrorNull()
|
||||
{
|
||||
Console.SetOut(TextWriter.Null);
|
||||
Console.SetError(TextWriter.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
175
Util/DragAdorner.cs
Normal file
175
Util/DragAdorner.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright (C) Josh Smith - January 2007
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace WPF.JoshSmith.Adorners
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders a visual which can follow the mouse cursor,
|
||||
/// such as during a drag-and-drop operation.
|
||||
/// </summary>
|
||||
public class DragAdorner : Adorner
|
||||
{
|
||||
#region Data
|
||||
|
||||
private Rectangle child = null;
|
||||
private double offsetLeft = 0;
|
||||
private double offsetTop = 0;
|
||||
|
||||
#endregion // Data
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of DragVisualAdorner.
|
||||
/// </summary>
|
||||
/// <param name="adornedElement">The element being adorned.</param>
|
||||
/// <param name="size">The size of the adorner.</param>
|
||||
/// <param name="brush">A brush to with which to paint the adorner.</param>
|
||||
public DragAdorner( UIElement adornedElement, Size size, Brush brush )
|
||||
: base( adornedElement )
|
||||
{
|
||||
Rectangle rect = new Rectangle();
|
||||
rect.Fill = brush;
|
||||
rect.Width = size.Width;
|
||||
rect.Height = size.Height;
|
||||
rect.IsHitTestVisible = false;
|
||||
this.child = rect;
|
||||
}
|
||||
|
||||
#endregion // Constructor
|
||||
|
||||
#region Public Interface
|
||||
|
||||
#region GetDesiredTransform
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="transform"></param>
|
||||
/// <returns></returns>
|
||||
public override GeneralTransform GetDesiredTransform( GeneralTransform transform )
|
||||
{
|
||||
GeneralTransformGroup result = new GeneralTransformGroup();
|
||||
result.Children.Add( base.GetDesiredTransform( transform ) );
|
||||
result.Children.Add( new TranslateTransform( this.offsetLeft, this.offsetTop ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion // GetDesiredTransform
|
||||
|
||||
#region OffsetLeft
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the horizontal offset of the adorner.
|
||||
/// </summary>
|
||||
public double OffsetLeft
|
||||
{
|
||||
get { return this.offsetLeft; }
|
||||
set
|
||||
{
|
||||
this.offsetLeft = value;
|
||||
UpdateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // OffsetLeft
|
||||
|
||||
#region SetOffsets
|
||||
|
||||
/// <summary>
|
||||
/// Updates the location of the adorner in one atomic operation.
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="top"></param>
|
||||
public void SetOffsets( double left, double top )
|
||||
{
|
||||
this.offsetLeft = left;
|
||||
this.offsetTop = top;
|
||||
this.UpdateLocation();
|
||||
}
|
||||
|
||||
#endregion // SetOffsets
|
||||
|
||||
#region OffsetTop
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the vertical offset of the adorner.
|
||||
/// </summary>
|
||||
public double OffsetTop
|
||||
{
|
||||
get { return this.offsetTop; }
|
||||
set
|
||||
{
|
||||
this.offsetTop = value;
|
||||
UpdateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // OffsetTop
|
||||
|
||||
#endregion // Public Interface
|
||||
|
||||
#region Protected Overrides
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="constraint"></param>
|
||||
/// <returns></returns>
|
||||
protected override Size MeasureOverride( Size constraint )
|
||||
{
|
||||
this.child.Measure( constraint );
|
||||
return this.child.DesiredSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="finalSize"></param>
|
||||
/// <returns></returns>
|
||||
protected override Size ArrangeOverride( Size finalSize )
|
||||
{
|
||||
this.child.Arrange( new Rect( finalSize ) );
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override.
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
protected override Visual GetVisualChild( int index )
|
||||
{
|
||||
return this.child;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override. Always returns 1.
|
||||
/// </summary>
|
||||
protected override int VisualChildrenCount
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
#endregion // Protected Overrides
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
private void UpdateLocation()
|
||||
{
|
||||
AdornerLayer adornerLayer = this.Parent as AdornerLayer;
|
||||
if( adornerLayer != null )
|
||||
adornerLayer.Update( this.AdornedElement );
|
||||
}
|
||||
|
||||
#endregion // Private Helpers
|
||||
}
|
||||
}
|
||||
376
Util/FileIcon.cs
Normal file
376
Util/FileIcon.cs
Normal file
@@ -0,0 +1,376 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
class FileIcon
|
||||
{
|
||||
|
||||
|
||||
public static Icon GetIcon(string filePath)
|
||||
{
|
||||
IntPtr hIcon = GetJumboIcon(GetIconIndex(filePath));
|
||||
Icon ico = Icon.FromHandle(hIcon);
|
||||
return ico;
|
||||
}
|
||||
|
||||
public static BitmapImage GetBitmapImage(string filePath)
|
||||
{
|
||||
//Icon ico;
|
||||
//BitmapImage bmpImage = null;
|
||||
//MemoryStream strm;
|
||||
//using (ico = GetIcon(filePath))
|
||||
//{
|
||||
// Bitmap bmp = ico.ToBitmap();
|
||||
// using (strm = new MemoryStream())
|
||||
// {
|
||||
// bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png);
|
||||
// bmpImage = new BitmapImage();
|
||||
// bmpImage.BeginInit();
|
||||
// strm.Seek(0, SeekOrigin.Begin);
|
||||
// bmpImage.StreamSource = strm;
|
||||
// bmpImage.EndInit();
|
||||
// }
|
||||
//}
|
||||
//return bmpImage;
|
||||
Icon ico = GetIcon(filePath);
|
||||
Bitmap bmp = ico.ToBitmap();
|
||||
MemoryStream strm = new MemoryStream();
|
||||
bmp.Save(strm, System.Drawing.Imaging.ImageFormat.Png);
|
||||
BitmapImage bmpImage = new BitmapImage();
|
||||
bmpImage.BeginInit();
|
||||
strm.Seek(0, SeekOrigin.Begin);
|
||||
bmpImage.StreamSource = strm;
|
||||
bmpImage.EndInit();
|
||||
|
||||
return bmpImage.Clone();
|
||||
}
|
||||
|
||||
public static int GetIconIndex(string pszFile)
|
||||
{
|
||||
SHFILEINFO sfi = new SHFILEINFO();
|
||||
Shell32.SHGetFileInfo(pszFile
|
||||
, 0
|
||||
, ref sfi
|
||||
, (uint)System.Runtime.InteropServices.Marshal.SizeOf(sfi)
|
||||
, (uint)(SHGFI.SysIconIndex | SHGFI.LargeIcon | SHGFI.UseFileAttributes));
|
||||
return sfi.iIcon;
|
||||
}
|
||||
|
||||
// 256*256
|
||||
public static IntPtr GetJumboIcon(int iImage)
|
||||
{
|
||||
IImageList spiml = null;
|
||||
Guid guil = new Guid(IID_IImageList2);//or IID_IImageList
|
||||
|
||||
Shell32.SHGetImageList(Shell32.SHIL_JUMBO, ref guil, ref spiml);
|
||||
IntPtr hIcon = IntPtr.Zero;
|
||||
spiml.GetIcon(iImage, Shell32.ILD_TRANSPARENT | Shell32.ILD_IMAGE, ref hIcon);
|
||||
|
||||
return hIcon;
|
||||
}
|
||||
|
||||
const string IID_IImageList = "46EB5926-582E-4017-9FDF-E8998DAA0950";
|
||||
const string IID_IImageList2 = "192B9D83-50FC-457B-90A0-2B82A8B5DAE1";
|
||||
|
||||
public static class Shell32
|
||||
{
|
||||
|
||||
public const int SHIL_LARGE = 0x0;
|
||||
public const int SHIL_SMALL = 0x1;
|
||||
public const int SHIL_EXTRALARGE = 0x2;
|
||||
public const int SHIL_SYSSMALL = 0x3;
|
||||
public const int SHIL_JUMBO = 0x4;
|
||||
public const int SHIL_LAST = 0x4;
|
||||
|
||||
public const int ILD_TRANSPARENT = 0x00000001;
|
||||
public const int ILD_IMAGE = 0x00000020;
|
||||
|
||||
[DllImport("shell32.dll", EntryPoint = "#727")]
|
||||
public extern static int SHGetImageList(int iImageList, ref Guid riid, ref IImageList ppv);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "DestroyIcon", SetLastError = true)]
|
||||
public static unsafe extern int DestroyIcon(IntPtr hIcon);
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
public static extern uint SHGetIDListFromObject([MarshalAs(UnmanagedType.IUnknown)] object iUnknown, out IntPtr ppidl);
|
||||
|
||||
[DllImport("Shell32.dll")]
|
||||
public static extern IntPtr SHGetFileInfo(
|
||||
string pszPath,
|
||||
uint dwFileAttributes,
|
||||
ref SHFILEINFO psfi,
|
||||
uint cbFileInfo,
|
||||
uint uFlags
|
||||
);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum SHGFI : uint
|
||||
{
|
||||
/// <summary>get icon</summary>
|
||||
Icon = 0x000000100,
|
||||
/// <summary>get display name</summary>
|
||||
DisplayName = 0x000000200,
|
||||
/// <summary>get type name</summary>
|
||||
TypeName = 0x000000400,
|
||||
/// <summary>get attributes</summary>
|
||||
Attributes = 0x000000800,
|
||||
/// <summary>get icon location</summary>
|
||||
IconLocation = 0x000001000,
|
||||
/// <summary>return exe type</summary>
|
||||
ExeType = 0x000002000,
|
||||
/// <summary>get system icon index</summary>
|
||||
SysIconIndex = 0x000004000,
|
||||
/// <summary>put a link overlay on icon</summary>
|
||||
LinkOverlay = 0x000008000,
|
||||
/// <summary>show icon in selected state</summary>
|
||||
Selected = 0x000010000,
|
||||
/// <summary>get only specified attributes</summary>
|
||||
Attr_Specified = 0x000020000,
|
||||
/// <summary>get large icon</summary>
|
||||
LargeIcon = 0x000000000,
|
||||
/// <summary>get small icon</summary>
|
||||
SmallIcon = 0x000000001,
|
||||
/// <summary>get open icon</summary>
|
||||
OpenIcon = 0x000000002,
|
||||
/// <summary>get shell size icon</summary>
|
||||
ShellIconSize = 0x000000004,
|
||||
/// <summary>pszPath is a pidl</summary>
|
||||
PIDL = 0x000000008,
|
||||
/// <summary>use passed dwFileAttribute</summary>
|
||||
UseFileAttributes = 0x000000010,
|
||||
/// <summary>apply the appropriate overlays</summary>
|
||||
AddOverlays = 0x000000020,
|
||||
/// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
|
||||
OverlayIndex = 0x000000040,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SHFILEINFO
|
||||
{
|
||||
public const int NAMESIZE = 80;
|
||||
public IntPtr hIcon;
|
||||
public int iIcon;
|
||||
public uint dwAttributes;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szDisplayName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||
public string szTypeName;
|
||||
};
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int left, top, right, bottom;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGELISTDRAWPARAMS
|
||||
{
|
||||
public int cbSize;
|
||||
public IntPtr himl;
|
||||
public int i;
|
||||
public IntPtr hdcDst;
|
||||
public int x;
|
||||
public int y;
|
||||
public int cx;
|
||||
public int cy;
|
||||
public int xBitmap; // x offest from the upperleft of bitmap
|
||||
public int yBitmap; // y offset from the upperleft of bitmap
|
||||
public int rgbBk;
|
||||
public int rgbFg;
|
||||
public int fStyle;
|
||||
public int dwRop;
|
||||
public int fState;
|
||||
public int Frame;
|
||||
public int crEffect;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGEINFO
|
||||
{
|
||||
public IntPtr hbmImage;
|
||||
public IntPtr hbmMask;
|
||||
public int Unused1;
|
||||
public int Unused2;
|
||||
public RECT rcImage;
|
||||
}
|
||||
[ComImportAttribute()]
|
||||
[GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
|
||||
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IImageList
|
||||
{
|
||||
[PreserveSig]
|
||||
int Add(
|
||||
IntPtr hbmImage,
|
||||
IntPtr hbmMask,
|
||||
ref int pi);
|
||||
|
||||
[PreserveSig]
|
||||
int ReplaceIcon(
|
||||
int i,
|
||||
IntPtr hicon,
|
||||
ref int pi);
|
||||
|
||||
[PreserveSig]
|
||||
int SetOverlayImage(
|
||||
int iImage,
|
||||
int iOverlay);
|
||||
|
||||
[PreserveSig]
|
||||
int Replace(
|
||||
int i,
|
||||
IntPtr hbmImage,
|
||||
IntPtr hbmMask);
|
||||
|
||||
[PreserveSig]
|
||||
int AddMasked(
|
||||
IntPtr hbmImage,
|
||||
int crMask,
|
||||
ref int pi);
|
||||
|
||||
[PreserveSig]
|
||||
int Draw(
|
||||
ref IMAGELISTDRAWPARAMS pimldp);
|
||||
|
||||
[PreserveSig]
|
||||
int Remove(int i);
|
||||
|
||||
[PreserveSig]
|
||||
int GetIcon(
|
||||
int i,
|
||||
int flags,
|
||||
ref IntPtr picon);
|
||||
|
||||
[PreserveSig]
|
||||
int GetImageInfo(
|
||||
int i,
|
||||
ref IMAGEINFO pImageInfo);
|
||||
|
||||
[PreserveSig]
|
||||
int Copy(
|
||||
int iDst,
|
||||
IImageList punkSrc,
|
||||
int iSrc,
|
||||
int uFlags);
|
||||
|
||||
[PreserveSig]
|
||||
int Merge(
|
||||
int i1,
|
||||
IImageList punk2,
|
||||
int i2,
|
||||
int dx,
|
||||
int dy,
|
||||
ref Guid riid,
|
||||
ref IntPtr ppv);
|
||||
|
||||
[PreserveSig]
|
||||
int Clone(
|
||||
ref Guid riid,
|
||||
ref IntPtr ppv);
|
||||
|
||||
[PreserveSig]
|
||||
int GetImageRect(
|
||||
int i,
|
||||
ref RECT prc);
|
||||
|
||||
[PreserveSig]
|
||||
int GetIconSize(
|
||||
ref int cx,
|
||||
ref int cy);
|
||||
|
||||
[PreserveSig]
|
||||
int SetIconSize(
|
||||
int cx,
|
||||
int cy);
|
||||
|
||||
[PreserveSig]
|
||||
int GetImageCount(ref int pi);
|
||||
|
||||
[PreserveSig]
|
||||
int SetImageCount(
|
||||
int uNewCount);
|
||||
|
||||
[PreserveSig]
|
||||
int SetBkColor(
|
||||
int clrBk,
|
||||
ref int pclr);
|
||||
|
||||
[PreserveSig]
|
||||
int GetBkColor(
|
||||
ref int pclr);
|
||||
|
||||
[PreserveSig]
|
||||
int BeginDrag(
|
||||
int iTrack,
|
||||
int dxHotspot,
|
||||
int dyHotspot);
|
||||
|
||||
[PreserveSig]
|
||||
int EndDrag();
|
||||
|
||||
[PreserveSig]
|
||||
int DragEnter(
|
||||
IntPtr hwndLock,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
[PreserveSig]
|
||||
int DragLeave(
|
||||
IntPtr hwndLock);
|
||||
|
||||
[PreserveSig]
|
||||
int DragMove(
|
||||
int x,
|
||||
int y);
|
||||
|
||||
[PreserveSig]
|
||||
int SetDragCursorImage(
|
||||
ref IImageList punk,
|
||||
int iDrag,
|
||||
int dxHotspot,
|
||||
int dyHotspot);
|
||||
|
||||
[PreserveSig]
|
||||
int DragShowNolock(
|
||||
int fShow);
|
||||
|
||||
[PreserveSig]
|
||||
int GetDragImage(
|
||||
ref POINT ppt,
|
||||
ref POINT pptHotspot,
|
||||
ref Guid riid,
|
||||
ref IntPtr ppv);
|
||||
|
||||
[PreserveSig]
|
||||
int GetItemFlags(
|
||||
int i,
|
||||
ref int dwFlags);
|
||||
|
||||
[PreserveSig]
|
||||
int GetOverlayImage(
|
||||
int iOverlay,
|
||||
ref int piIndex);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
864
Util/ListViewDragDropManager.cs
Normal file
864
Util/ListViewDragDropManager.cs
Normal file
@@ -0,0 +1,864 @@
|
||||
// Copyright (C) Josh Smith - January 2007
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Input;
|
||||
using WPF.JoshSmith.Adorners;
|
||||
using WPF.JoshSmith.Controls.Utilities;
|
||||
|
||||
namespace WPF.JoshSmith.ServiceProviders.UI
|
||||
{
|
||||
#region ListViewDragDropManager
|
||||
|
||||
/// <summary>
|
||||
/// Manages the dragging and dropping of ListViewItems in a ListView.
|
||||
/// The ItemType type parameter indicates the type of the objects in
|
||||
/// the ListView's items source. The ListView's ItemsSource must be
|
||||
/// set to an instance of ObservableCollection of ItemType, or an
|
||||
/// Exception will be thrown.
|
||||
/// </summary>
|
||||
/// <typeparam name="ItemType">The type of the ListView's items.</typeparam>
|
||||
public class ListViewDragDropManager<ItemType> where ItemType : class
|
||||
{
|
||||
#region Data
|
||||
|
||||
bool canInitiateDrag;
|
||||
DragAdorner dragAdorner;
|
||||
double dragAdornerOpacity;
|
||||
int indexToSelect;
|
||||
bool isDragInProgress;
|
||||
ItemType itemUnderDragCursor;
|
||||
ListView listView;
|
||||
Point ptMouseDown;
|
||||
bool showDragAdorner;
|
||||
|
||||
#endregion // Data
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListViewDragManager.
|
||||
/// </summary>
|
||||
public ListViewDragDropManager()
|
||||
{
|
||||
this.canInitiateDrag = false;
|
||||
this.dragAdornerOpacity = 0.7;
|
||||
this.indexToSelect = -1;
|
||||
this.showDragAdorner = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListViewDragManager.
|
||||
/// </summary>
|
||||
/// <param name="listView"></param>
|
||||
public ListViewDragDropManager( ListView listView )
|
||||
: this()
|
||||
{
|
||||
this.ListView = listView;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListViewDragManager.
|
||||
/// </summary>
|
||||
/// <param name="listView"></param>
|
||||
/// <param name="dragAdornerOpacity"></param>
|
||||
public ListViewDragDropManager( ListView listView, double dragAdornerOpacity )
|
||||
: this( listView )
|
||||
{
|
||||
this.DragAdornerOpacity = dragAdornerOpacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of ListViewDragManager.
|
||||
/// </summary>
|
||||
/// <param name="listView"></param>
|
||||
/// <param name="showDragAdorner"></param>
|
||||
public ListViewDragDropManager( ListView listView, bool showDragAdorner )
|
||||
: this( listView )
|
||||
{
|
||||
this.ShowDragAdorner = showDragAdorner;
|
||||
}
|
||||
|
||||
#endregion // Constructors
|
||||
|
||||
#region Public Interface
|
||||
|
||||
#region DragAdornerOpacity
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the opacity of the drag adorner. This property has no
|
||||
/// effect if ShowDragAdorner is false. The default value is 0.7
|
||||
/// </summary>
|
||||
public double DragAdornerOpacity
|
||||
{
|
||||
get { return this.dragAdornerOpacity; }
|
||||
set
|
||||
{
|
||||
if( this.IsDragInProgress )
|
||||
throw new InvalidOperationException( "Cannot set the DragAdornerOpacity property during a drag operation." );
|
||||
|
||||
if( value < 0.0 || value > 1.0 )
|
||||
throw new ArgumentOutOfRangeException( "DragAdornerOpacity", value, "Must be between 0 and 1." );
|
||||
|
||||
this.dragAdornerOpacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // DragAdornerOpacity
|
||||
|
||||
#region IsDragInProgress
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if there is currently a drag operation being managed.
|
||||
/// </summary>
|
||||
public bool IsDragInProgress
|
||||
{
|
||||
get { return this.isDragInProgress; }
|
||||
private set { this.isDragInProgress = value; }
|
||||
}
|
||||
|
||||
#endregion // IsDragInProgress
|
||||
|
||||
#region ListView
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the ListView whose dragging is managed. This property
|
||||
/// can be set to null, to prevent drag management from occuring. If
|
||||
/// the ListView's AllowDrop property is false, it will be set to true.
|
||||
/// </summary>
|
||||
public ListView ListView
|
||||
{
|
||||
get { return listView; }
|
||||
set
|
||||
{
|
||||
if( this.IsDragInProgress )
|
||||
throw new InvalidOperationException( "Cannot set the ListView property during a drag operation." );
|
||||
|
||||
if( this.listView != null )
|
||||
{
|
||||
#region Unhook Events
|
||||
|
||||
this.listView.PreviewMouseLeftButtonDown -= listView_PreviewMouseLeftButtonDown;
|
||||
this.listView.PreviewMouseMove -= listView_PreviewMouseMove;
|
||||
this.listView.DragOver -= listView_DragOver;
|
||||
this.listView.DragLeave -= listView_DragLeave;
|
||||
this.listView.DragEnter -= listView_DragEnter;
|
||||
this.listView.Drop -= listView_Drop;
|
||||
|
||||
#endregion // Unhook Events
|
||||
}
|
||||
|
||||
this.listView = value;
|
||||
|
||||
if( this.listView != null )
|
||||
{
|
||||
if( !this.listView.AllowDrop )
|
||||
this.listView.AllowDrop = true;
|
||||
|
||||
#region Hook Events
|
||||
|
||||
this.listView.PreviewMouseLeftButtonDown += listView_PreviewMouseLeftButtonDown;
|
||||
this.listView.PreviewMouseMove += listView_PreviewMouseMove;
|
||||
this.listView.DragOver += listView_DragOver;
|
||||
this.listView.DragLeave += listView_DragLeave;
|
||||
this.listView.DragEnter += listView_DragEnter;
|
||||
this.listView.Drop += listView_Drop;
|
||||
|
||||
#endregion // Hook Events
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // ListView
|
||||
|
||||
#region ProcessDrop [event]
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a drop occurs. By default the dropped item will be moved
|
||||
/// to the target index. Handle this event if relocating the dropped item
|
||||
/// requires custom behavior. Note, if this event is handled the default
|
||||
/// item dropping logic will not occur.
|
||||
/// </summary>
|
||||
public event EventHandler<ProcessDropEventArgs<ItemType>> ProcessDrop;
|
||||
|
||||
#endregion // ProcessDrop [event]
|
||||
|
||||
#region ShowDragAdorner
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets whether a visual representation of the ListViewItem being dragged
|
||||
/// follows the mouse cursor during a drag operation. The default value is true.
|
||||
/// </summary>
|
||||
public bool ShowDragAdorner
|
||||
{
|
||||
get { return this.showDragAdorner; }
|
||||
set
|
||||
{
|
||||
if( this.IsDragInProgress )
|
||||
throw new InvalidOperationException( "Cannot set the ShowDragAdorner property during a drag operation." );
|
||||
|
||||
this.showDragAdorner = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // ShowDragAdorner
|
||||
|
||||
#endregion // Public Interface
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
#region listView_PreviewMouseLeftButtonDown
|
||||
|
||||
void listView_PreviewMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
|
||||
{
|
||||
if( this.IsMouseOverScrollbar )
|
||||
{
|
||||
// 4/13/2007 - Set the flag to false when cursor is over scrollbar.
|
||||
this.canInitiateDrag = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int index = this.IndexUnderDragCursor;
|
||||
this.canInitiateDrag = index > -1;
|
||||
|
||||
if( this.canInitiateDrag )
|
||||
{
|
||||
// Remember the location and index of the ListViewItem the user clicked on for later.
|
||||
this.ptMouseDown = MouseUtilities.GetMousePosition( this.listView );
|
||||
this.indexToSelect = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ptMouseDown = new Point( -10000, -10000 );
|
||||
this.indexToSelect = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // listView_PreviewMouseLeftButtonDown
|
||||
|
||||
#region listView_PreviewMouseMove
|
||||
|
||||
void listView_PreviewMouseMove( object sender, MouseEventArgs e )
|
||||
{
|
||||
if( !this.CanStartDragOperation )
|
||||
return;
|
||||
|
||||
// Select the item the user clicked on.
|
||||
if( this.listView.SelectedIndex != this.indexToSelect )
|
||||
this.listView.SelectedIndex = this.indexToSelect;
|
||||
|
||||
// If the item at the selected index is null, there's nothing
|
||||
// we can do, so just return;
|
||||
if( this.listView.SelectedItem == null )
|
||||
return;
|
||||
|
||||
ListViewItem itemToDrag = this.GetListViewItem( this.listView.SelectedIndex );
|
||||
if( itemToDrag == null )
|
||||
return;
|
||||
|
||||
AdornerLayer adornerLayer = this.ShowDragAdornerResolved ? this.InitializeAdornerLayer( itemToDrag ) : null;
|
||||
|
||||
this.InitializeDragOperation( itemToDrag );
|
||||
this.PerformDragOperation();
|
||||
this.FinishDragOperation( itemToDrag, adornerLayer );
|
||||
}
|
||||
|
||||
#endregion // listView_PreviewMouseMove
|
||||
|
||||
#region listView_DragOver
|
||||
|
||||
void listView_DragOver( object sender, DragEventArgs e )
|
||||
{
|
||||
e.Effects = DragDropEffects.Move;
|
||||
|
||||
if( this.ShowDragAdornerResolved )
|
||||
this.UpdateDragAdornerLocation();
|
||||
|
||||
// Update the item which is known to be currently under the drag cursor.
|
||||
int index = this.IndexUnderDragCursor;
|
||||
this.ItemUnderDragCursor = index < 0 ? null : this.ListView.Items[index] as ItemType;
|
||||
}
|
||||
|
||||
#endregion // listView_DragOver
|
||||
|
||||
#region listView_DragLeave
|
||||
|
||||
void listView_DragLeave( object sender, DragEventArgs e )
|
||||
{
|
||||
if( !this.IsMouseOver( this.listView ) )
|
||||
{
|
||||
if( this.ItemUnderDragCursor != null )
|
||||
this.ItemUnderDragCursor = null;
|
||||
|
||||
if( this.dragAdorner != null )
|
||||
this.dragAdorner.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // listView_DragLeave
|
||||
|
||||
#region listView_DragEnter
|
||||
|
||||
void listView_DragEnter( object sender, DragEventArgs e )
|
||||
{
|
||||
if( this.dragAdorner != null && this.dragAdorner.Visibility != Visibility.Visible )
|
||||
{
|
||||
// Update the location of the adorner and then show it.
|
||||
this.UpdateDragAdornerLocation();
|
||||
this.dragAdorner.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // listView_DragEnter
|
||||
|
||||
#region listView_Drop
|
||||
|
||||
void listView_Drop( object sender, DragEventArgs e )
|
||||
{
|
||||
if( this.ItemUnderDragCursor != null )
|
||||
this.ItemUnderDragCursor = null;
|
||||
|
||||
e.Effects = DragDropEffects.None;
|
||||
|
||||
if( !e.Data.GetDataPresent( typeof( ItemType ) ) )
|
||||
return;
|
||||
|
||||
// Get the data object which was dropped.
|
||||
ItemType data = e.Data.GetData( typeof( ItemType ) ) as ItemType;
|
||||
if( data == null )
|
||||
return;
|
||||
|
||||
// Get the ObservableCollection<ItemType> which contains the dropped data object.
|
||||
ObservableCollection<ItemType> itemsSource = this.listView.ItemsSource as ObservableCollection<ItemType>;
|
||||
if( itemsSource == null )
|
||||
throw new Exception(
|
||||
"A ListView managed by ListViewDragManager must have its ItemsSource set to an ObservableCollection<ItemType>." );
|
||||
|
||||
int oldIndex = itemsSource.IndexOf( data );
|
||||
int newIndex = this.IndexUnderDragCursor;
|
||||
|
||||
if( newIndex < 0 )
|
||||
{
|
||||
// The drag started somewhere else, and our ListView is empty
|
||||
// so make the new item the first in the list.
|
||||
if( itemsSource.Count == 0 )
|
||||
newIndex = 0;
|
||||
|
||||
// The drag started somewhere else, but our ListView has items
|
||||
// so make the new item the last in the list.
|
||||
else if( oldIndex < 0 )
|
||||
newIndex = itemsSource.Count;
|
||||
|
||||
// The user is trying to drop an item from our ListView into
|
||||
// our ListView, but the mouse is not over an item, so don't
|
||||
// let them drop it.
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// Dropping an item back onto itself is not considered an actual 'drop'.
|
||||
if( oldIndex == newIndex )
|
||||
return;
|
||||
|
||||
if( this.ProcessDrop != null )
|
||||
{
|
||||
// Let the client code process the drop.
|
||||
ProcessDropEventArgs<ItemType> args = new ProcessDropEventArgs<ItemType>( itemsSource, data, oldIndex, newIndex, e.AllowedEffects );
|
||||
this.ProcessDrop( this, args );
|
||||
e.Effects = args.Effects;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move the dragged data object from it's original index to the
|
||||
// new index (according to where the mouse cursor is). If it was
|
||||
// not previously in the ListBox, then insert the item.
|
||||
if( oldIndex > -1 )
|
||||
itemsSource.Move( oldIndex, newIndex );
|
||||
else
|
||||
itemsSource.Insert( newIndex, data );
|
||||
|
||||
// Set the Effects property so that the call to DoDragDrop will return 'Move'.
|
||||
e.Effects = DragDropEffects.Move;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // listView_Drop
|
||||
|
||||
#endregion // Event Handling Methods
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
#region CanStartDragOperation
|
||||
|
||||
bool CanStartDragOperation
|
||||
{
|
||||
get
|
||||
{
|
||||
if( Mouse.LeftButton != MouseButtonState.Pressed )
|
||||
return false;
|
||||
|
||||
if( !this.canInitiateDrag )
|
||||
return false;
|
||||
|
||||
if( this.indexToSelect == -1 )
|
||||
return false;
|
||||
|
||||
if( !this.HasCursorLeftDragThreshold )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // CanStartDragOperation
|
||||
|
||||
#region FinishDragOperation
|
||||
|
||||
void FinishDragOperation( ListViewItem draggedItem, AdornerLayer adornerLayer )
|
||||
{
|
||||
// Let the ListViewItem know that it is not being dragged anymore.
|
||||
ListViewItemDragState.SetIsBeingDragged( draggedItem, false );
|
||||
|
||||
this.IsDragInProgress = false;
|
||||
|
||||
if( this.ItemUnderDragCursor != null )
|
||||
this.ItemUnderDragCursor = null;
|
||||
|
||||
// Remove the drag adorner from the adorner layer.
|
||||
if( adornerLayer != null )
|
||||
{
|
||||
adornerLayer.Remove( this.dragAdorner );
|
||||
this.dragAdorner = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // FinishDragOperation
|
||||
|
||||
#region GetListViewItem
|
||||
|
||||
ListViewItem GetListViewItem( int index )
|
||||
{
|
||||
if( this.listView.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated )
|
||||
return null;
|
||||
|
||||
return this.listView.ItemContainerGenerator.ContainerFromIndex( index ) as ListViewItem;
|
||||
}
|
||||
|
||||
ListViewItem GetListViewItem( ItemType dataItem )
|
||||
{
|
||||
if( this.listView.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated )
|
||||
return null;
|
||||
|
||||
return this.listView.ItemContainerGenerator.ContainerFromItem( dataItem ) as ListViewItem;
|
||||
}
|
||||
|
||||
#endregion // GetListViewItem
|
||||
|
||||
#region HasCursorLeftDragThreshold
|
||||
|
||||
bool HasCursorLeftDragThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
if( this.indexToSelect < 0 )
|
||||
return false;
|
||||
|
||||
ListViewItem item = this.GetListViewItem( this.indexToSelect );
|
||||
Rect bounds = VisualTreeHelper.GetDescendantBounds( item );
|
||||
Point ptInItem = this.listView.TranslatePoint( this.ptMouseDown, item );
|
||||
|
||||
// In case the cursor is at the very top or bottom of the ListViewItem
|
||||
// we want to make the vertical threshold very small so that dragging
|
||||
// over an adjacent item does not select it.
|
||||
double topOffset = Math.Abs( ptInItem.Y );
|
||||
double btmOffset = Math.Abs( bounds.Height - ptInItem.Y );
|
||||
double vertOffset = Math.Min( topOffset, btmOffset );
|
||||
|
||||
double width = SystemParameters.MinimumHorizontalDragDistance * 2;
|
||||
double height = Math.Min( SystemParameters.MinimumVerticalDragDistance, vertOffset ) * 2;
|
||||
Size szThreshold = new Size( width, height );
|
||||
|
||||
Rect rect = new Rect( this.ptMouseDown, szThreshold );
|
||||
rect.Offset( szThreshold.Width / -2, szThreshold.Height / -2 );
|
||||
Point ptInListView = MouseUtilities.GetMousePosition( this.listView );
|
||||
return !rect.Contains( ptInListView );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // HasCursorLeftDragThreshold
|
||||
|
||||
#region IndexUnderDragCursor
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the ListViewItem underneath the
|
||||
/// drag cursor, or -1 if the cursor is not over an item.
|
||||
/// </summary>
|
||||
int IndexUnderDragCursor
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = -1;
|
||||
for( int i = 0; i < this.listView.Items.Count; ++i )
|
||||
{
|
||||
ListViewItem item = this.GetListViewItem( i );
|
||||
if( this.IsMouseOver( item ) )
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // IndexUnderDragCursor
|
||||
|
||||
#region InitializeAdornerLayer
|
||||
|
||||
AdornerLayer InitializeAdornerLayer( ListViewItem itemToDrag )
|
||||
{
|
||||
// Create a brush which will paint the ListViewItem onto
|
||||
// a visual in the adorner layer.
|
||||
VisualBrush brush = new VisualBrush( itemToDrag );
|
||||
|
||||
// Create an element which displays the source item while it is dragged.
|
||||
this.dragAdorner = new DragAdorner( this.listView, itemToDrag.RenderSize, brush );
|
||||
|
||||
// Set the drag adorner's opacity.
|
||||
this.dragAdorner.Opacity = this.DragAdornerOpacity;
|
||||
|
||||
AdornerLayer layer = AdornerLayer.GetAdornerLayer( this.listView );
|
||||
layer.Add( dragAdorner );
|
||||
|
||||
// Save the location of the cursor when the left mouse button was pressed.
|
||||
this.ptMouseDown = MouseUtilities.GetMousePosition( this.listView );
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
#endregion // InitializeAdornerLayer
|
||||
|
||||
#region InitializeDragOperation
|
||||
|
||||
void InitializeDragOperation( ListViewItem itemToDrag )
|
||||
{
|
||||
// Set some flags used during the drag operation.
|
||||
this.IsDragInProgress = true;
|
||||
this.canInitiateDrag = false;
|
||||
|
||||
// Let the ListViewItem know that it is being dragged.
|
||||
ListViewItemDragState.SetIsBeingDragged( itemToDrag, true );
|
||||
}
|
||||
|
||||
#endregion // InitializeDragOperation
|
||||
|
||||
#region IsMouseOver
|
||||
|
||||
bool IsMouseOver( Visual target )
|
||||
{
|
||||
// We need to use MouseUtilities to figure out the cursor
|
||||
// coordinates because, during a drag-drop operation, the WPF
|
||||
// mechanisms for getting the coordinates behave strangely.
|
||||
|
||||
Rect bounds = VisualTreeHelper.GetDescendantBounds( target );
|
||||
Point mousePos = MouseUtilities.GetMousePosition( target );
|
||||
return bounds.Contains( mousePos );
|
||||
}
|
||||
|
||||
#endregion // IsMouseOver
|
||||
|
||||
#region IsMouseOverScrollbar
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the mouse cursor is over a scrollbar in the ListView.
|
||||
/// </summary>
|
||||
bool IsMouseOverScrollbar
|
||||
{
|
||||
get
|
||||
{
|
||||
Point ptMouse = MouseUtilities.GetMousePosition( this.listView );
|
||||
HitTestResult res = VisualTreeHelper.HitTest( this.listView, ptMouse );
|
||||
if( res == null )
|
||||
return false;
|
||||
|
||||
DependencyObject depObj = res.VisualHit;
|
||||
while( depObj != null )
|
||||
{
|
||||
if( depObj is ScrollBar )
|
||||
return true;
|
||||
|
||||
// VisualTreeHelper works with objects of type Visual or Visual3D.
|
||||
// If the current object is not derived from Visual or Visual3D,
|
||||
// then use the LogicalTreeHelper to find the parent element.
|
||||
if( depObj is Visual || depObj is System.Windows.Media.Media3D.Visual3D )
|
||||
depObj = VisualTreeHelper.GetParent( depObj );
|
||||
else
|
||||
depObj = LogicalTreeHelper.GetParent( depObj );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // IsMouseOverScrollbar
|
||||
|
||||
#region ItemUnderDragCursor
|
||||
|
||||
ItemType ItemUnderDragCursor
|
||||
{
|
||||
get { return this.itemUnderDragCursor; }
|
||||
set
|
||||
{
|
||||
if( this.itemUnderDragCursor == value )
|
||||
return;
|
||||
|
||||
// The first pass handles the previous item under the cursor.
|
||||
// The second pass handles the new one.
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
if( i == 1 )
|
||||
this.itemUnderDragCursor = value;
|
||||
|
||||
if( this.itemUnderDragCursor != null )
|
||||
{
|
||||
ListViewItem listViewItem = this.GetListViewItem( this.itemUnderDragCursor );
|
||||
if( listViewItem != null )
|
||||
ListViewItemDragState.SetIsUnderDragCursor( listViewItem, i == 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // ItemUnderDragCursor
|
||||
|
||||
#region PerformDragOperation
|
||||
|
||||
void PerformDragOperation()
|
||||
{
|
||||
ItemType selectedItem = this.listView.SelectedItem as ItemType;
|
||||
DragDropEffects allowedEffects = DragDropEffects.Move | DragDropEffects.Move | DragDropEffects.Link;
|
||||
if( DragDrop.DoDragDrop( this.listView, selectedItem, allowedEffects ) != DragDropEffects.None )
|
||||
{
|
||||
// The item was dropped into a new location,
|
||||
// so make it the new selected item.
|
||||
this.listView.SelectedItem = selectedItem;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // PerformDragOperation
|
||||
|
||||
#region ShowDragAdornerResolved
|
||||
|
||||
bool ShowDragAdornerResolved
|
||||
{
|
||||
get { return this.ShowDragAdorner && this.DragAdornerOpacity > 0.0; }
|
||||
}
|
||||
|
||||
#endregion // ShowDragAdornerResolved
|
||||
|
||||
#region UpdateDragAdornerLocation
|
||||
|
||||
void UpdateDragAdornerLocation()
|
||||
{
|
||||
if( this.dragAdorner != null )
|
||||
{
|
||||
Point ptCursor = MouseUtilities.GetMousePosition( this.ListView );
|
||||
|
||||
double left = ptCursor.X - this.ptMouseDown.X;
|
||||
|
||||
// 4/13/2007 - Made the top offset relative to the item being dragged.
|
||||
ListViewItem itemBeingDragged = this.GetListViewItem( this.indexToSelect );
|
||||
Point itemLoc = itemBeingDragged.TranslatePoint( new Point( 0, 0 ), this.ListView );
|
||||
double top = itemLoc.Y + ptCursor.Y - this.ptMouseDown.Y;
|
||||
|
||||
this.dragAdorner.SetOffsets( left, top );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // UpdateDragAdornerLocation
|
||||
|
||||
#endregion // Private Helpers
|
||||
}
|
||||
|
||||
#endregion // ListViewDragDropManager
|
||||
|
||||
#region ListViewItemDragState
|
||||
|
||||
/// <summary>
|
||||
/// Exposes attached properties used in conjunction with the ListViewDragDropManager class.
|
||||
/// Those properties can be used to allow triggers to modify the appearance of ListViewItems
|
||||
/// in a ListView during a drag-drop operation.
|
||||
/// </summary>
|
||||
public static class ListViewItemDragState
|
||||
{
|
||||
#region IsBeingDragged
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the ListViewItemDragState's IsBeingDragged attached property.
|
||||
/// This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsBeingDraggedProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"IsBeingDragged",
|
||||
typeof( bool ),
|
||||
typeof( ListViewItemDragState ),
|
||||
new UIPropertyMetadata( false ) );
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified ListViewItem is being dragged, else false.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListViewItem to check.</param>
|
||||
public static bool GetIsBeingDragged( ListViewItem item )
|
||||
{
|
||||
return (bool)item.GetValue( IsBeingDraggedProperty );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the IsBeingDragged attached property for the specified ListViewItem.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListViewItem to set the property on.</param>
|
||||
/// <param name="value">Pass true if the element is being dragged, else false.</param>
|
||||
internal static void SetIsBeingDragged( ListViewItem item, bool value )
|
||||
{
|
||||
item.SetValue( IsBeingDraggedProperty, value );
|
||||
}
|
||||
|
||||
#endregion // IsBeingDragged
|
||||
|
||||
#region IsUnderDragCursor
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the ListViewItemDragState's IsUnderDragCursor attached property.
|
||||
/// This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsUnderDragCursorProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"IsUnderDragCursor",
|
||||
typeof( bool ),
|
||||
typeof( ListViewItemDragState ),
|
||||
new UIPropertyMetadata( false ) );
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the specified ListViewItem is currently underneath the cursor
|
||||
/// during a drag-drop operation, else false.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListViewItem to check.</param>
|
||||
public static bool GetIsUnderDragCursor( ListViewItem item )
|
||||
{
|
||||
return (bool)item.GetValue( IsUnderDragCursorProperty );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the IsUnderDragCursor attached property for the specified ListViewItem.
|
||||
/// </summary>
|
||||
/// <param name="item">The ListViewItem to set the property on.</param>
|
||||
/// <param name="value">Pass true if the element is underneath the drag cursor, else false.</param>
|
||||
internal static void SetIsUnderDragCursor( ListViewItem item, bool value )
|
||||
{
|
||||
item.SetValue( IsUnderDragCursorProperty, value );
|
||||
}
|
||||
|
||||
#endregion // IsUnderDragCursor
|
||||
}
|
||||
|
||||
#endregion // ListViewItemDragState
|
||||
|
||||
#region ProcessDropEventArgs
|
||||
|
||||
/// <summary>
|
||||
/// Event arguments used by the ListViewDragDropManager.ProcessDrop event.
|
||||
/// </summary>
|
||||
/// <typeparam name="ItemType">The type of data object being dropped.</typeparam>
|
||||
public class ProcessDropEventArgs<ItemType> : EventArgs where ItemType : class
|
||||
{
|
||||
#region Data
|
||||
|
||||
ObservableCollection<ItemType> itemsSource;
|
||||
ItemType dataItem;
|
||||
int oldIndex;
|
||||
int newIndex;
|
||||
DragDropEffects allowedEffects = DragDropEffects.None;
|
||||
DragDropEffects effects = DragDropEffects.None;
|
||||
|
||||
#endregion // Data
|
||||
|
||||
#region Constructor
|
||||
|
||||
internal ProcessDropEventArgs(
|
||||
ObservableCollection<ItemType> itemsSource,
|
||||
ItemType dataItem,
|
||||
int oldIndex,
|
||||
int newIndex,
|
||||
DragDropEffects allowedEffects )
|
||||
{
|
||||
this.itemsSource = itemsSource;
|
||||
this.dataItem = dataItem;
|
||||
this.oldIndex = oldIndex;
|
||||
this.newIndex = newIndex;
|
||||
this.allowedEffects = allowedEffects;
|
||||
}
|
||||
|
||||
#endregion // Constructor
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// The items source of the ListView where the drop occurred.
|
||||
/// </summary>
|
||||
public ObservableCollection<ItemType> ItemsSource
|
||||
{
|
||||
get { return this.itemsSource; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The data object which was dropped.
|
||||
/// </summary>
|
||||
public ItemType DataItem
|
||||
{
|
||||
get { return this.dataItem; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current index of the data item being dropped, in the ItemsSource collection.
|
||||
/// </summary>
|
||||
public int OldIndex
|
||||
{
|
||||
get { return this.oldIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target index of the data item being dropped, in the ItemsSource collection.
|
||||
/// </summary>
|
||||
public int NewIndex
|
||||
{
|
||||
get { return this.newIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The drag drop effects allowed to be performed.
|
||||
/// </summary>
|
||||
public DragDropEffects AllowedEffects
|
||||
{
|
||||
get { return allowedEffects; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The drag drop effect(s) performed on the dropped item.
|
||||
/// </summary>
|
||||
public DragDropEffects Effects
|
||||
{
|
||||
get { return effects; }
|
||||
set { effects = value; }
|
||||
}
|
||||
|
||||
#endregion // Public Properties
|
||||
}
|
||||
|
||||
#endregion // ProcessDropEventArgs
|
||||
}
|
||||
29
Util/MenuWidthConvert.cs
Normal file
29
Util/MenuWidthConvert.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
class MenuWidthConvert : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value != null && value.ToString().Length>0)
|
||||
{
|
||||
return System.Convert.ToDouble(value.ToString()) - 10d;
|
||||
} else
|
||||
{
|
||||
return 0d;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Util/MouseUtilities.cs
Normal file
58
Util/MouseUtilities.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace WPF.JoshSmith.Controls.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to the mouse location by calling unmanaged code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class was written by Dan Crevier (Microsoft).
|
||||
/// http://blogs.msdn.com/llobo/archive/2006/09/06/Scrolling-Scrollviewer-on-Mouse-Drag-at-the-boundaries.aspx
|
||||
/// </remarks>
|
||||
public class MouseUtilities
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
private struct Win32Point
|
||||
{
|
||||
public Int32 X;
|
||||
public Int32 Y;
|
||||
};
|
||||
|
||||
[DllImport( "user32.dll" )]
|
||||
private static extern bool GetCursorPos( ref Win32Point pt );
|
||||
|
||||
[DllImport( "user32.dll" )]
|
||||
private static extern bool ScreenToClient( IntPtr hwnd, ref Win32Point pt );
|
||||
|
||||
/// <summary>
|
||||
/// Returns the mouse cursor location. This method is necessary during
|
||||
/// a drag-drop operation because the WPF mechanisms for retrieving the
|
||||
/// cursor coordinates are unreliable.
|
||||
/// </summary>
|
||||
/// <param name="relativeTo">The Visual to which the mouse coordinates will be relative.</param>
|
||||
public static Point GetMousePosition( Visual relativeTo )
|
||||
{
|
||||
Win32Point mouse = new Win32Point();
|
||||
GetCursorPos( ref mouse );
|
||||
|
||||
// Using PointFromScreen instead of Dan Crevier's code (commented out below)
|
||||
// is a bug fix created by William J. Roberts. Read his comments about the fix
|
||||
// here: http://www.codeproject.com/useritems/ListViewDragDropManager.asp?msg=1911611#xx1911611xx
|
||||
return relativeTo.PointFromScreen( new Point( (double)mouse.X, (double)mouse.Y ) );
|
||||
|
||||
#region Commented Out
|
||||
//System.Windows.Interop.HwndSource presentationSource =
|
||||
// (System.Windows.Interop.HwndSource)PresentationSource.FromVisual( relativeTo );
|
||||
//ScreenToClient( presentationSource.Handle, ref mouse );
|
||||
//GeneralTransform transform = relativeTo.TransformToAncestor( presentationSource.RootVisual );
|
||||
//Point offset = transform.Transform( new Point( 0, 0 ) );
|
||||
//return new Point( mouse.X - offset.X, mouse.Y - offset.Y );
|
||||
#endregion // Commented Out
|
||||
}
|
||||
}
|
||||
}
|
||||
152
Util/SystemIcon.cs
Normal file
152
Util/SystemIcon.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using Microsoft.Win32;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Drawing.Imaging;
|
||||
using GeekDesk.Util;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
class SystemIcon
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct SHFILEINFO
|
||||
{
|
||||
public IntPtr hIcon;
|
||||
public int iIcon;
|
||||
public uint dwAttributes;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szDisplayName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||
public string szTypeName;
|
||||
}
|
||||
[DllImport("Shell32.dll", EntryPoint = "SHGetFileInfo", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
|
||||
[DllImport("User32.dll", EntryPoint = "DestroyIcon")]
|
||||
public static extern int DestroyIcon(IntPtr hIcon);
|
||||
#region API 参数的常量定义
|
||||
public enum FileInfoFlags : uint
|
||||
{
|
||||
SHGFI_ICON = 0x000000100, // get icon
|
||||
SHGFI_DISPLAYNAME = 0x000000200, // get display name
|
||||
SHGFI_TYPENAME = 0x000000400, // get type name
|
||||
SHGFI_ATTRIBUTES = 0x000000800, // get attributes
|
||||
SHGFI_ICONLOCATION = 0x000001000, // get icon location
|
||||
SHGFI_EXETYPE = 0x000002000, // return exe type
|
||||
SHGFI_SYSICONINDEX = 0x000004000, // get system icon index
|
||||
SHGFI_LINKOVERLAY = 0x000008000, // put a link overlay on icon
|
||||
SHGFI_SELECTED = 0x000010000, // show icon in selected state
|
||||
SHGFI_ATTR_SPECIFIED = 0x000020000, // get only specified attributes
|
||||
SHGFI_LARGEICON = 0x000000000, // get large icon
|
||||
SHGFI_SMALLICON = 0x000000001, // get small icon
|
||||
SHGFI_OPENICON = 0x000000002, // get open icon
|
||||
SHGFI_SHELLICONSIZE = 0x000000004, // get shell size icon
|
||||
SHGFI_PIDL = 0x000000008, // pszPath is a pidl
|
||||
SHGFI_USEFILEATTRIBUTES = 0x000000010, // use passed dwFileAttribute
|
||||
SHGFI_ADDOVERLAYS = 0x000000020, // apply the appropriate overlays
|
||||
SHGFI_OVERLAYINDEX = 0x000000040 // Get the index of the overlay
|
||||
}
|
||||
public enum FileAttributeFlags : uint
|
||||
{
|
||||
FILE_ATTRIBUTE_READONLY = 0x00000001,
|
||||
FILE_ATTRIBUTE_HIDDEN = 0x00000002,
|
||||
FILE_ATTRIBUTE_SYSTEM = 0x00000004,
|
||||
FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
|
||||
FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
|
||||
FILE_ATTRIBUTE_DEVICE = 0x00000040,
|
||||
FILE_ATTRIBUTE_NORMAL = 0x00000080,
|
||||
FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
|
||||
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
|
||||
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
|
||||
FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
|
||||
FILE_ATTRIBUTE_OFFLINE = 0x00001000,
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
|
||||
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
|
||||
}
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// 获取文件类型的关联图标
|
||||
/// </summary>
|
||||
/// <param name="fileName">文件类型的扩展名或文件的绝对路径</param>
|
||||
/// <param name="isLargeIcon">是否返回大图标</param>
|
||||
/// <returns>获取到的图标</returns>
|
||||
public static Icon GetIcon(string fileName, bool isLargeIcon)
|
||||
{
|
||||
//SHFILEINFO shfi = new SHFILEINFO();
|
||||
//IntPtr hI;
|
||||
//if (isLargeIcon)
|
||||
// hI = SHGetFileInfo(fileName, 0, ref shfi, (uint)Marshal.SizeOf(shfi), (uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (uint)FileInfoFlags.SHGFI_LARGEICON);
|
||||
//else
|
||||
// hI = SHGetFileInfo(fileName, 0, ref shfi, (uint)Marshal.SizeOf(shfi), (uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (uint)FileInfoFlags.SHGFI_SMALLICON);
|
||||
//Icon icon = Icon.FromHandle(shfi.hIcon).Clone() as Icon;
|
||||
//DestroyIcon(shfi.hIcon); //释放资源
|
||||
|
||||
//选中文件中的图标总数
|
||||
//var iconTotalCount = PrivateExtractIcons(fileName, 0, 0, 0, null, null, 1, 0);
|
||||
//用于接收获取到的图标指针
|
||||
//IntPtr[] hIcons = new IntPtr[1];
|
||||
////对应的图标id
|
||||
//int[] ids = new int[1];
|
||||
////成功获取到的图标个数
|
||||
//int successCount = PrivateExtractIcons(fileName, 0, 0, 0, hIcons, ids, 1, 0);
|
||||
//Icon ico = Icon.FromHandle(hIcons[0]);
|
||||
//var myIcon = ico.ToBitmap();
|
||||
//myIcon.Save("D:\\" + ids[0].ToString("000") + ".png", ImageFormat.Png);
|
||||
IntPtr hIcon = FileIcon.GetJumboIcon(FileIcon.GetIconIndex(fileName));
|
||||
//IntPtr hIcon = GetJumboIcon(GetIconIndex("*." + ext));
|
||||
|
||||
// from native to managed
|
||||
Icon ico = Icon.FromHandle(hIcon);
|
||||
string path = "D:\\test\\" + System.Guid.NewGuid().ToString() + ".png";
|
||||
//using ( ico = (Icon)Icon.FromHandle(hIcon).Clone())
|
||||
//{
|
||||
// // save to file (or show in a picture box)
|
||||
// ico.ToBitmap().Save(path, ImageFormat.Png);
|
||||
//}
|
||||
//FileIcon.Shell32.DestroyIcon(hIcon); // don't forget to cleanup
|
||||
|
||||
return ico;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取文件夹图标
|
||||
/// </summary>
|
||||
/// <returns>图标</returns>
|
||||
public static Icon GetDirectoryIcon(bool isLargeIcon)
|
||||
{
|
||||
SHFILEINFO _SHFILEINFO = new SHFILEINFO();
|
||||
IntPtr _IconIntPtr;
|
||||
if (isLargeIcon)
|
||||
{
|
||||
_IconIntPtr = SHGetFileInfo(@"", 0, ref _SHFILEINFO, (uint)Marshal.SizeOf(_SHFILEINFO), ((uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_LARGEICON));
|
||||
}
|
||||
else
|
||||
{
|
||||
_IconIntPtr = SHGetFileInfo(@"", 0, ref _SHFILEINFO, (uint)Marshal.SizeOf(_SHFILEINFO), ((uint)FileInfoFlags.SHGFI_ICON | (uint)FileInfoFlags.SHGFI_SMALLICON));
|
||||
}
|
||||
if (_IconIntPtr.Equals(IntPtr.Zero)) return null;
|
||||
Icon _Icon = System.Drawing.Icon.FromHandle(_SHFILEINFO.hIcon);
|
||||
return _Icon;
|
||||
}
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
public static extern int PrivateExtractIcons(
|
||||
string lpszFile, //file name
|
||||
int nIconIndex, //The zero-based index of the first icon to extract.
|
||||
int cxIcon, //The horizontal icon size wanted.
|
||||
int cyIcon, //The vertical icon size wanted.
|
||||
IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
|
||||
int[] piconid, //(out) A pointer to a returned resource identifier.
|
||||
int nIcons, //The number of icons to extract from the file. Only valid when *.exe and *.dll
|
||||
int flags //Specifies flags that control this function.
|
||||
);
|
||||
|
||||
//[DllImport("User32.dll")]
|
||||
//public static extern bool DestroyIcon(
|
||||
// IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
|
||||
// );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user