diff --git a/Business/Menus.cs b/Business/Menus.cs index b67d9f9..fe7c464 100644 --- a/Business/Menus.cs +++ b/Business/Menus.cs @@ -537,7 +537,7 @@ namespace SystemTrayMenu.Business dgv.Rows.Count > hitTestInfo.RowIndex) { RowData trigger = (RowData)dgv.Rows[hitTestInfo.RowIndex].Tag; - trigger.DoubleClick(); + trigger.DoubleClick(e); } } diff --git a/DataClasses/RowData.cs b/DataClasses/RowData.cs index 9107fa4..10918d9 100644 --- a/DataClasses/RowData.cs +++ b/DataClasses/RowData.cs @@ -26,6 +26,7 @@ namespace SystemTrayMenu.DataClasses internal bool IsSelectedByKeyboard; internal bool ContainsMenu; internal bool IsContextMenuOpen; + private static DateTime ContextMenuClosed; internal bool IsResolvedLnk; internal bool IsLoading = false; internal bool RestartLoading = false; @@ -337,11 +338,13 @@ namespace SystemTrayMenu.DataClasses e.Button == MouseButtons.Right && FileInfo != null && dgv != null && - dgv.Rows.Count > RowIndex) + dgv.Rows.Count > RowIndex && + (DateTime.Now - ContextMenuClosed).TotalMilliseconds > 200) { IsContextMenuOpen = true; - IsSelected = true; - dgv.Rows[RowIndex].Selected = true; + Color colorbefore = dgv.Rows[RowIndex].DefaultCellStyle.SelectionBackColor; + dgv.Rows[RowIndex].DefaultCellStyle.SelectionBackColor = + MenuDefines.ColorSelectedItem; ShellContextMenu ctxMnu = new ShellContextMenu(); Point location = dgv.FindForm().Location; @@ -363,17 +366,19 @@ namespace SystemTrayMenu.DataClasses if (!dgv.IsDisposed) { - IsSelected = false; - dgv.Rows[RowIndex].Selected = false; + dgv.Rows[RowIndex].DefaultCellStyle.SelectionBackColor = colorbefore; } IsContextMenuOpen = false; + ContextMenuClosed = DateTime.Now; } } - internal void DoubleClick() + internal void DoubleClick(MouseEventArgs e) { - if (ContainsMenu) + if (e == null || + e.Button == MouseButtons.Left && + ContainsMenu) { Log.ProcessStart("explorer.exe", TargetFilePath); } diff --git a/Utilities/DataGridViewExtensions.cs b/Utilities/DataGridViewExtensions.cs index fc06e10..d710608 100644 --- a/Utilities/DataGridViewExtensions.cs +++ b/Utilities/DataGridViewExtensions.cs @@ -33,7 +33,7 @@ namespace SystemTrayMenu.Utilities } dgv.Columns[i].Width = (int)(widthMax + 0.5); - string stringWithWidthLikeIcon = "___"; + string stringWithWidthLikeIcon = "____"; #pragma warning disable CA1303 // Do not pass literals as localized parameters float Width0 = gfx.MeasureString(stringWithWidthLikeIcon, #pragma warning restore CA1303 // Do not pass literals as localized parameters diff --git a/Utilities/File/FileLnk.cs b/Utilities/File/FileLnk.cs index 49433b3..b617278 100644 --- a/Utilities/File/FileLnk.cs +++ b/Utilities/File/FileLnk.cs @@ -41,289 +41,27 @@ namespace SystemTrayMenu.Utilities FolderItem folderItem = folder.ParseName(filenameOnly); if (folderItem != null) { - ShellLinkObject link = (ShellLinkObject)folderItem.GetLink; - if (string.IsNullOrEmpty(link.Path)) + try { - resolvedFilename = link.Target.Path; + ShellLinkObject link = (ShellLinkObject)folderItem.GetLink; + if (string.IsNullOrEmpty(link.Path)) + { + resolvedFilename = link.Target.Path; + } + else + { + resolvedFilename = link.Path; + } } - else + catch (UnauthorizedAccessException ex) { - resolvedFilename = link.Path; + Log.Warn($"shortcutFilename:'{shortcutFilename}'", ex); } } return resolvedFilename; } - // [Flags()] - // private enum SLGP_FLAGS - // { - // /// Retrieves the standard short (8.3 format) file name - // SLGP_SHORTPATH = 0x1, - // /// Retrieves the Universal Naming Convention (UNC) path name of the file - // SLGP_UNCPRIORITY = 0x2, - // /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded - // SLGP_RAWPATH = 0x4 - // } - - // [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - // private struct WIN32_FIND_DATAW - // { - // public uint dwFileAttributes; - // public long ftCreationTime; - // public long ftLastAccessTime; - // public long ftLastWriteTime; - // public uint nFileSizeHigh; - // public uint nFileSizeLow; - // public uint dwReserved0; - // public uint dwReserved1; - // [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - // public string cFileName; - // [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - // public string cAlternateFileName; - // } - - // [Flags()] - // private enum SLR_FLAGS - // { - // /// - // /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, - // /// the high-order word of fFlags can be set to a time-out value that specifies the - // /// maximum amount of time to be spent resolving the link. The function returns if the - // /// link cannot be resolved within the time-out duration. If the high-order word is set - // /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds - // /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out - // /// duration, in milliseconds. - // /// - // SLR_NO_UI = 0x1, - // /// Obsolete and no longer used - // SLR_ANY_MATCH = 0x2, - // /// If the link object has changed, update its path and list of identifiers. - // /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine - // /// whether or not the link object has changed. - // SLR_UPDATE = 0x4, - // /// Do not update the link information - // SLR_NOUPDATE = 0x8, - // /// Do not execute the search heuristics - // SLR_NOSEARCH = 0x10, - // /// Do not use distributed link tracking - // SLR_NOTRACK = 0x20, - // /// Disable distributed link tracking. By default, distributed link tracking tracks - // /// removable media across multiple devices based on the volume name. It also uses the - // /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter - // /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. - // SLR_NOLINKINFO = 0x40, - // /// Call the Microsoft Windows Installer - // SLR_INVOKE_MSI = 0x80 - // } - - // /// The IShellLink interface allows Shell links to be created, modified, and resolved - // [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] - // private interface IShellLinkW - // { - // /// Retrieves the path and file name of a Shell link object - // void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags); - // /// Retrieves the list of item identifiers for a Shell link object - // void GetIDList(out IntPtr ppidl); - // /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. - // void SetIDList(IntPtr pidl); - // /// Retrieves the description string for a Shell link object - // void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); - // /// Sets the description for a Shell link object. The description can be any application-defined string - // void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - // /// Retrieves the name of the working directory for a Shell link object - // void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); - // /// Sets the name of the working directory for a Shell link object - // void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - // /// Retrieves the command-line arguments associated with a Shell link object - // void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); - // /// Sets the command-line arguments for a Shell link object - // void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - // /// Retrieves the hot key for a Shell link object - // void GetHotkey(out short pwHotkey); - // /// Sets a hot key for a Shell link object - // void SetHotkey(short wHotkey); - // /// Retrieves the show command for a Shell link object - // void GetShowCmd(out int piShowCmd); - // /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. - // void SetShowCmd(int iShowCmd); - // /// Retrieves the location (path and index) of the icon for a Shell link object - // void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - // int cchIconPath, out int piIcon); - // /// Sets the location (path and index) of the icon for a Shell link object - // void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - // /// Sets the relative path to the Shell link object - // void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); - // /// Attempts to find the target of a Shell link, even if it has been moved or renamed - // void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); - // /// Sets the path and file name of a Shell link object - // void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - - // } - - // [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), - // InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - // public interface IPersist - // { - // [PreserveSig] - // void GetClassID(out Guid pClassID); - // } - - // [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), - // InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - // public interface IPersistFile : IPersist - // { - // new void GetClassID(out Guid pClassID); - - // [PreserveSig] - // int IsDirty(); - - // [PreserveSig] - // void Load([In, MarshalAs(UnmanagedType.LPWStr)] - // string pszFileName, uint dwMode); - - // [PreserveSig] - // void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, - // [In, MarshalAs(UnmanagedType.Bool)] bool fRemember); - - // [PreserveSig] - // void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); - - // [PreserveSig] - // void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); - // } - - // private const uint STGM_READ = 0; - // private const int MAX_PATH = 260; - - // // CLSID_ShellLink from ShlGuid.h - // [ - // ComImport(), - // Guid("00021401-0000-0000-C000-000000000046") - // ] - // public class ShellLink - // { - // } - - // public static string ResolveShortcut(string filename) - // { - // ShellLink link = new ShellLink(); - //#pragma warning disable CA2010 // Always consume the value returned by methods marked with PreserveSigAttribute - // ((IPersistFile)link).Load(filename, STGM_READ); - //#pragma warning restore CA2010 // => Has no returned value => OK - // StringBuilder sb = new StringBuilder(MAX_PATH); - // WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - // ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0); - // string resolvedPath = sb.ToString(); - // if (!IsDirectory(resolvedPath) && - // !File.Exists(resolvedPath)) - // { - // //For some lnk e.g. WinRar SkypeForBuisness - // //resolved path wrong to Program Files (x86) - //#warning Using Shell32 with this method only allow in single thread application. You have to include [STAThread] in main entry point. - // resolvedPath = ReplaceFirst(resolvedPath, - // @"\Program Files (x86)\", - // @"\Program Files\"); - // if (!File.Exists(resolvedPath)) - // { - // resolvedPath = string.Empty; - - // //Shell32.Folder folder = GetShell32NameSpaceFolder(filename as object); - - // //string name1 = string.Empty; - // //string path1 = string.Empty; - // //string description1 = string.Empty; - // //string working_dir1 = string.Empty; - // //string args1 = string.Empty; - - // ////string test2 = name1 + path1 + description1 + working_dir1 + args1 + test1; - - // //object[] args = new object[] { filename }; - // //if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) - // //{ - // // //string test1 = - // // GetShortcutInfo(filename); - // //} - // //else - // //{ - // // Thread staThread = new Thread(new ParameterizedThreadStart(GetShortcutInfo)); - // // staThread.SetApartmentState(ApartmentState.STA); - // // staThread.Start(args); - // // staThread.Join(); - // //} - // } - // } - // return resolvedPath; - // } - - // //public static Shell32.Folder GetShell32NameSpaceFolder(Object folder) - // //{ - // // Type shellAppType = Type.GetTypeFromProgID("Shell.Application"); - - // // Object shell = Activator.CreateInstance(shellAppType); - // // return (Shell32.Folder)shellAppType.InvokeMember("NameSpace", - // // System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { folder }, CultureInfo.InvariantCulture); - // //} - - // //TESTING - // // Get information about this link. - // // Return an error message if there's a problem. - // //static void GetShortcutInfo(object parameters) - // //{ - // // object[] args = (object[])parameters; - // // string full_name = (string)args[0]; - // // string name = ""; - // // string path = ""; - // // string descr = ""; - // // string working_dir = ""; - // // //string args = ""; - - // // try - // // { - // // // Make a Shell object. - // // Shell32.Shell shell = new Shell32.Shell(); - - // // // Get the shortcut's folder and name. - // // string shortcut_path = - // // full_name.Substring(0, full_name.LastIndexOf("\\")); - // // string shortcut_name = - // // full_name.Substring(full_name.LastIndexOf("\\") + 1); - // // if (!shortcut_name.EndsWith(".lnk")) - // // shortcut_name += ".lnk"; - - // // // Get the shortcut's folder. - // // Shell32.Folder shortcut_folder = - // // shell.NameSpace(shortcut_path); - - // // // Get the shortcut's file. - // // Shell32.FolderItem folder_item = - // // shortcut_folder.Items().Item(shortcut_name); - - // // if (folder_item == null) - // // { - // // //return "Cannot find shortcut file '" + full_name + "'"; - // // } - // // if (!folder_item.IsLink) - // // { - // // //return "File '" + full_name + "' isn't a shortcut."; - // // } - - // // // Display the shortcut's information. - // // Shell32.ShellLinkObject lnk = - // // (Shell32.ShellLinkObject)folder_item.GetLink; - // // name = folder_item.Name; - // // descr = lnk.Description; - // // path = lnk.Path; - // // working_dir = lnk.WorkingDirectory; - // // //args = lnk.Arguments; - // // //return ""; - // // } - // // catch (Exception ex) - // // { - // // //return ex.Message; - // // } - // //} - public static bool IsDirectory(string filePath) { bool isDirectory = false; @@ -338,16 +76,5 @@ namespace SystemTrayMenu.Utilities return isDirectory; } - - // public static string ReplaceFirst(string text, string search, string replace) - // { - // int pos = text.IndexOf(search, StringComparison.InvariantCulture); - // if (pos < 0) - // { - // return text; - // } - // return text.Substring(0, pos) + replace + - // text.Substring(pos + search.Length); - // } } } \ No newline at end of file