⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 browsercontextmenuwrappers.cs

📁 C#界面编程
💻 CS
📖 第 1 页 / 共 5 页
字号:
                        iContextMenu3 = null;
                    }

                    if (contextMenu != null)
                        ShellAPI.DestroyMenu(contextMenu);

                    if (iContextMenuPtr != IntPtr.Zero)
                        Marshal.Release(iContextMenuPtr);

                    if (iContextMenuPtr2 != IntPtr.Zero)
                        Marshal.Release(iContextMenuPtr2);

                    if (iContextMenuPtr3 != IntPtr.Zero)                    
                        Marshal.Release(iContextMenuPtr3);
                }
                #endregion
            }
            contextMenuVisible = false;
        }

        #endregion
    }

    /// <summary>
    /// This class takes care of showing ContextMenu's for a BrowserListView and 
    /// executing items when pressing enter or double clicking
    /// </summary>
    internal class BrowserLVContextMenuWrapper : NativeWindow
    {
        #region Fields

        // The browser for which to provide the context menu's
        private Browser br;

        private BrowserPluginWrapper pluginWrapper;
        private StreamStorageProvider provider;

        private BackgroundWorker viewPluginWorker;
        private System.Windows.Forms.Timer viewPluginTimer;
        private delegate void ViewPluginFileChange(IFileInfoProvider provider, ShellItem item);
        private delegate void ViewPluginFolderChange(IDirInfoProvider provider, ShellItem item);

        private delegate void ToolTipDelegate(ListViewItem listItem);
        private ToolTipDelegate toolTipDelegate;

        // If this bool is true the next time the context menu has to be shown will be cancelled
        private bool suspendContextMenu;

        // The interfaces for the needed context menu's
        private IContextMenu iContextMenu, newContextMenu;
        private IContextMenu2 iContextMenu2, newContextMenu2;
        private IContextMenu3 iContextMenu3, newContextMenu3;

        private IntPtr newSubmenuPtr;

        private bool contextMenuVisible;

        // The cmd for a custom added menu item
        private enum CMD_CUSTOM
        {
            Tiles = (int)ShellAPI.CMD_LAST + 1,
            Icons,
            List,
            Details,
            Properties,
            Paste,
            Paste_ShortCut,
            SpecialView
        }

        #endregion

        /// <summary>
        /// Registers the neccesairy events
        /// </summary>
        /// <param name="br">The browser for which to support the ContextMenu</param>
        public BrowserLVContextMenuWrapper(Browser br, BrowserPluginWrapper pluginWrapper)
        {
            this.br = br;
            this.pluginWrapper = pluginWrapper;

            provider = new StreamStorageProvider(FileAccess.ReadWrite);
            viewPluginWorker = new BackgroundWorker();
            viewPluginWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            viewPluginTimer = new System.Windows.Forms.Timer();
            viewPluginTimer.Tick += new EventHandler(viewPluginTimer_Tick);
            viewPluginTimer.Interval = 300;

            br.FileView.ShowItemToolTips = true;
            toolTipDelegate = new ToolTipDelegate(SetToolTip);

            br.SelectedFolderChanged += new SelectedFolderChangedEventHandler(br_SelectedFolderChanged);

            br.FileView.LabelEdit = true;
            br.FileView.MouseUp += new MouseEventHandler(FileView_MouseUp);
            br.FileView.ItemActivate += new EventHandler(FileView_ItemActivate);
            br.FileView.AfterLabelEdit += new LabelEditEventHandler(FileView_AfterLabelEdit);
            br.FileView.BeforeLabelEdit += new LabelEditEventHandler(FileView_BeforeLabelEdit);
            br.FileView.KeyDown += new KeyEventHandler(FileView_KeyDown);
            br.FileView.ItemSelectionChanged += new ListViewItemSelectionChangedEventHandler(FileView_ItemSelectionChanged);
            br.FileView.ItemMouseHover += new ListViewItemMouseHoverEventHandler(FileView_ItemMouseHover);

            this.CreateHandle(new CreateParams());
        }

        #region Public

        public bool SuspendContextMenu
        {
            get { return suspendContextMenu; }
            set { suspendContextMenu = value; }
        }

        #endregion

        #region Override

        /// <summary>
        /// This method receives WindowMessages. It will make the "Open With" and "Send To" work 
        /// by calling HandleMenuMsg and HandleMenuMsg2. It will also call the OnContextMenuMouseHover 
        /// method of Browser when hovering over a ContextMenu item.
        /// </summary>
        /// <param name="m">the Message of the Browser's WndProc</param>
        /// <returns>true if the message has been handled, false otherwise</returns>
        protected override void WndProc(ref Message m)
        {
            #region IContextMenu

            if (iContextMenu != null &&
                m.Msg == (int)ShellAPI.WM.MENUSELECT &&
                ((int)ShellHelper.HiWord(m.WParam) & (int)ShellAPI.MFT.SEPARATOR) == 0 &&
                ((int)ShellHelper.HiWord(m.WParam) & (int)ShellAPI.MFT.POPUP) == 0)
            {
                string info = string.Empty;
                info = ContextMenuHelper.GetCommandString(
                    iContextMenu,
                    ShellHelper.LoWord(m.WParam) - ShellAPI.CMD_FIRST, 
                    false);
                br.OnContextMenuMouseHover(new ContextMenuMouseHoverEventArgs(info.ToString()));
            }

            #endregion

            #region IContextMenu2

            if (iContextMenu2 != null &&
                (m.Msg == (int)ShellAPI.WM.INITMENUPOPUP ||
                 m.Msg == (int)ShellAPI.WM.MEASUREITEM ||
                 m.Msg == (int)ShellAPI.WM.DRAWITEM))
            {
                if (iContextMenu2.HandleMenuMsg(
                    (uint)m.Msg, m.WParam, m.LParam) == ShellAPI.S_OK)
                    return;
            }

            if (newContextMenu2 != null &&
                ((m.Msg == (int)ShellAPI.WM.INITMENUPOPUP && m.WParam == newSubmenuPtr) ||
                 m.Msg == (int)ShellAPI.WM.MEASUREITEM ||
                 m.Msg == (int)ShellAPI.WM.DRAWITEM))
            {
                if (newContextMenu2.HandleMenuMsg(
                    (uint)m.Msg, m.WParam, m.LParam) == ShellAPI.S_OK)
                    return;
            }

            #endregion

            #region IContextMenu3

            if (iContextMenu3 != null &&
                m.Msg == (int)ShellAPI.WM.MENUCHAR)
            {
                if (iContextMenu3.HandleMenuMsg2(
                    (uint)m.Msg, m.WParam, m.LParam, IntPtr.Zero) == ShellAPI.S_OK)
                    return;
            }

            if (newContextMenu3 != null &&
                m.Msg == (int)ShellAPI.WM.MENUCHAR)
            {
                if (newContextMenu3.HandleMenuMsg2(
                    (uint)m.Msg, m.WParam, m.LParam, IntPtr.Zero) == ShellAPI.S_OK)
                    return;
            }

            #endregion   

            base.WndProc(ref m);
        }

        #endregion

        #region Events

        void FileView_KeyDown(object sender, KeyEventArgs e)
        {
            ContextMenuHelper.ProcessKeyCommands(br, sender, e);
        }

        void FileView_BeforeLabelEdit(object sender, LabelEditEventArgs e)
        {
            ShellItem item = br.FileView.Items[e.Item].Tag as ShellItem;

            if (!item.CanRename)
            {
                e.CancelEdit = true;
                System.Media.SystemSounds.Beep.Play();
                return;
            }
            else if (item.IsDisk)
            {
                IntPtr editHandle = ShellAPI.SendMessage(br.FileView.Handle, ShellAPI.WM.LVM_GETEDITCONTROL, 0, IntPtr.Zero);
                ShellAPI.SendMessage(editHandle, ShellAPI.WM.SETTEXT, 0,
                    Marshal.StringToHGlobalAuto(item.Text.Substring(0, item.Text.LastIndexOf(' '))));
            }
        }

        void FileView_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            ShellItem item = br.FileView.Items[e.Item].Tag as ShellItem;

            if (e.Label != null && br.FileView.SelectedOrder.Count == 1)
            {
                #region Rename One
                IntPtr newPidl = IntPtr.Zero;
                if (!(item.IsDisk && item.Text.Substring(0, item.Text.LastIndexOf(' ')) == e.Label) &&
                    item.ParentItem.ShellFolder.SetNameOf(
                        br.Handle,
                        item.PIDLRel.Ptr,
                        e.Label,
                        ShellAPI.SHGNO.NORMAL,
                        out newPidl) == ShellAPI.S_OK)
                {
                    item.Update(newPidl, ShellItemUpdateType.Renamed);
                }
                else
                    e.CancelEdit = true;
                #endregion
            }
            else if (e.Label != null)
            {
                #region Rename Batch
                string label = (!string.IsNullOrEmpty(e.Label) ? e.Label : br.FileView.Items[e.Item].Text);

                string startString = Path.GetFileNameWithoutExtension(label);
                string endString = Path.GetExtension(label);

                int countLength = br.FileView.SelectedOrder.Count.ToString().Length;

                IntPtr newPidl = IntPtr.Zero;
                ShellItem shellItem;
                ListViewItem listItem;

                StringBuilder renameString = new StringBuilder(startString.Length + endString.Length + countLength);
                renameString.Append(startString);
                renameString.Append('0', countLength);
                renameString.Append(endString);

                string counter;
                for (int i = 1; i <= br.FileView.SelectedOrder.Count; i++)
                {
                    listItem = br.FileView.SelectedOrder[i - 1] as ListViewItem;
                    shellItem = listItem.Tag as ShellItem;

                    if (shellItem.IsDisk)
                        continue;

                    counter = i.ToString();
                    renameString.Insert(startString.Length, "0", countLength - counter.Length);
                    renameString.Insert(startString.Length + countLength - counter.Length, counter);
                    renameString.Remove(startString.Length + countLength, countLength);

                    if (shellItem.ParentItem.ShellFolder.SetNameOf(
                            (i == 1 ? br.Handle : IntPtr.Zero),
                            shellItem.PIDLRel.Ptr,
                            renameString.ToString(),
                            ShellAPI.SHGNO.NORMAL,
                            out newPidl) == ShellAPI.S_OK)
                    {
                        shellItem.Update(newPidl, ShellItemUpdateType.Renamed);
                    }
                    else if (i == 1)
                        break;
                }

                e.CancelEdit = true;
                #endregion
            }
        }

        /// <summary>
        /// When items are activated (by pressing enter or double clicking) this method will invoke
        /// the default item of the items contextmenu.
        /// </summary>
        void FileView_ItemActivate(object sender, EventArgs e)
        {
            TreeNode parent = br.FolderView.SelectedNode;

            if (parent != null && br.FileView.SelectedOrder.Count > 0)
            {
                ListViewItem listViewItem = (ListViewItem)br.FileView.SelectedOrder[0];
                ShellItem shellItem = (ShellItem)listViewItem.Tag;
                int startIndex = 0;

                if ((Control.ModifierKeys & Keys.Alt) == 0)
                {
                    if (shellItem.IsFolder)
                    {
                        if (!parent.IsExpanded)
                            parent.Expand();

                        br.FolderView.SelectedNode = parent.Nodes[listViewItem.Text];
                        startIndex = 1;
                    }

                    if (br.FileView.SelectedOrder.Count - startIndex > 0)
                    {
                        #region Fields

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -