📄 browsercontextmenuwrappers.cs
字号:
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 + -