home *** CD-ROM | disk | FTP | other *** search
Wrap
// Pavel Zolnikov[http://www.codeproject.com/script/profile/whos_who.asp?id=35980], 2002 using System; using System.IO; using System.Text; using Microsoft.Win32; using System.Threading; using System.Reflection; using System.Diagnostics; using System.Collections; using System.Windows.Forms; using System.Runtime.InteropServices; using SHDocVw; using Shell32; using ZCommon; using BandObjects; namespace CommandBar { /// <summary> /// Implementation of Command consoleCtrl Explorer Bar. /// </summary> /// <remarks> /// Hosts ConsoleCtrl and provides toolbar with shortcut commands to several operations over console. /// Relies on base FormBandObject class that implements all functionality required by explorer from Band Objects. /// </remarks> [ComVisible(true)] [Guid("8689A69C-CC9D-3AEC-9D7C-E7F409700C15")] [BandObject("Command Prompt /Ctrl+M/", BandObjectStyles.Horizontal ,HelpText="Shows Command Prompt Bar.")] public class CommandBarObj : BandObject { System.ComponentModel.IContainer components; MacroMenuBuilder macroMenuBuilder; ImageList toolbarImages; ToolBar toolBar; ToolBarButton toolBarButtonNew; ToolBarButton toolBarButtonSync; ToolBarButton toolBarButtonMacro; ToolTip toolTips; ToolBarButton toolBarButtonCls; ToolBarButton toolBarButtonEnter; ToolBarButton toolBarButtonEsc; ToolBarButton toolBarButtonType; ToolBarButton toolBarButtonGrow; ToolBarButton toolBarButtonShrink; ToolBarButton toolBarButton3; /// <summary> /// Command prompt window incapsulated in the form of WindowsForms control. /// </summary> ConsoleCtrl consoleCtrl; System.Windows.Forms.Timer timer; static Hashtable bars = Hashtable.Synchronized(new Hashtable()); static CreateProcessHook createProcessHook; Int32 threadId; public static CommandBarObj GetBarFromThreadId(Int32 threadId) { foreach( CommandBarObj bar in bars.Values ) { if( bar.threadId == threadId ) return bar; } return null; } [CLSCompliant(false)] public static CommandBarObj GetBarFromExplorer(WebBrowserClass explorer) { CommandBarObj bar = null; try { bar = (CommandBarObj)bars[explorer]; } catch( ArgumentException /*e*/) {} return bar; } public static bool HookCreateProcess { get { return hookCreateProcess; } set { hookCreateProcess = value; if( HookCreateProcess && createProcessHook == null ) createProcessHook = new CreateProcessHook(); if( !HookCreateProcess && createProcessHook != null ) { createProcessHook.Dispose(); createProcessHook = null; } } }static bool hookCreateProcess = true; public CommandBarObj() { InitializeComponent(); ContextMenu mnu = new ContextMenu(); mnu.Popup += new EventHandler( OnMacroMenuChanged ); toolBarButtonMacro.DropDownMenu = mnu; macroMenuBuilder = new MacroMenuBuilder(MacroFilePath,mnu); macroMenuBuilder.MenuItemClick += new EventHandler( OnMacroMenuIemClick ); macroMenuBuilder.MenuChanged += new EventHandler( OnMacroMenuChanged ); // // consoleCtrl // // this.consoleCtrl = new ZCommon.ConsoleCtrl(); // this.consoleCtrl.Parent = this; // // this.consoleCtrl.Anchor = System.Windows.Forms.AnchorStyles.Top // | System.Windows.Forms.AnchorStyles.Bottom // | System.Windows.Forms.AnchorStyles.Left // | System.Windows.Forms.AnchorStyles.Right; // // this.consoleCtrl.Name = "consoleCtrl"; // this.consoleCtrl.Location = new System.Drawing.Point(40, 0); // this.consoleCtrl.Size = new System.Drawing.Size(260, 208); // this.consoleCtrl.VisibleChanged += new System.EventHandler(this.consoleCtrl_VisibleChanged); // this.consoleCtrl.TabStop = true; // this.consoleCtrl.TabIndex = 1; ConsoleCtrl.ConsoleExited += new EventHandler( OnConsoleExited ); HookCreateProcess = HookCreateProcess; } public override Int32 HasFocusIO() { return base.HasFocusIO() == 0 || ConsoleCtrl.ConsoleFocused ? 0 : 1;// S_OK : S_FALSE } protected override void OnExplorerAttached(EventArgs ea) { base.OnExplorerAttached(ea); bars[Explorer] = this; threadId = Win32.GetCurrentThreadId(); } protected override void OnExplorerDetaching(EventArgs ea) { base.OnExplorerDetaching(ea); bars.Remove(Explorer); } protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(CommandBarObj)); this.consoleCtrl = new ZCommon.ConsoleCtrl(); this.toolbarImages = new System.Windows.Forms.ImageList(this.components); this.toolBar = new System.Windows.Forms.ToolBar(); this.toolBarButtonNew = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonSync = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonCls = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonType = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonEnter = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonEsc = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonMacro = new System.Windows.Forms.ToolBarButton(); this.toolBarButton3 = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonGrow = new System.Windows.Forms.ToolBarButton(); this.toolBarButtonShrink = new System.Windows.Forms.ToolBarButton(); this.toolTips = new System.Windows.Forms.ToolTip(this.components); this.timer = new System.Windows.Forms.Timer(this.components); this.SuspendLayout(); // // consoleCtrl // this.consoleCtrl.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right); this.consoleCtrl.Location = new System.Drawing.Point(40, 0); this.consoleCtrl.Name = "consoleCtrl"; this.consoleCtrl.ScreenBufferAutoGrow = true; this.consoleCtrl.Size = new System.Drawing.Size(260, 208); this.consoleCtrl.TabIndex = 1; this.consoleCtrl.VisibleChanged += new System.EventHandler(this.consoleCtrl_VisibleChanged); // // toolbarImages // this.toolbarImages.ColorDepth = System.Windows.Forms.ColorDepth.Depth16Bit; this.toolbarImages.ImageSize = new System.Drawing.Size(16, 16); this.toolbarImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("toolbarImages.ImageStream"))); this.toolbarImages.TransparentColor = System.Drawing.Color.Transparent; // // toolBar // this.toolBar.Appearance = System.Windows.Forms.ToolBarAppearance.Flat; this.toolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] { this.toolBarButtonNew, this.toolBarButtonSync, this.toolBarButtonCls, this.toolBarButtonType, this.toolBarButtonEnter, this.toolBarButtonEsc, this.toolBarButtonMacro, this.toolBarButton3, this.toolBarButtonGrow, this.toolBarButtonShrink}); this.toolBar.Dock = System.Windows.Forms.DockStyle.Left; this.toolBar.DropDownArrows = true; this.toolBar.ImageList = this.toolbarImages; this.toolBar.Name = "toolBar"; this.toolBar.ShowToolTips = true; this.toolBar.Size = new System.Drawing.Size(39, 208); this.toolBar.TabIndex = 0; this.toolBar.TabStop = true; this.toolBar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.toolBar_ButtonClick); // // toolBarButtonNew // this.toolBarButtonNew.ImageIndex = 0; this.toolBarButtonNew.Style = System.Windows.Forms.ToolBarButtonStyle.DropDownButton; this.toolBarButtonNew.ToolTipText = "Console menu"; // // toolBarButtonSync // this.toolBarButtonSync.ImageIndex = 1; this.toolBarButtonSync.Pushed = true; this.toolBarButtonSync.ToolTipText = "Syncronize"; // // toolBarButtonCls // this.toolBarButtonCls.ImageIndex = 6; this.toolBarButtonCls.ToolTipText = "cls"; // // toolBarButtonType // this.toolBarButtonType.ImageIndex = 5; this.toolBarButtonType.ToolTipText = "Get selected folder items"; // // toolBarButtonEnter // this.toolBarButtonEnter.ImageIndex = 8; this.toolBarButtonEnter.ToolTipText = "Enter key"; // // toolBarButtonEsc // this.toolBarButtonEsc.ImageIndex = 7; this.toolBarButtonEsc.ToolTipText = "Escape key"; // // toolBarButtonMacro // this.toolBarButtonMacro.ImageIndex = 3; this.toolBarButtonMacro.Style = System.Windows.Forms.ToolBarButtonStyle.DropDownButton; this.toolBarButtonMacro.ToolTipText = "Macro"; // // toolBarButton3 // this.toolBarButton3.Style = System.Windows.Forms.ToolBarButtonStyle.Separator; // // toolBarButtonGrow // this.toolBarButtonGrow.ImageIndex = 9; this.toolBarButtonGrow.ToolTipText = "Grow"; // // toolBarButtonShrink // this.toolBarButtonShrink.ImageIndex = 10; this.toolBarButtonShrink.ToolTipText = "Shrink"; // // timer // this.timer.Interval = 750; this.timer.Tick += new System.EventHandler(this.timer_Tick); // // CommandBarObj // this.Controls.AddRange(new System.Windows.Forms.Control[] { this.consoleCtrl, this.toolBar}); this.Name = "CommandBarObj"; this.Size = new System.Drawing.Size(292, 208); this.Title = "Command Prompt"; this.VisibleChanged += new System.EventHandler(this.CommandBar_VisibleChanged); this.ResumeLayout(false); } #endregion /// <summary> /// Tells explorer to show or hide CommandBar. /// </summary> [CLSCompliant(false)] public static void ShowBrowserBar(bool show, WebBrowserClass explorer) { if( explorer != null ) { CommandBarObj me = GetBarFromExplorer(explorer); // if( !show ) // { // if( me != null ) // me.Invoke( new MethodInvoker(me.NotifyExplorerLostFocus) ); // } if( show ) { foreach( CommandBarObj bar in bars.Values ) { if( bar.Visible && bar != me ) ShowBrowserBar( false, bar.Explorer ); } } Object guid = "{8689A69C-CC9D-3AEC-9D7C-E7F409700C15}"; Object oShow = show; Object dummy = false; explorer.ShowBrowserBar( ref guid, ref oShow, ref dummy); } } /// <summary> /// Current filesystem folder that explorer looks at or "" if explorer looks at a shell namespace (My Computer). /// </summary> String currentDir { get { try { Uri uri = new Uri( Explorer.LocationURL , true ); return uri.LocalPath; } catch { return ""; } } } /// <summary> /// Path to the xml file with the set of macro commands. /// </summary> public static String MacroFilePath { get { Microsoft.Win32.RegistryKey rkCmdBar = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"SOFTWARE\CommandBar"); return rkCmdBar.GetValue("MacroFilePath","").ToString(); } } class FolderSelectionFormatter : IFormatProvider, ICustomFormatter { public Object GetFormat(Type formatType) { if( formatType == typeof(ICustomFormatter) ) return this; else return Thread.CurrentThread.CurrentCulture.GetFormat(formatType); } String FormatFolderItem(String format, FolderItem item) { String s; switch(format[0]) { case 'F': case 'f': s = item.Path; break; case 'N': s = item.Name; break; case 'n': s = Path.GetFileNameWithoutExtension(item.Name); break; case 'P': case 'p': s = Path.GetDirectoryName(item.Path); break; case 'E': case 'e': s = Path.GetExtension(item.Name); break; default: s = "<<unknown format>>"; break; } if( format[1] == '"' || (format[1] == '\'' && item.Name.IndexOf(" ") != -1) ) { return "\"" + s + "\""; } else { return s; } } public String Format(String format, Object arg, IFormatProvider formatProvider) { //default formatting if( format == null || format == "" ) format = "N' "; if( format.Length == 1 ) format += "' "; if( format.Length == 2 ) format += " "; if( arg.GetType() == typeof(Object[]) ) { StringBuilder sb = new StringBuilder(40); bool firstItem = true; foreach(FolderItem item in arg as Object[]) { if( !firstItem ) sb.Append( format[2] ); else firstItem = false; sb.Append(FormatFolderItem(format,item)); } return sb.ToString(); } if( arg is FolderItem ) { return FormatFolderItem( format, arg as FolderItem ); } IFormattable formattable = arg as IFormattable; if( formattable != null ) return formattable.ToString(format,formatProvider); else return arg.ToString(); } } String ExpandCommandRegistryKeys(String command) { int begin; int end; while( (begin=command.IndexOf('[')) != -1 ) { end=command.IndexOf(']',begin); if( end != -1 ) { String registryPath = command.Substring(begin+1,end-begin-1); bool commandChanged = false; Type type = typeof(Microsoft.Win32.Registry); foreach(FieldInfo field in type.GetFields()) { object obj = field.GetValue(null); RegistryKey key = obj as RegistryKey; if( registryPath.StartsWith(key.Name) ) { registryPath = registryPath.Remove(0,key.Name.Length+1); int lastSlash = registryPath.LastIndexOf('\\'); object val = key.OpenSubKey(registryPath.Substring(0,lastSlash)). GetValue(registryPath.Substring(lastSlash+1),"<not found>"); String str = val as String; command = command.Substring(0,begin) + str + command.Substring(end+1); commandChanged = true; break; } } if( !commandChanged ) break;//avoiding infinite loop } } return command; } String ExpandCommand(String command) { command = ExpandCommandRegistryKeys(command); IShellFolderViewDual folder = Explorer.Document as IShellFolderViewDual; ArrayList selection = new ArrayList(); foreach( FolderItem item in folder.SelectedItems()) { selection.Add( item ); } StringBuilder sb = new StringBuilder(40); selection.Insert( 0, selection.ToArray() ); try { sb.AppendFormat( new FolderSelectionFormatter(), command, selection.ToArray() ); } catch( System.FormatException) { } return sb.ToString().Trim(); } /// <summary> /// Synchronizes current folder of command prompt with the one of explorer. /// </summary> void synchronizeConsole() { if( toolBarButtonSync.Pushed ) { ConsoleCtrl.SendEscKey(); ConsoleCtrl.Output("cd /D "+ currentDir, true, true);// /D makes it to change drives also } } /// <summary> /// After explorer navigated to the new folder synchronizes command prompt current folder. /// </summary> /// <remarks> /// Synchronization does not appear immediately. It is delayed by 0.75 sec with the help of timer. This allows to skip some synchronizations cycles in the case user is just moving fast through folders. /// </remarks> void OnNavigateComplete2( object sender, ref object args) { timer.Stop(); timer.Start(); } void OnConsoleExited(Object sender, EventArgs ea ) { if( Explorer != null ) { ShowBrowserBar(false, Explorer); Win32.SetWindowPos( (IntPtr)Explorer.HWND, IntPtr.Zero, 0, 0, 0, 0, 0x3 ); } } /// <summary> /// Called when menu displayed by Script button has been changed. /// </summary> /// <remarks> /// This is happens because xml macro file was changed. So we need to check if there are any errors and update Script button icon and tooltip accordingly. /// </remarks> void OnMacroMenuChanged(Object sender, EventArgs ea ) { if( macroMenuBuilder.MacroFileError != null ) { toolBarButtonMacro.ImageIndex = 4;//script with exclamaiton icon toolBarButtonMacro.ToolTipText = macroMenuBuilder.MacroFileError; } else { toolBarButtonMacro.ImageIndex = 3;//ok, no error toolBarButtonMacro.ToolTipText = ""; } } /// <summary> /// Called when user clicked on one of the macro menu items. /// </summary> /// <remarks> /// If menu item is script then we output its command to the console. /// </remarks> void OnMacroMenuIemClick( Object sender, EventArgs ea ) { //we know for sure that menu build by MacroMenuBuilder consists of TagMenuItems TagMenuItem mi = (TagMenuItem)sender; //these items' tags are either MacroMenuBuilder.group(s) or MacroMenuBuilder.macro(s) if( mi.Tag is MacroMenuBuilder.macro ) { MacroMenuBuilder.macro script = (MacroMenuBuilder.macro)mi.Tag; //if script does not have a command then its text is a command String command = script.command == null ? script.text : script.command; ConsoleCtrl.Output( ExpandCommand( command ), true, script.execute && (Control.ModifierKeys!=Keys.Shift)); } } void toolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e) { ToolBarButton b = e.Button; if( b == toolBarButtonSync ) { toolBar.SuspendLayout(); b.Pushed ^= true; if( b.Pushed ) { b.ImageIndex = 1; toolBar.Invalidate(); toolBar.Update(); synchronizeConsole(); } else { b.ImageIndex = 2; toolBar.Invalidate(); toolBar.Update(); } toolBar.ResumeLayout(); } else if ( b == toolBarButtonNew ) { new About().ShowDialog(this); } else if ( b == toolBarButtonMacro ) { //starts notepad so user can edit macro menu file Process.Start("notepad.exe", MacroFilePath ); } else if ( b == toolBarButtonType ) { //outputs current explorer selection to the console ConsoleCtrl.Output( ExpandCommand("{0}"), true, false ); } else if ( b == toolBarButtonCls ) { //cleans the screen ConsoleCtrl.SendEscKey(); ConsoleCtrl.Output( "cls", true, true ); } else if ( b == toolBarButtonEnter ) { //same as hitting an enter key ConsoleCtrl.Output( "", true, true ); } else if ( b == toolBarButtonEsc ) { //same as hitting an Esc key ConsoleCtrl.SendEscKey(); } else if ( b == toolBarButtonGrow ) { //increases width of the console screen buffer ConsoleCtrl.ResizeConsoleScreenBuffer(4); } else if ( b == toolBarButtonShrink ) { //decreases width of the console screen buffer ConsoleCtrl.ResizeConsoleScreenBuffer(-4); } } /// <summary> /// Called when command propmpt porcess (cmd.exe) exits. /// </summary> /// <remarks> /// Hides Command consoleCtrl Explore Bar. Assuming that user has typed 'exit' it looks like the right thing to do. /// </remarks> void consoleCtrl_ConsoleExit(object sender, System.EventArgs e) { if( Explorer != null ) { ShowBrowserBar( false, Explorer ); } } /// <summary> /// If we here then explorer navigated to another folder about 0.75 sec ago. Syncronizing. /// </summary> void timer_Tick(object sender, System.EventArgs e) { timer.Stop(); synchronizeConsole(); } /// <summary> /// Called by base class when it processes explorer request to hide or show band object. /// </summary> void CommandBar_VisibleChanged(object sender, System.EventArgs e) { if( Visible ) { if( !ConsoleCtrl.ConsoleRunning ) ConsoleCtrl.OpenConsole(); consoleCtrl.MainWindowHandle = (IntPtr)Explorer.HWND; //makes this buttons menu look like it is a console window system menu toolBarButtonNew.DropDownMenu = ConsoleCtrl.SystemMenu; Explorer.NavigateComplete2 += new DWebBrowserEvents2_NavigateComplete2EventHandler( OnNavigateComplete2 ); synchronizeConsole(); consoleCtrl.Show(); } else { Explorer.NavigateComplete2 -= new DWebBrowserEvents2_NavigateComplete2EventHandler( OnNavigateComplete2 ); } } private void consoleCtrl_VisibleChanged(object sender, System.EventArgs e) { if ( !consoleCtrl.Visible ) ShowBrowserBar( false, Explorer ); } } }