├── .gitignore ├── LICENSE ├── README.md ├── Wlx2Explorer.sln └── Wlx2Explorer ├── Extensions └── EnumExtensions.cs ├── Forms ├── AboutForm.Designer.cs ├── AboutForm.cs ├── AboutForm.resx ├── ListerForm.Designer.cs ├── ListerForm.cs ├── ListerForm.resx ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── MessageBoxForm.Designer.cs ├── MessageBoxForm.cs ├── MessageBoxForm.resx ├── PluginSettingsForm.Designer.cs ├── PluginSettingsForm.cs ├── PluginSettingsForm.resx ├── ProgramSettingsForm.Designer.cs ├── ProgramSettingsForm.cs ├── ProgramSettingsForm.resx ├── SearchForm.Designer.cs ├── SearchForm.cs └── SearchForm.resx ├── Hooks ├── KeyboardHook.cs ├── VirtualKey.cs └── VirtualKeyModifier.cs ├── Images ├── Down.png ├── Start.png ├── Stop.png ├── Up.png ├── Wlx2Explorer.ico └── Wlx2Explorer.png ├── InitializationFile.cs ├── Libs ├── UnRAR.dll └── UnRAR64.dll ├── Native ├── Interfaces │ ├── IServiceProvider.cs │ └── IShellBrowser.cs ├── NativeConstants.cs ├── NativeMethods.cs └── NativeTypes.cs ├── Plugin.cs ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── Settings ├── PluginInfo.cs └── ProgramSettings.cs ├── StartUpManager.cs ├── ToggleParser.cs ├── Utils ├── AssemblyUtils.cs └── WindowUtils.cs ├── Win32WindowWrapper.cs ├── Wlx2Explorer.csproj ├── Wlx2Explorer.ico ├── Wlx2Explorer.ini └── Wlx2Explorer.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | ## Ignore Visual Studio temporary files, build results, and 8 | ## files generated by popular Visual Studio add-ons. 9 | 10 | # User-specific files 11 | *.suo 12 | *.user 13 | *.sln.docstates 14 | 15 | # Build results 16 | 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | build/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | 24 | #NuGet 25 | packages/ 26 | 27 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 28 | !packages/*/build/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | *_i.c 35 | *_p.c 36 | *.ilk 37 | *.meta 38 | *.obj 39 | *.pch 40 | *.pdb 41 | *.pgc 42 | *.pgd 43 | *.rsp 44 | *.sbr 45 | *.tlb 46 | *.tli 47 | *.tlh 48 | *.tmp 49 | *.tmp_proj 50 | *.log 51 | *.vspscc 52 | *.vssscc 53 | .builds 54 | *.pidb 55 | *.log 56 | *.scc 57 | 58 | # Visual C++ cache files 59 | ipch/ 60 | *.aps 61 | *.ncb 62 | *.opensdf 63 | *.sdf 64 | *.cachefile 65 | 66 | # Visual Studio profiler 67 | *.psess 68 | *.vsp 69 | *.vspx 70 | 71 | # Guidance Automation Toolkit 72 | *.gpState 73 | 74 | # ReSharper is a .NET coding add-in 75 | _ReSharper*/ 76 | *.[Rr]e[Ss]harper 77 | 78 | # TeamCity is a build add-in 79 | _TeamCity* 80 | 81 | # DotCover is a Code Coverage Tool 82 | *.dotCover 83 | 84 | # NCrunch 85 | *.ncrunch* 86 | .*crunch*.local.xml 87 | 88 | # Installshield output folder 89 | [Ee]xpress/ 90 | 91 | # DocProject is a documentation generator add-in 92 | DocProject/buildhelp/ 93 | DocProject/Help/*.HxT 94 | DocProject/Help/*.HxC 95 | DocProject/Help/*.hhc 96 | DocProject/Help/*.hhk 97 | DocProject/Help/*.hhp 98 | DocProject/Help/Html2 99 | DocProject/Help/html 100 | 101 | # Click-Once directory 102 | publish/ 103 | 104 | # Publish Web Output 105 | *.Publish.xml 106 | 107 | # NuGet Packages Directory 108 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 109 | #packages/ 110 | 111 | # Windows Azure Build Output 112 | csx 113 | *.build.csdef 114 | 115 | # Windows Store app package directory 116 | AppPackages/ 117 | 118 | # Others 119 | sql/ 120 | *.Cache 121 | ClientBin/ 122 | [Ss]tyle[Cc]op.* 123 | ~$* 124 | *~ 125 | *.dbmdl 126 | *.[Pp]ublish.xml 127 | *.pfx 128 | *.publishsettings 129 | 130 | # RIA/Silverlight projects 131 | Generated_Code/ 132 | 133 | # Backup & report files from converting an old project file to a newer 134 | # Visual Studio version. Backup files are not needed, because we have git ;-) 135 | _UpgradeReport_Files/ 136 | Backup*/ 137 | UpgradeLog*.XML 138 | UpgradeLog*.htm 139 | 140 | # SQL Server files 141 | App_Data/*.mdf 142 | App_Data/*.ldf 143 | 144 | 145 | #LightSwitch generated files 146 | GeneratedArtifacts/ 147 | _Pvt_Extensions/ 148 | ModelManifest.xml 149 | 150 | # ========================= 151 | # Windows detritus 152 | # ========================= 153 | 154 | # Windows image file caches 155 | Thumbs.db 156 | ehthumbs.db 157 | 158 | # Folder config file 159 | Desktop.ini 160 | 161 | # Recycle Bin used on file shares 162 | $RECYCLE.BIN/ 163 | 164 | # Mac desktop service store files 165 | .DS_Store 166 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alexander Illarionov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | logo 4 | 5 | # Wlx2Explorer 6 | 7 |
8 | 9 | Wlx2Explorer is an application which allows you to use Total Commander lister plugins from File Explorer or Desktop. 10 | 11 | * Open File Explorer, select the necessary file and press the hot keys (Ctrl + Q), then you can use the plugin. 12 | * Or simply select the necessary file on your Desktop and press the hot keys (Ctrl + Q). 13 | 14 | Screenshot 15 | ------------------ 16 | 17 | ![alt tag](https://user-images.githubusercontent.com/8102586/101646453-9eba5500-3a48-11eb-9442-4ab87d7e3deb.gif) 18 | ![alt tag](https://user-images.githubusercontent.com/8102586/115141202-b7182d00-a043-11eb-88c0-1e0257337863.gif) 19 | 20 | Command Line Interface 21 | -------------------- 22 | 23 | ```bash 24 | -h --help The help 25 | -f --file Path to file 26 | -s --suppressmsg Suppress messages 27 | 28 | Example: 29 | Wlx2Explorer.exe -s --file "C:\Temp\Image.jpeg" 30 | ``` 31 | 32 | Requirements 33 | ------------------ 34 | 35 | * OS Windows XP SP3 and later. 36 | * .NET Framework 4.0 37 | 38 | Files 39 | ------------------ 40 | 41 | * Wlx2Explorer.exe - The main executable module. 42 | * Wlx2Explorer.xml - The application settings file. 43 | * Wlx2Explorer.ini - The plugins settings file. -------------------------------------------------------------------------------- /Wlx2Explorer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29318.209 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wlx2Explorer", "Wlx2Explorer\Wlx2Explorer.csproj", "{82A3A166-142C-4C62-8D57-6CF8678402AA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Debug|x64.ActiveCfg = Debug|x64 17 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Debug|x64.Build.0 = Debug|x64 18 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Debug|x86.ActiveCfg = Debug|x86 19 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Debug|x86.Build.0 = Debug|x86 20 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Release|x64.ActiveCfg = Release|x64 21 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Release|x64.Build.0 = Release|x64 22 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Release|x86.ActiveCfg = Release|x86 23 | {82A3A166-142C-4C62-8D57-6CF8678402AA}.Release|x86.Build.0 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | VisualSVNWorkingCopyRoot = . 30 | SolutionGuid = {BF0AC8CD-EEA6-4627-9260-407C1EA7A175} 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /Wlx2Explorer/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.ComponentModel; 4 | 5 | namespace Wlx2Explorer.Extensions 6 | { 7 | static class EnumExtensions 8 | { 9 | public static string GetDescription(this Enum value) => 10 | value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false).OfType()?.FirstOrDefault()?.Description ?? string.Empty; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/AboutForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Forms 2 | { 3 | partial class AboutForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm)); 32 | this.lblProductName = new System.Windows.Forms.Label(); 33 | this.lblCopyright = new System.Windows.Forms.Label(); 34 | this.linkUrl = new System.Windows.Forms.LinkLabel(); 35 | this.btnOk = new System.Windows.Forms.Button(); 36 | this.pbImage = new System.Windows.Forms.PictureBox(); 37 | this.lblProductTitle = new System.Windows.Forms.Label(); 38 | ((System.ComponentModel.ISupportInitialize)(this.pbImage)).BeginInit(); 39 | this.SuspendLayout(); 40 | // 41 | // lblProductName 42 | // 43 | this.lblProductName.AutoSize = true; 44 | this.lblProductName.Location = new System.Drawing.Point(58, 21); 45 | this.lblProductName.Name = "lblProductName"; 46 | this.lblProductName.Size = new System.Drawing.Size(75, 13); 47 | this.lblProductName.TabIndex = 0; 48 | this.lblProductName.Text = "Product Name"; 49 | // 50 | // lblCopyright 51 | // 52 | this.lblCopyright.AutoSize = true; 53 | this.lblCopyright.Location = new System.Drawing.Point(58, 72); 54 | this.lblCopyright.Name = "lblCopyright"; 55 | this.lblCopyright.Size = new System.Drawing.Size(51, 13); 56 | this.lblCopyright.TabIndex = 1; 57 | this.lblCopyright.Text = "Copyright"; 58 | // 59 | // linkUrl 60 | // 61 | this.linkUrl.AutoSize = true; 62 | this.linkUrl.Location = new System.Drawing.Point(58, 95); 63 | this.linkUrl.Name = "linkUrl"; 64 | this.linkUrl.Size = new System.Drawing.Size(29, 13); 65 | this.linkUrl.TabIndex = 2; 66 | this.linkUrl.TabStop = true; 67 | this.linkUrl.Text = "URL"; 68 | this.linkUrl.Click += new System.EventHandler(this.LinkClick); 69 | // 70 | // btnOk 71 | // 72 | this.btnOk.Location = new System.Drawing.Point(352, 16); 73 | this.btnOk.Name = "btnOk"; 74 | this.btnOk.Size = new System.Drawing.Size(75, 23); 75 | this.btnOk.TabIndex = 3; 76 | this.btnOk.Text = "Ok"; 77 | this.btnOk.UseVisualStyleBackColor = true; 78 | this.btnOk.Click += new System.EventHandler(this.CloseClick); 79 | // 80 | // pbImage 81 | // 82 | this.pbImage.Image = ((System.Drawing.Image)(resources.GetObject("pbImage.Image"))); 83 | this.pbImage.InitialImage = null; 84 | this.pbImage.Location = new System.Drawing.Point(4, 21); 85 | this.pbImage.Name = "pbImage"; 86 | this.pbImage.Size = new System.Drawing.Size(48, 48); 87 | this.pbImage.TabIndex = 4; 88 | this.pbImage.TabStop = false; 89 | // 90 | // lblProductTitle 91 | // 92 | this.lblProductTitle.AutoSize = true; 93 | this.lblProductTitle.Location = new System.Drawing.Point(58, 47); 94 | this.lblProductTitle.Name = "lblProductTitle"; 95 | this.lblProductTitle.Size = new System.Drawing.Size(67, 13); 96 | this.lblProductTitle.TabIndex = 5; 97 | this.lblProductTitle.Text = "Product Title"; 98 | // 99 | // AboutForm 100 | // 101 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 102 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 103 | this.ClientSize = new System.Drawing.Size(439, 132); 104 | this.Controls.Add(this.lblProductTitle); 105 | this.Controls.Add(this.pbImage); 106 | this.Controls.Add(this.btnOk); 107 | this.Controls.Add(this.linkUrl); 108 | this.Controls.Add(this.lblCopyright); 109 | this.Controls.Add(this.lblProductName); 110 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 111 | this.KeyPreview = true; 112 | this.MaximizeBox = false; 113 | this.MinimizeBox = false; 114 | this.Name = "AboutForm"; 115 | this.ShowInTaskbar = false; 116 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 117 | this.Text = "About"; 118 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormKeyDown); 119 | ((System.ComponentModel.ISupportInitialize)(this.pbImage)).EndInit(); 120 | this.ResumeLayout(false); 121 | this.PerformLayout(); 122 | 123 | } 124 | 125 | #endregion 126 | 127 | private System.Windows.Forms.Label lblProductName; 128 | private System.Windows.Forms.Label lblCopyright; 129 | private System.Windows.Forms.LinkLabel linkUrl; 130 | private System.Windows.Forms.Button btnOk; 131 | private System.Windows.Forms.PictureBox pbImage; 132 | private System.Windows.Forms.Label lblProductTitle; 133 | } 134 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/AboutForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows.Forms; 4 | using Wlx2Explorer.Utils; 5 | 6 | namespace Wlx2Explorer.Forms 7 | { 8 | partial class AboutForm : Form 9 | { 10 | private const string URL = "https://github.com/AlexanderPro/Wlx2Explorer"; 11 | 12 | public AboutForm() 13 | { 14 | InitializeComponent(); 15 | Text = $"About {AssemblyUtils.AssemblyProductName}"; 16 | lblProductName.Text = $"{AssemblyUtils.AssemblyProductName} v{AssemblyUtils.AssemblyProductVersion}"; 17 | lblProductTitle.Text = AssemblyUtils.AssemblyTitle; 18 | lblCopyright.Text = $"Copyright © 2014 - {DateTime.Now.Year}"; 19 | linkUrl.Text = URL; 20 | } 21 | 22 | private void CloseClick(object sender, EventArgs e) 23 | { 24 | Close(); 25 | } 26 | 27 | private void LinkClick(object sender, EventArgs e) 28 | { 29 | Process.Start(URL); 30 | } 31 | 32 | private void FormKeyDown(object sender, KeyEventArgs e) 33 | { 34 | CloseClick(sender, e); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/AboutForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAC 124 | 4gAAAuIBSbr4BAAAAAd0SU1FB90KCwwyJVCrQ6MAAA24SURBVGhD1ZoJVFTXHcZt0yTdkoiapumWpkua 125 | tqlJmnhijDZteurSNm2OMS5VE3erxQUVQZYZ9gDDKqsSF1zQoKAQFRQiKIMBhWEZlpFlWGYGhmEWZgZm 126 | gYGv//sYlhG0GEna3nN+RzMn+L7fvd+9773RKRMZZm2hQidPj1Q3HZ1XUrLpYfvH/z/D1Hmhz6LLh7Ix 127 | Bfr2i5Ye1SURfRZvUp16G6q4b9v/t//doW892G/RZcDWUwRpRSxaKsPQ2RCD7vbTsGiu2Kzay5Je3aUT 128 | ZtWZVUZlwnfsP/a/M7qa9vcb25MA63UMWMsgq02GuDAAreJwTsTQmoAexQGYVafQq7sCq/aK3KrNyrB0 129 | pjlbOo/83P7H/PeGThrZb2iLBSxZJHEN6K2AVn4RN3K8UHVjrIipjWTaD8KiOkkyl0kqR9urzf7Uqkn3 130 | 7mlLegVIfcj+R385QyeN6DcoogFzpoOEuasIwmw+inN5qC0Ogrw6AurGsSJDWDqOk1A2WyWTVZddbFVn 131 | hJmVR9+CLOIb9kt9MWNE4PwoiXySKIfNXANRgQAFl/ZBdM0X9aXBaKuNhEYae1eREaFkEspiK8T2UXWv 132 | JiPJ3P7R7+2XnbzhKDAkcckuUYGBvmbczPXD9Yv7cPNTHlerpnIBlLejoG2Kg1GWeE+RYZRHuT3ULUvO 133 | Ad6bvJqNFRi9EgVAnwSymmRczdwLYZYHJ1FZ6M+thqwqHKr6/dC3xqNbnshJ3FvkAHq1V9BW4uFqv/yD 134 | j/EFMuwSNFm9IhiUOZwAq1JxrjdK8324k6quJJjb5Mrb0dxq3L1W9N9tiUQCzB0noCz3z7df/sHH+AJ2 135 | CW4VimDS5A0LFNHpVJLHR4XQj9vcjWWh3EqMlaDA9uAmCm5qi4dJEUdVOoaOsoDr9ss/+Li3ANsLQphU 136 | WXcVaBCFcDe/dkkUd9zqW+Oo5ywsCz0S3KSIJWJIKhnKMr8vScB8kSTyYGzPQO65ewu01UZAVRcFXXMM 137 | bexY9MhZ6JHgJvl++iwapvYjJOD7JQmYPsGAOReGtnTs3uuPna48XDw7WiAQDbSZWypCoagJQ0ddBHRN 138 | 0TC2srAs9EjwHnkUemRRJHBocgW0jeF3ESBMGRgwXYZRcQbhYeHg8XzwL+c9eH/9Xhw7xEdtETuNgtBc 139 | EQxFdSg6boeRQCSMLVFUIxaaoNA9skgigsPUloR2EX/yBDR3EzClY6DnHAlkwaBIRUJCAgSCMHh5+WCb 140 | swtWrlyHpat2IUTgTzUKIoEQdEgE0ErDYWiJRHcrCz0UPBw9rWH0WRh62g5Cfos3eQLq8QS48Gcx0J1G 141 | v16AQZaCuLh4xMbGISREAA8PHtZt3I0fvJGE3//dBytW74KrRwDEN0KgbRTA0BxOYVlo9isLLiBC0d0S 142 | SidUIlpvek2eQOedAiaadS58KnEG/d2ZdLKcpOChnEB0dAyCAkOw3YWHJ15NwROzUvHdN1KwYf1WrFzj 143 | hk0eH6NUSBu5hYUmKHR3S4idYKpVPJqLJlOgIWyUwDkSYLNO4Y2n0W/8mDgPfUsyPD29IQgNw34SCA+P 144 | grtn8LDAtNfOcgKr1rhixrwcOL3xKd7efB652XSHptDdzR/CyBFEArFo/MxzEgXqRwlw4c/QzJ8mgRQK 145 | fwr9hjTamEep9zvh7e2D0NBwREZEg+8Xfk8Bp7lX8cz8HDSLBVxwY3MgjE0BtB9i0HDD/QsQGO79x4Ph 146 | DSeIk8QZEjiMD95fh507doPP86U6hcHXP2pEYPb4Ak5z87DF8zQX3NjkT/hRraJRX7B38gRUdoHh3nOz 147 | TuH1x4jjsOlToZMm4d3Fy7F2zUa4uOwBn+8Hb/7ICkwngc2bto0rMP13edDU+cMg9SV8SCASkmuukyhQ 148 | RwJ0k+F6T9XhZp2F7zoKG8dpaBo/wu8WbMGSJSuxfv1m7HJxxR63AAeBnTv3jivA6LztB0Mjn+DRnghH 149 | bd7uyRPoqBP0G+i8Hu694TiFT4ZNd5g4QqTQM04SHpsZg6dnhWH2fDd8sMYZW533Yeosu8DraXB388Ka 150 | jfvGF5D4UHhvwov2QhiqPt1VQJf+ymCCBxzK2yGDAkO91yeTAAv+EWzaQ8QJaBoOwunlWDz2YgIef+kg 151 | ZsxKwqyFoVjyQSDeXBKPp+elwtODj01b+eML1PKgb/AkPEggFOU5LkK6NPsOir3YfJVgMp9PSFkbTAIR 152 | o6rDwrPgBzn6tMnQNSYg82IetnqexzNvHsHjvz2Mx185Bidagd8sPISl68Kxz90b/9zmN66AqtYL+vp9 153 | hDsJBEOUvZ0JsHflrxOPEkzmawQTuj+R9toP+/V0x2Qblus9Fz4JNk0i+jgOQ1sfC6FQiOLiYhTfLIEg 154 | MR+z30sb3gNTX0vHs388g7eWJo0vUONB4d3QVbcXhqYglFzaVkiXfoxgX5x9i7hThq3KxEYbJxDGVYfr 155 | PRf+APrU8ejrJNQHoK4RQHj6NCcgEokgFoshkUhwPrsSy12uYsacc5g6OxNTX78IpzlXxgh0VLtTeFdi 156 | D51EgSi+4PwZXdqJmEo8QQzJMJjMxN+ZFTWBJCAY1XuqjTqBwseiTxWDXlUsVNVBEAYHo3j7doji4iCu 157 | rOQEpFIpZDIZKmta4RUlwk8XUvhxBfai6/ZuYhcJBOBGxpYiujT7lm8GMZ2YRgzJfJOY+AooqgI4geHe 158 | s9qo4yj8fvR2RKFXGQllpd9whUSpqRDv2QNJQACktBJMQKlUQqPRoFPTheSMFry59qajQNUeCu8CnWQn 159 | 9I1+KEjfXEyX/h7xXeIpgsk8SbBVYVWa+D5QVPmRQOhI77nqxJAAhe+IQG+7APJSrxGBoQrR76X+/pB5 160 | e0N54wYnYDAYYLFYYLPZkHhGNiIg3kXhdxDb6STygSjXS+HmPId9R/QD4vsEk3maYKvBNvPEh3xIYLj3 161 | rDrRFD6SZj+MBEIgyd0DobMzimNiICotHd4DXIWam6E8fBgaHg+G9HRYzGZO4MJ11SgBmv3abXacobtN 162 | G7opzngybtkuivAM8SPihwRbkUeIia+ArNKHBEJG9Z5Vh4UPp/ChMMsDkfvJocEVOHkSIhcXiGnmJbQS 163 | Q3tgqEKGwkJYqFq2lBRHgUqa/dp/QVvD2Iqe9tP0YnMMhZk7blOEnxE/IZ4lfkywOjGJiY3WCn6/nh55 164 | ud5TdQZ7z8ILYG0Lhlnmj5wLxx0rVFAACZ8PqacnZPT5sMBQhWgVRgsoK7ZxwbU1W6Ct/id6DeXo71Xj 165 | 5oUVBorwPPEcwb7pZrAVuQ+Bcn5/F91cBnvPqkO9V7LwIbAqgmBu9cWV3eshjI4ec4xK6+shO3gQSi8v 166 | aM6ehUGvH94DjgI08xRcW72Z2ASroYwTKM5czgReIH5N/JL4BcGqNPF90FLOI4EPx/Te2vYhCQTA1OKD 167 | y5/QChw5MniM+vhAfPOmwzHKrUBeHgx+frAkJtIDYJejQPkWaCi4pmojsWFY4LPzy5jAS8SLxEyCSbAj 168 | deL3AVkFEwhy6D2rjlURCKvcDz0tPGRnHhup0NWrENOMS9zdIc3Pd9wDrEJyOWxpaQ4C7WWbueCaqvXQ 169 | iNfBqhdxAoXnlhopwit2XiZYndjdeOJDLva2dTUHOPSeVccq94dF5oOeZm9kRfmOPUarqyGlm5rMwwNK 170 | ujfceYw6CtDsU3CNeC3U4jUkUEoCnRCmLWECs+0wCXas3t9fNCrEPjYdJ2CvDhc+gML7wtLKQ0+TJy79 171 | ZAaEzz2HYjrzRUVFjscoW4GcHGhoUxvi42EhkTECog1ccHXlB8T7gwJWEjj7bjdFmEe8QbxKPE5M/C7M 172 | xq3L20MMtIkHqzPYe4uMutzKh6XFC93Sfbj47HTQ4yPo9gnR1KkQb9gACdVnzDHa2AhLRARsyckOAm2l 173 | 67jg6srVUFesgklbgj6zCtfPLGYCfyCYBOv//dVnaBRmOq/Q1PnahnrPqmNp9Ya52RPdDW64MFqAEBOS 174 | hx6CdNEiyKjvY47RO1agrZRmn4KrK1ais+IfEN+6hltFNSTwDhOYT7xJsJvY/d2FRw9hxsZftIjcdEPV 175 | sbR4ksA+EnBF+LK/qXOe+9WAgwAhJWSE8oUXoNm/HwaVanyBkve54J3lK4jlyM7IRuqpIlxP/RsTWEiw 176 | PcAe4h5s5Oev+XrNte0VrDosvLnJDd31u/HOn55nt/wF2+e8k3LltT9Yqh55BHUUvImQEx2EljBOmwaL 177 | qytsTU0OAopbq7jgneXL0Fm2FB8lnENQ4GVc+/htJrCAYHfjid+8/tMozdp4qLtxL8xSVxjrXLDirzM3 178 | 0sfsrGY3nV9umrt4ec785a0t33mKC68h9EQPYSX6qV51a3aPEqDZp+CdZe9BVbYEBZ8E4HDcIeSe+DPN 179 | wZQ5BJv9z/dKebfxWebatWrxDpta7IzVi198iz5iT4vs0Zc99rKnRqcFLyz4ft6yHTmdM1+1mSl4L2Ej 180 | Bgjl3EUUfvCRWn5rORdcJXqXWIyrpxapyi79Oe9A0Dw2MV/cP2coSFs7U5i+unj+i0+x1z52QrBlHmL0 181 | e+xDOev8eco//t0w8OijgF3gqZd9MW1OBv7yp+fXB7u/dOR41Oxbcb6v5Xzz4Sm/pZ9hb17s5yd35u9j 182 | sAvfyZSsrdFzGxZvaqxbuLr3yVlxmP56Op78tS+bZfbayJ5zGA++Yb/w8UrJw07z8pY7zc0vnLLo0uc4 183 | 36dM+TcRZl/hRmSf3QAAAABJRU5ErkJggg== 184 | 185 | 186 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/ListerForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Forms 2 | { 3 | partial class ListerForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ListerForm)); 32 | this.pnlLister = new System.Windows.Forms.Panel(); 33 | this.SuspendLayout(); 34 | // 35 | // pnlLister 36 | // 37 | this.pnlLister.BackColor = System.Drawing.SystemColors.Control; 38 | this.pnlLister.Dock = System.Windows.Forms.DockStyle.Fill; 39 | this.pnlLister.Location = new System.Drawing.Point(0, 0); 40 | this.pnlLister.Name = "pnlLister"; 41 | this.pnlLister.Size = new System.Drawing.Size(715, 603); 42 | this.pnlLister.TabIndex = 0; 43 | // 44 | // ListerForm 45 | // 46 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 48 | this.AutoSize = true; 49 | this.ClientSize = new System.Drawing.Size(715, 603); 50 | this.Controls.Add(this.pnlLister); 51 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 52 | this.Name = "ListerForm"; 53 | this.Opacity = 0D; 54 | this.ShowInTaskbar = false; 55 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 56 | this.Text = "Lister"; 57 | this.ResumeLayout(false); 58 | 59 | } 60 | 61 | #endregion 62 | 63 | private System.Windows.Forms.Panel pnlLister; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/ListerForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | using System.Runtime.ExceptionServices; 7 | using System.IO; 8 | using System.Drawing.Printing; 9 | using Wlx2Explorer.Utils; 10 | using Wlx2Explorer.Settings; 11 | using Wlx2Explorer.Native; 12 | using Wlx2Explorer.Hooks; 13 | 14 | namespace Wlx2Explorer.Forms 15 | { 16 | partial class ListerForm : Form, IMessageFilter 17 | { 18 | private IntPtr _pluginHandle; 19 | private Plugin _plugin; 20 | private string _fileName; 21 | private ProgramSettings _settings; 22 | 23 | public ListerForm(ProgramSettings settings, IList plugins, string fileName) 24 | { 25 | InitializeComponent(); 26 | 27 | bool pluginLoaded = TryToLoadPlugin(settings, plugins, fileName, out _pluginHandle, out _plugin); 28 | if (!pluginLoaded) 29 | { 30 | Close(); 31 | return; 32 | } 33 | 34 | _settings = settings; 35 | _fileName = fileName; 36 | Text = "Lister - " + fileName; 37 | Width = settings.ListerFormWidth; 38 | Height = settings.ListerFormHeight; 39 | Opacity = 1.0; 40 | ShowInTaskbar = true; 41 | CenterToScreen(); 42 | WindowState = settings.ListerFormMaximized ? FormWindowState.Maximized : WindowState; 43 | Application.AddMessageFilter(this); 44 | } 45 | 46 | [HandleProcessCorruptedStateExceptions] 47 | private bool TryToLoadPlugin(ProgramSettings settings, IList plugins, string fileName, out IntPtr pluginHandle, out Plugin plugin) 48 | { 49 | pluginHandle = IntPtr.Zero; 50 | plugin = null; 51 | foreach (var sourcePlugin in plugins) 52 | { 53 | try 54 | { 55 | PluginInfo pluginInfo = settings.Plugins.FirstOrDefault(x => string.Compare(x.Path, sourcePlugin.ModuleName) == 0); 56 | string extension = Path.GetExtension(fileName).TrimStart('.'); 57 | if (pluginInfo.Extensions.Count == 0 || pluginInfo.Extensions.Contains(extension.ToLower()) || pluginInfo.Extensions.Contains(extension.ToUpper())) 58 | { 59 | pluginHandle = sourcePlugin.ListLoad(pnlLister.Handle, fileName); 60 | } 61 | } 62 | catch 63 | { 64 | } 65 | 66 | if (pluginHandle != IntPtr.Zero) 67 | { 68 | plugin = sourcePlugin; 69 | break; 70 | } 71 | } 72 | return pluginHandle != IntPtr.Zero; 73 | } 74 | 75 | protected override void OnLoad(EventArgs e) 76 | { 77 | base.OnLoad(e); 78 | 79 | pnlLister.Focus(); 80 | NativeMethods.SetFocus(_pluginHandle); 81 | } 82 | 83 | [HandleProcessCorruptedStateExceptions] 84 | protected override void OnClosing(CancelEventArgs e) 85 | { 86 | base.OnClosing(e); 87 | 88 | try 89 | { 90 | if (_plugin.ListCloseWindowExist) 91 | { 92 | _plugin.ListCloseWindow(_pluginHandle); 93 | } 94 | else 95 | { 96 | NativeMethods.DestroyWindow(_pluginHandle); 97 | } 98 | Application.RemoveMessageFilter(this); 99 | } 100 | catch 101 | { 102 | } 103 | } 104 | 105 | protected override void OnResize(EventArgs e) 106 | { 107 | base.OnResize(e); 108 | 109 | if (_pluginHandle == IntPtr.Zero) return; 110 | NativeMethods.SetWindowPos(_pluginHandle, new IntPtr(0), 0, 0, pnlLister.Width, pnlLister.Height, 0); 111 | } 112 | 113 | bool IMessageFilter.PreFilterMessage(ref Message m) 114 | { 115 | if (m.Msg == NativeConstants.WM_KEYDOWN && WindowUtils.IsChildWindow(m.HWnd, Handle)) 116 | { 117 | if (m.WParam.ToInt32() == _settings.SearchDialogKey3) 118 | { 119 | var key1 = true; 120 | var key2 = true; 121 | 122 | if ((VirtualKeyModifier)_settings.SearchDialogKey1 != VirtualKeyModifier.None) 123 | { 124 | int key1State = NativeMethods.GetAsyncKeyState(_settings.SearchDialogKey1) & 0x8000; 125 | key1 = Convert.ToBoolean(key1State); 126 | } 127 | 128 | if ((VirtualKeyModifier)_settings.SearchDialogKey2 != VirtualKeyModifier.None) 129 | { 130 | int key2State = NativeMethods.GetAsyncKeyState(_settings.SearchDialogKey2) & 0x8000; 131 | key2 = Convert.ToBoolean(key2State); 132 | } 133 | 134 | if (key1 && key2) 135 | { 136 | if (!_plugin.ListSearchDialogExist && !_plugin.ListSearchTextExist) 137 | { 138 | MessageBox.Show("This plugin does not support text search!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 139 | } 140 | else 141 | if (_plugin.ListSearchDialogExist) 142 | { 143 | _plugin.ListSearchDialog(_pluginHandle, 0); 144 | } 145 | else 146 | { 147 | var searchDlg = new SearchForm(); 148 | var result = searchDlg.ShowDialog(this); 149 | if (result == DialogResult.OK) 150 | { 151 | var flags = 0; 152 | flags |= SearchForm.SearchFromBeginning ? NativeConstants.LCS_FINDFIRST : 0; 153 | flags |= SearchForm.SearchCaseSensitive ? NativeConstants.LCS_MATCHCASE : 0; 154 | flags |= SearchForm.SearchWholeWordsOnly ? NativeConstants.LCS_WHOLEWORDS : 0; 155 | flags |= SearchForm.SearchBackwards ? NativeConstants.LCS_BACKWARDS : 0; 156 | _plugin.ListSearchText(_pluginHandle, SearchForm.SearchingText, flags); 157 | } 158 | } 159 | } 160 | } 161 | 162 | if (m.WParam.ToInt32() == _settings.PrintDialogKey3) 163 | { 164 | var key1 = true; 165 | var key2 = true; 166 | 167 | if ((VirtualKeyModifier)_settings.PrintDialogKey1 != VirtualKeyModifier.None) 168 | { 169 | int key1State = NativeMethods.GetAsyncKeyState(_settings.PrintDialogKey1) & 0x8000; 170 | key1 = Convert.ToBoolean(key1State); 171 | } 172 | 173 | if ((VirtualKeyModifier)_settings.PrintDialogKey2 != VirtualKeyModifier.None) 174 | { 175 | int key2State = NativeMethods.GetAsyncKeyState(_settings.PrintDialogKey2) & 0x8000; 176 | key2 = Convert.ToBoolean(key2State); 177 | } 178 | 179 | if (key1 && key2) 180 | { 181 | if (!_plugin.ListPrintExist) 182 | { 183 | MessageBox.Show("This plugin does not support printing!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 184 | } 185 | else 186 | { 187 | Rect rectangle = null; 188 | PrinterSettings printerSettings = new PrinterSettings(); 189 | _plugin.ListPrint(_pluginHandle, _fileName, printerSettings.PrinterName, 0, ref rectangle); 190 | } 191 | } 192 | } 193 | 194 | if (m.WParam.ToInt32() == (int)VirtualKey.VK_F3) 195 | { 196 | if (_plugin.ListSearchTextExist && !string.IsNullOrEmpty(SearchForm.SearchingText)) 197 | { 198 | var flags = 0; 199 | flags |= SearchForm.SearchFromBeginning ? NativeConstants.LCS_FINDFIRST : 0; 200 | flags |= SearchForm.SearchCaseSensitive ? NativeConstants.LCS_MATCHCASE : 0; 201 | flags |= SearchForm.SearchWholeWordsOnly ? NativeConstants.LCS_WHOLEWORDS : 0; 202 | flags |= SearchForm.SearchBackwards ? NativeConstants.LCS_BACKWARDS : 0; 203 | _plugin.ListSearchText(_pluginHandle, SearchForm.SearchingText, flags); 204 | } 205 | } 206 | 207 | if (m.WParam.ToInt32() == (int)VirtualKey.VK_ESCAPE) 208 | { 209 | Close(); 210 | } 211 | } 212 | 213 | return false; 214 | } 215 | } 216 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Forms 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 33 | this.miStartStop = new System.Windows.Forms.ToolStripMenuItem(); 34 | this.miSettings = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.miAbout = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.miSeparator = new System.Windows.Forms.ToolStripSeparator(); 37 | this.miExit = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.iconSystemTray = new System.Windows.Forms.NotifyIcon(this.components); 39 | this.menuSystemTray = new System.Windows.Forms.ContextMenuStrip(this.components); 40 | this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); 42 | this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); 43 | this.menuSystemTray.SuspendLayout(); 44 | this.SuspendLayout(); 45 | // 46 | // miStartStop 47 | // 48 | this.miStartStop.Image = global::Wlx2Explorer.Properties.Resources.Start; 49 | this.miStartStop.Name = "miStartStop"; 50 | this.miStartStop.Size = new System.Drawing.Size(125, 22); 51 | this.miStartStop.Text = "Stop"; 52 | this.miStartStop.Click += new System.EventHandler(this.MenuItemStartStopClick); 53 | // 54 | // miSettings 55 | // 56 | this.miSettings.Name = "miSettings"; 57 | this.miSettings.Size = new System.Drawing.Size(125, 22); 58 | this.miSettings.Text = "Settings..."; 59 | this.miSettings.Click += new System.EventHandler(this.MenuItemSettingsClick); 60 | // 61 | // miAbout 62 | // 63 | this.miAbout.Name = "miAbout"; 64 | this.miAbout.Size = new System.Drawing.Size(125, 22); 65 | this.miAbout.Text = "About"; 66 | this.miAbout.Click += new System.EventHandler(this.MenuItemAboutClick); 67 | // 68 | // miSeparator 69 | // 70 | this.miSeparator.Name = "miSeparator"; 71 | this.miSeparator.Size = new System.Drawing.Size(122, 6); 72 | // 73 | // miExit 74 | // 75 | this.miExit.Name = "miExit"; 76 | this.miExit.Size = new System.Drawing.Size(125, 22); 77 | this.miExit.Text = "Exit"; 78 | this.miExit.Click += new System.EventHandler(this.MenuItemExitClick); 79 | // 80 | // iconSystemTray 81 | // 82 | this.iconSystemTray.ContextMenuStrip = this.menuSystemTray; 83 | this.iconSystemTray.Icon = ((System.Drawing.Icon)(resources.GetObject("iconSystemTray.Icon"))); 84 | this.iconSystemTray.Visible = true; 85 | // 86 | // menuSystemTray 87 | // 88 | this.menuSystemTray.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 89 | this.miStartStop, 90 | this.miSettings, 91 | this.miAbout, 92 | this.miSeparator, 93 | this.miExit}); 94 | this.menuSystemTray.Name = "menuSystemTray"; 95 | this.menuSystemTray.Size = new System.Drawing.Size(126, 98); 96 | // 97 | // toolStripMenuItem1 98 | // 99 | this.toolStripMenuItem1.Name = "toolStripMenuItem1"; 100 | this.toolStripMenuItem1.Size = new System.Drawing.Size(32, 19); 101 | // 102 | // toolStripMenuItem2 103 | // 104 | this.toolStripMenuItem2.Name = "toolStripMenuItem2"; 105 | this.toolStripMenuItem2.Size = new System.Drawing.Size(32, 19); 106 | // 107 | // toolStripMenuItem3 108 | // 109 | this.toolStripMenuItem3.Name = "toolStripMenuItem3"; 110 | this.toolStripMenuItem3.Size = new System.Drawing.Size(32, 19); 111 | // 112 | // MainForm 113 | // 114 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 115 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 116 | this.ClientSize = new System.Drawing.Size(364, 147); 117 | this.Name = "MainForm"; 118 | this.Opacity = 0D; 119 | this.ShowInTaskbar = false; 120 | this.Text = "Wlx2Explorer"; 121 | this.menuSystemTray.ResumeLayout(false); 122 | this.ResumeLayout(false); 123 | 124 | } 125 | 126 | #endregion 127 | 128 | private System.Windows.Forms.NotifyIcon iconSystemTray; 129 | private System.Windows.Forms.ToolStripMenuItem miStartStop; 130 | private System.Windows.Forms.ToolStripMenuItem miSettings; 131 | private System.Windows.Forms.ToolStripMenuItem miAbout; 132 | private System.Windows.Forms.ToolStripSeparator miSeparator; 133 | private System.Windows.Forms.ToolStripMenuItem miExit; 134 | private System.Windows.Forms.ContextMenuStrip menuSystemTray; 135 | private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; 136 | private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; 137 | private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3; 138 | 139 | } 140 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | using Wlx2Explorer.Utils; 6 | using Wlx2Explorer.Settings; 7 | using Wlx2Explorer.Native; 8 | using Wlx2Explorer.Hooks; 9 | 10 | namespace Wlx2Explorer.Forms 11 | { 12 | partial class MainForm : Form 13 | { 14 | private IList _plugins; 15 | private KeyboardHook _keyboardKook; 16 | private ProgramSettings _settings; 17 | private ListerForm _listerForm; 18 | private AboutForm _aboutForm; 19 | private ProgramSettingsForm _settingsForm; 20 | private bool _isProgramStarted; 21 | 22 | public MainForm() 23 | { 24 | InitializeComponent(); 25 | iconSystemTray.Text = AssemblyUtils.AssemblyTitle; 26 | 27 | Start(); 28 | ChangeMenuStartStopText(); 29 | } 30 | 31 | protected override void OnLoad(EventArgs e) 32 | { 33 | BeginInvoke(new Action(Hide)); 34 | base.OnLoad(e); 35 | } 36 | 37 | private void Start() 38 | { 39 | Environment.CurrentDirectory = AssemblyUtils.AssemblyDirectory; 40 | _isProgramStarted = false; 41 | try 42 | { 43 | _settings = ProgramSettings.Read(); 44 | } 45 | catch 46 | { 47 | MessageBox.Show("Failed to read a program setting file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 48 | return; 49 | } 50 | 51 | if (_listerForm != null && _listerForm.IsHandleCreated) 52 | { 53 | _listerForm.Close(); 54 | } 55 | 56 | _plugins = _plugins ?? new List(); 57 | foreach (var plugin in _plugins) 58 | { 59 | try 60 | { 61 | plugin.UnloadModule(); 62 | } 63 | catch 64 | { 65 | var message = $@"Failed to unload a plugin ""{plugin.ModuleName}""."; 66 | MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 67 | } 68 | } 69 | _plugins.Clear(); 70 | 71 | foreach (var pluginInfo in _settings.Plugins) 72 | { 73 | var plugin = new Plugin(pluginInfo.Path); 74 | var pluginLoaded = false; 75 | var pluginInitialized = true; 76 | 77 | try 78 | { 79 | pluginLoaded = plugin.LoadModule(); 80 | } 81 | catch 82 | { 83 | pluginLoaded = false; 84 | } 85 | 86 | try 87 | { 88 | if (plugin.ListSetDefaultParamsExist) 89 | { 90 | var pluginExtension = Path.GetExtension(pluginInfo.Path); 91 | var pluginIniFile = Path.GetFullPath(pluginInfo.Path).Replace(pluginExtension, ".ini"); 92 | if (!File.Exists(pluginIniFile)) 93 | { 94 | plugin.ListSetDefaultParams(_settings.PluginLowVersion, _settings.PluginHighVersion, _settings.PluginIniFile); 95 | } 96 | } 97 | } 98 | catch 99 | { 100 | pluginInitialized = false; 101 | } 102 | 103 | if (pluginLoaded && pluginInitialized) 104 | { 105 | _plugins.Add(plugin); 106 | } 107 | else 108 | if (!pluginLoaded) 109 | { 110 | MessageBox.Show($@"Failed to load the plugin {Environment.NewLine} ""{pluginInfo.Path}"".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 111 | } 112 | else 113 | { 114 | MessageBox.Show($@"Failed to initialize the plugin with default settings {Environment.NewLine} ""{pluginInfo.Path}"".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 115 | } 116 | } 117 | 118 | try 119 | { 120 | _keyboardKook = _keyboardKook ?? new KeyboardHook(); 121 | _keyboardKook.Stop(); 122 | _keyboardKook.Hooked -= KeyHooked; 123 | _keyboardKook.Hooked += KeyHooked; 124 | bool result = _keyboardKook.Start(_settings.ListerFormKey1, _settings.ListerFormKey2, _settings.ListerFormKey3); 125 | if (!result) throw new Exception("Failed to run a keyboard hook."); 126 | _isProgramStarted = true; 127 | } 128 | catch (Exception ex) 129 | { 130 | MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 131 | } 132 | } 133 | 134 | private void Stop() 135 | { 136 | if (_listerForm != null && _listerForm.IsHandleCreated) 137 | { 138 | _listerForm.Close(); 139 | } 140 | 141 | _plugins = _plugins ?? new List(); 142 | foreach (var plugin in _plugins) 143 | { 144 | try 145 | { 146 | plugin.UnloadModule(); 147 | } 148 | catch 149 | { 150 | MessageBox.Show($@"Failed to unload a plugin ""{ plugin.ModuleName}"".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 151 | } 152 | } 153 | _plugins.Clear(); 154 | _keyboardKook = _keyboardKook ?? new KeyboardHook(); 155 | _keyboardKook.Stop(); 156 | _keyboardKook.Hooked -= KeyHooked; 157 | _isProgramStarted = false; 158 | } 159 | 160 | private void KeyHooked(object sender, EventArgs e) 161 | { 162 | if (InvokeRequired) 163 | { 164 | Invoke(new Action(ShowListerForm)); 165 | } 166 | else 167 | { 168 | ShowListerForm(); 169 | } 170 | } 171 | 172 | private void ShowListerForm() 173 | { 174 | var fileName = (string)null; 175 | try 176 | { 177 | fileName = WindowUtils.GetSelectedFileFromDesktopOrExplorer(); 178 | } 179 | catch (Exception e) 180 | { 181 | MessageBox.Show($"Failed to get selected file. {e.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 182 | return; 183 | } 184 | 185 | Environment.CurrentDirectory = AssemblyUtils.AssemblyDirectory; 186 | 187 | if (_listerForm != null && _listerForm.IsHandleCreated) 188 | { 189 | _listerForm.Close(); 190 | } 191 | 192 | if (_listerForm == null || _listerForm.IsDisposed) 193 | { 194 | _listerForm = new ListerForm(_settings, _plugins, fileName); 195 | } 196 | 197 | if (_listerForm.IsDisposed) 198 | { 199 | _listerForm = null; 200 | } 201 | else 202 | { 203 | var hwnd = NativeMethods.GetForegroundWindow(); 204 | var className = WindowUtils.GetClassName(hwnd); 205 | if (className == "WorkerW" || className == "Progman") 206 | { 207 | _listerForm.Show(); 208 | } 209 | else 210 | { 211 | _listerForm.Show(new Win32WindowWrapper(hwnd)); 212 | } 213 | _listerForm.Activate(); 214 | } 215 | } 216 | 217 | private void MenuItemStartStopClick(object sender, EventArgs e) 218 | { 219 | if (_isProgramStarted) 220 | { 221 | Stop(); 222 | } 223 | else 224 | { 225 | Start(); 226 | } 227 | ChangeMenuStartStopText(); 228 | } 229 | 230 | private void MenuItemSettingsClick(object sender, EventArgs e) 231 | { 232 | if (_settingsForm == null || _settingsForm.IsDisposed || !_settingsForm.IsHandleCreated) 233 | { 234 | if (_settings != null) 235 | { 236 | _settings.AutoStartProgram = StartUpManager.IsInStartup(AssemblyUtils.AssemblyProductName, AssemblyUtils.AssemblyLocation); 237 | } 238 | Environment.CurrentDirectory = AssemblyUtils.AssemblyDirectory; 239 | _settingsForm = new ProgramSettingsForm(_settings); 240 | } 241 | 242 | if (!_settingsForm.Visible) 243 | { 244 | DialogResult result = _settingsForm.ShowDialog(); 245 | if (result == DialogResult.OK) 246 | { 247 | try 248 | { 249 | ProgramSettings.Write(_settingsForm.Settings); 250 | } 251 | catch 252 | { 253 | MessageBox.Show("Failed to save program settings.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 254 | return; 255 | } 256 | if (_settingsForm.Settings.AutoStartProgram) 257 | { 258 | StartUpManager.AddToStartup(AssemblyUtils.AssemblyProductName, AssemblyUtils.AssemblyLocation); 259 | } 260 | else 261 | if (StartUpManager.IsInStartup(AssemblyUtils.AssemblyProductName, AssemblyUtils.AssemblyLocation)) 262 | { 263 | StartUpManager.RemoveFromStartup(AssemblyUtils.AssemblyProductName); 264 | } 265 | Stop(); 266 | Start(); 267 | } 268 | } 269 | } 270 | 271 | private void MenuItemAboutClick(object sender, EventArgs e) 272 | { 273 | if (_aboutForm == null || _aboutForm.IsDisposed || !_aboutForm.IsHandleCreated) 274 | { 275 | _aboutForm = new AboutForm(); 276 | } 277 | _aboutForm.Show(); 278 | _aboutForm.Activate(); 279 | } 280 | 281 | private void MenuItemExitClick(object sender, EventArgs e) 282 | { 283 | Close(); 284 | } 285 | 286 | private void ChangeMenuStartStopText() 287 | { 288 | if (_isProgramStarted) 289 | { 290 | miStartStop.Image = Properties.Resources.Stop; 291 | miStartStop.Text = "Stop"; 292 | } 293 | else 294 | { 295 | miStartStop.Image = Properties.Resources.Start; 296 | miStartStop.Text = "Start"; 297 | } 298 | } 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 46, 17 122 | 123 | 124 | 162, 16 125 | 126 | 127 | 128 | 129 | AAABAAEACxAAAAEAIAAoAwAAFgAAACgAAAALAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 130 | AAD///8A////AAD//wFQj68Q////AAAAAAF6WZhFb1bN1qI2EqoiZnEtAAAAEP///wBbl7URa8bc6k2P 131 | orJdSImaSD/Q+AkJ8f9VUff/oWJK/1XP6/+DtcXibrnQQX3X6vx94vj/SnvB/wwMzv9iYt7/y8vt/+HW 132 | 6/+kZU7/W9Hs/67V4P94zN/xjef6/4Pk+f9pnMn/u7vO/7q63v/IyO3/7OHp/6ZmTv9h0+3/s+by/3fL 133 | 3PeT6vv/ieb5/4CyzP+5uc7/wMDe/8zM7f/s4en/p2dO/2fV7v+25/L/esze95js+/+P6fr/gbvU/7Ky 134 | zv/Jyd7/zMzt/+LW5/+pZ0//btfv/4TJ2rh7zt72nu/8/5Xr+/+X0eX/sLDO/87Fzf/PlH//w04o/6to 135 | T/922vD/bL/WU3/R4fWj8f3/m+78/6DW4/+taFL/nEEl/5VdTP++PRP/rGhP/3zc8f91y+FLgtLl9an0 136 | /v+h8P3/nsvW/29aVv+dTTT/jFxN/749E/+talD/gt7y/3zO5EuD1Ob1r/b//6fz/v+g0t7/jYqK/5tM 137 | Mv+FU0X/vkAa/5qopf+I4PP/gNXoS4PV5vWx9///rfX+/67c5/+MiYn/gVFC/4p6c/+R0dv/jOL0/47i 138 | 9P+F1e9Lg9Xo9bH3//+y9///td3n/3x8ev+FxND/jNbl/5Pi8/+S5Pb/k+T1/4jb70uD1ej1sff//7L3 139 | //+45u//fLvI/4XI1v+R2ej/meb2/5jm9/+Y5vb/jdrvSoPV6PWy9///vfj//57R3f+Fx9X/ld/u/5rn 140 | 9/+b5/f/pur4+5/l9bZ///8EhNbo9bv1/f+d0d3/ld3r/6fq+POo6vi+pun4gabp9jeZzP8F////AP// 141 | /wCk3uvhq+LtxKXn9m6k7PkmAP//Af///wD///8A////AP///wD///8A////AP5gAADAAAAAgAAAAAAA 142 | AAAAAAAAAAAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAAeAAAD/gAAA= 143 | 144 | 145 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/MessageBoxForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Forms 2 | { 3 | partial class MessageBoxForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btnOk = new System.Windows.Forms.Button(); 32 | this.txtMessage = new System.Windows.Forms.TextBox(); 33 | this.SuspendLayout(); 34 | // 35 | // btnOk 36 | // 37 | this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 38 | this.btnOk.Location = new System.Drawing.Point(431, 137); 39 | this.btnOk.Name = "btnOk"; 40 | this.btnOk.Size = new System.Drawing.Size(115, 30); 41 | this.btnOk.TabIndex = 0; 42 | this.btnOk.Text = "Ok"; 43 | this.btnOk.UseVisualStyleBackColor = true; 44 | this.btnOk.Click += new System.EventHandler(this.OkClick); 45 | // 46 | // txtMessage 47 | // 48 | this.txtMessage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 49 | | System.Windows.Forms.AnchorStyles.Left) 50 | | System.Windows.Forms.AnchorStyles.Right))); 51 | this.txtMessage.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 52 | this.txtMessage.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 53 | this.txtMessage.Location = new System.Drawing.Point(12, 12); 54 | this.txtMessage.Multiline = true; 55 | this.txtMessage.Name = "txtMessage"; 56 | this.txtMessage.ReadOnly = true; 57 | this.txtMessage.Size = new System.Drawing.Size(534, 107); 58 | this.txtMessage.TabIndex = 1; 59 | this.txtMessage.TabStop = false; 60 | // 61 | // MessageBoxForm 62 | // 63 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 64 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 65 | this.AutoSize = true; 66 | this.ClientSize = new System.Drawing.Size(558, 201); 67 | this.Controls.Add(this.txtMessage); 68 | this.Controls.Add(this.btnOk); 69 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 70 | this.KeyPreview = true; 71 | this.MaximizeBox = false; 72 | this.MinimizeBox = false; 73 | this.Name = "MessageBoxForm"; 74 | this.ShowIcon = false; 75 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 76 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormKeyDown); 77 | this.ResumeLayout(false); 78 | this.PerformLayout(); 79 | 80 | } 81 | 82 | #endregion 83 | private System.Windows.Forms.Button btnOk; 84 | private System.Windows.Forms.TextBox txtMessage; 85 | } 86 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/MessageBoxForm.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace Wlx2Explorer.Forms 4 | { 5 | public partial class MessageBoxForm : Form 6 | { 7 | public string Message 8 | { 9 | get 10 | { 11 | return txtMessage.Text; 12 | } 13 | set 14 | { 15 | txtMessage.Text = value; 16 | } 17 | } 18 | 19 | public MessageBoxForm() 20 | { 21 | InitializeComponent(); 22 | } 23 | 24 | private void OkClick(object sender, System.EventArgs e) 25 | { 26 | Close(); 27 | } 28 | 29 | private void FormKeyDown(object sender, KeyEventArgs e) 30 | { 31 | if (e.KeyValue == 13 || e.KeyValue == 27) 32 | { 33 | Close(); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/MessageBoxForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/PluginSettingsForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Forms 2 | { 3 | partial class PluginSettingsForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.txtFileName = new System.Windows.Forms.TextBox(); 32 | this.btnBrowse = new System.Windows.Forms.Button(); 33 | this.txtExtensions = new System.Windows.Forms.TextBox(); 34 | this.lblFileName = new System.Windows.Forms.Label(); 35 | this.lblExtensions = new System.Windows.Forms.Label(); 36 | this.btnOk = new System.Windows.Forms.Button(); 37 | this.btnCancel = new System.Windows.Forms.Button(); 38 | this.SuspendLayout(); 39 | // 40 | // txtFileName 41 | // 42 | this.txtFileName.Location = new System.Drawing.Point(12, 30); 43 | this.txtFileName.Name = "txtFileName"; 44 | this.txtFileName.Size = new System.Drawing.Size(426, 20); 45 | this.txtFileName.TabIndex = 1; 46 | // 47 | // btnBrowse 48 | // 49 | this.btnBrowse.Location = new System.Drawing.Point(444, 29); 50 | this.btnBrowse.Name = "btnBrowse"; 51 | this.btnBrowse.Size = new System.Drawing.Size(43, 22); 52 | this.btnBrowse.TabIndex = 2; 53 | this.btnBrowse.Text = "..."; 54 | this.btnBrowse.UseVisualStyleBackColor = true; 55 | this.btnBrowse.Click += new System.EventHandler(this.BrowseClick); 56 | // 57 | // txtExtensions 58 | // 59 | this.txtExtensions.Location = new System.Drawing.Point(12, 93); 60 | this.txtExtensions.Name = "txtExtensions"; 61 | this.txtExtensions.Size = new System.Drawing.Size(474, 20); 62 | this.txtExtensions.TabIndex = 4; 63 | // 64 | // lblFileName 65 | // 66 | this.lblFileName.AutoSize = true; 67 | this.lblFileName.Location = new System.Drawing.Point(13, 13); 68 | this.lblFileName.Name = "lblFileName"; 69 | this.lblFileName.Size = new System.Drawing.Size(58, 13); 70 | this.lblFileName.TabIndex = 0; 71 | this.lblFileName.Text = "Plugin File:"; 72 | // 73 | // lblExtensions 74 | // 75 | this.lblExtensions.AutoSize = true; 76 | this.lblExtensions.Location = new System.Drawing.Point(13, 77); 77 | this.lblExtensions.Name = "lblExtensions"; 78 | this.lblExtensions.Size = new System.Drawing.Size(113, 13); 79 | this.lblExtensions.TabIndex = 3; 80 | this.lblExtensions.Text = "Supported Extensions:"; 81 | // 82 | // btnOk 83 | // 84 | this.btnOk.Location = new System.Drawing.Point(352, 131); 85 | this.btnOk.Name = "btnOk"; 86 | this.btnOk.Size = new System.Drawing.Size(64, 23); 87 | this.btnOk.TabIndex = 5; 88 | this.btnOk.Text = "Ok"; 89 | this.btnOk.UseVisualStyleBackColor = true; 90 | this.btnOk.Click += new System.EventHandler(this.OkClick); 91 | // 92 | // btnCancel 93 | // 94 | this.btnCancel.Location = new System.Drawing.Point(422, 131); 95 | this.btnCancel.Name = "btnCancel"; 96 | this.btnCancel.Size = new System.Drawing.Size(64, 23); 97 | this.btnCancel.TabIndex = 6; 98 | this.btnCancel.Text = "Cancel"; 99 | this.btnCancel.UseVisualStyleBackColor = true; 100 | this.btnCancel.Click += new System.EventHandler(this.CancelClick); 101 | // 102 | // PluginSettingsForm 103 | // 104 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 105 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 106 | this.ClientSize = new System.Drawing.Size(498, 168); 107 | this.Controls.Add(this.btnCancel); 108 | this.Controls.Add(this.btnOk); 109 | this.Controls.Add(this.lblExtensions); 110 | this.Controls.Add(this.lblFileName); 111 | this.Controls.Add(this.txtExtensions); 112 | this.Controls.Add(this.btnBrowse); 113 | this.Controls.Add(this.txtFileName); 114 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 115 | this.KeyPreview = true; 116 | this.MaximizeBox = false; 117 | this.MinimizeBox = false; 118 | this.Name = "PluginSettingsForm"; 119 | this.ShowInTaskbar = false; 120 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 121 | this.Text = "Plugin Settings"; 122 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormKeyDown); 123 | this.ResumeLayout(false); 124 | this.PerformLayout(); 125 | 126 | } 127 | 128 | #endregion 129 | 130 | private System.Windows.Forms.TextBox txtFileName; 131 | private System.Windows.Forms.Button btnBrowse; 132 | private System.Windows.Forms.TextBox txtExtensions; 133 | private System.Windows.Forms.Label lblFileName; 134 | private System.Windows.Forms.Label lblExtensions; 135 | private System.Windows.Forms.Button btnOk; 136 | private System.Windows.Forms.Button btnCancel; 137 | } 138 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/PluginSettingsForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | using Wlx2Explorer.Utils; 5 | 6 | namespace Wlx2Explorer.Forms 7 | { 8 | partial class PluginSettingsForm : Form 9 | { 10 | public string FileName { get { return txtFileName.Text; } } 11 | 12 | public string Extensions { get { return txtExtensions.Text; } } 13 | 14 | public PluginSettingsForm(string fileName, string extensions) 15 | { 16 | InitializeComponent(); 17 | 18 | fileName = Path.IsPathRooted(fileName) ? fileName : Path.Combine(AssemblyUtils.AssemblyDirectory, fileName); 19 | txtFileName.Text = fileName; 20 | txtExtensions.Text = extensions; 21 | } 22 | 23 | private void BrowseClick(object sender, EventArgs e) 24 | { 25 | var dialog = new OpenFileDialog() 26 | { 27 | RestoreDirectory = true, 28 | Filter = "Plugin files (*.wlx;*.wlx64)|*.wlx;*.wlx64|All files (*.*)|*.*" 29 | }; 30 | 31 | if (File.Exists(txtFileName.Text)) 32 | { 33 | dialog.InitialDirectory = Path.GetDirectoryName(txtFileName.Text); 34 | } 35 | 36 | if (dialog.ShowDialog() == DialogResult.OK) 37 | { 38 | txtFileName.Text = dialog.FileName; 39 | txtExtensions.Text = string.Join(";", Plugin.GetSupportedExtensions(dialog.FileName)); 40 | } 41 | } 42 | 43 | private void OkClick(object sender, EventArgs e) 44 | { 45 | if (!File.Exists(txtFileName.Text)) 46 | { 47 | MessageBox.Show("You should select an existing file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 48 | return; 49 | } 50 | 51 | try 52 | { 53 | txtExtensions.Text.Split(';'); 54 | } 55 | catch 56 | { 57 | MessageBox.Show("Extensions must be separated by semicolons.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 58 | return; 59 | } 60 | 61 | DialogResult = DialogResult.OK; 62 | Close(); 63 | } 64 | 65 | private void CancelClick(object sender, EventArgs e) 66 | { 67 | DialogResult = DialogResult.Cancel; 68 | Close(); 69 | } 70 | 71 | private void FormKeyDown(object sender, KeyEventArgs e) 72 | { 73 | if (e.KeyValue == 27) 74 | { 75 | CancelClick(sender, (EventArgs)e); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/PluginSettingsForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/ProgramSettingsForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using System.Linq; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | using Wlx2Explorer.Settings; 7 | using Wlx2Explorer.Utils; 8 | using Wlx2Explorer.Extensions; 9 | using Wlx2Explorer.Hooks; 10 | 11 | namespace Wlx2Explorer.Forms 12 | { 13 | partial class ProgramSettingsForm : Form 14 | { 15 | public ProgramSettings Settings { get; private set; } 16 | 17 | public ProgramSettingsForm(ProgramSettings settings) 18 | { 19 | InitializeComponent(); 20 | try 21 | { 22 | InitializeControls(settings); 23 | } 24 | catch 25 | { 26 | tabMain.Enabled = false; 27 | btnOk.Enabled = false; 28 | MessageBox.Show("Failed to read settings.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 29 | } 30 | } 31 | 32 | private void InitializeControls(ProgramSettings settings) 33 | { 34 | chbAutoStart.Checked = settings.AutoStartProgram; 35 | chbListerMaximized.Checked = settings.ListerFormMaximized; 36 | txtListerWidth.Text = settings.ListerFormWidth.ToString(); 37 | txtListerHeight.Text = settings.ListerFormHeight.ToString(); 38 | txtHighVersion.Text = settings.PluginHighVersion.ToString(); 39 | txtLowVersion.Text = settings.PluginLowVersion.ToString(); 40 | txtIniFile.Text = settings.PluginIniFile; 41 | if (settings.PluginIniFile.StartsWith(AssemblyUtils.AssemblyDirectory, StringComparison.InvariantCultureIgnoreCase)) 42 | { 43 | txtIniFile.Text = settings.PluginIniFile.Substring(AssemblyUtils.AssemblyDirectory.Length).TrimStart('\\'); 44 | } 45 | 46 | cmbListerFormKey1.DataSource = Enum.GetValues(typeof(VirtualKeyModifier)); 47 | cmbListerFormKey1.SelectedItem = (VirtualKeyModifier)settings.ListerFormKey1; 48 | cmbListerFormKey2.DataSource = Enum.GetValues(typeof(VirtualKeyModifier)); 49 | cmbListerFormKey2.SelectedItem = (VirtualKeyModifier)settings.ListerFormKey2; 50 | cmbListerFormKey3.ValueMember = "Id"; 51 | cmbListerFormKey3.DisplayMember = "Text"; 52 | cmbListerFormKey3.DataSource = ((VirtualKey[])Enum.GetValues(typeof(VirtualKey))).Where(x => !string.IsNullOrEmpty(x.GetDescription())).Select(x => new { Id = (int)x, Text = x.GetDescription() }).ToList(); 53 | cmbListerFormKey3.SelectedValue = settings.ListerFormKey3; 54 | cmbSearchDialogKey1.DataSource = Enum.GetValues(typeof(VirtualKeyModifier)); 55 | cmbSearchDialogKey1.SelectedItem = (VirtualKeyModifier)settings.SearchDialogKey1; 56 | cmbSearchDialogKey2.DataSource = Enum.GetValues(typeof(VirtualKeyModifier)); 57 | cmbSearchDialogKey2.SelectedItem = (VirtualKeyModifier)settings.SearchDialogKey2; 58 | cmbSearchDialogKey3.ValueMember = "Id"; 59 | cmbSearchDialogKey3.DisplayMember = "Text"; 60 | cmbSearchDialogKey3.DataSource = ((VirtualKey[])Enum.GetValues(typeof(VirtualKey))).Where(x => !string.IsNullOrEmpty(x.GetDescription())).Select(x => new { Id = (int)x, Text = x.GetDescription() }).ToList(); 61 | cmbSearchDialogKey3.SelectedValue = settings.SearchDialogKey3; 62 | cmbPrintDialogKey1.DataSource = Enum.GetValues(typeof(VirtualKeyModifier)); 63 | cmbPrintDialogKey1.SelectedItem = (VirtualKeyModifier)settings.PrintDialogKey1; 64 | cmbPrintDialogKey2.DataSource = Enum.GetValues(typeof(VirtualKeyModifier)); 65 | cmbPrintDialogKey2.SelectedItem = (VirtualKeyModifier)settings.PrintDialogKey2; 66 | cmbPrintDialogKey3.ValueMember = "Id"; 67 | cmbPrintDialogKey3.DisplayMember = "Text"; 68 | cmbPrintDialogKey3.DataSource = ((VirtualKey[])Enum.GetValues(typeof(VirtualKey))).Where(x => !string.IsNullOrEmpty(x.GetDescription())).Select(x => new { Id = (int)x, Text = x.GetDescription() }).ToList(); 69 | cmbPrintDialogKey3.SelectedValue = settings.PrintDialogKey3; 70 | 71 | foreach (var plugin in settings.Plugins) 72 | { 73 | var fileName = plugin.Path; 74 | if (fileName.StartsWith(AssemblyUtils.AssemblyDirectory, StringComparison.InvariantCultureIgnoreCase)) 75 | { 76 | fileName = fileName.Substring(AssemblyUtils.AssemblyDirectory.Length).TrimStart('\\'); 77 | } 78 | var index = gridViewPlugin.Rows.Add(); 79 | var row = gridViewPlugin.Rows[index]; 80 | row.Cells[0].Value = fileName; 81 | row.Cells[1].Value = string.Join(";", plugin.Extensions.ToArray()); 82 | } 83 | gridViewPlugin.Columns[0].Width = gridViewPlugin.ClientSize.Width - 100; 84 | gridViewPlugin.Columns[1].Width = 100; 85 | } 86 | 87 | private void MaximizeWindowCheckedChanged(object sender, EventArgs e) 88 | { 89 | var checkBox = (CheckBox)sender; 90 | lblWindowWidth.Enabled = !checkBox.Checked; 91 | lblWindowHeight.Enabled = !checkBox.Checked; 92 | txtListerWidth.Enabled = !checkBox.Checked; 93 | txtListerHeight.Enabled = !checkBox.Checked; 94 | if (!checkBox.Checked) 95 | { 96 | txtListerWidth.Focus(); 97 | } 98 | } 99 | 100 | private void BrowseWincmdIniClick(object sender, EventArgs e) 101 | { 102 | var dialog = new OpenFileDialog() 103 | { 104 | RestoreDirectory = true, 105 | FileName = "wincmd.ini", 106 | Filter = "Ini files (*.ini)|*.ini;|All files (*.*)|*.*" 107 | }; 108 | if (dialog.ShowDialog() == DialogResult.OK) 109 | { 110 | var file = new InitializationFile(dialog.FileName); 111 | try 112 | { 113 | file.LoadFile(); 114 | } 115 | catch 116 | { 117 | MessageBox.Show("Failed to read the file. May be wrong ini file format.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 118 | return; 119 | } 120 | var listerSection = file.GetSection("ListerPlugins"); 121 | if (listerSection == null) 122 | { 123 | MessageBox.Show("This file does not contain [ListerPlugins] section.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 124 | return; 125 | } 126 | if (gridViewPlugin.Rows.Count > 0 && 127 | MessageBox.Show("Do you want to clear the current list of the plugins.", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 128 | { 129 | gridViewPlugin.Rows.Clear(); 130 | } 131 | foreach (var pair in listerSection) 132 | { 133 | var fileName = pair.Value; 134 | if (File.Exists(fileName)) 135 | { 136 | var index = gridViewPlugin.Rows.Add(); 137 | var row = gridViewPlugin.Rows[index]; 138 | row.Cells[0].Value = fileName; 139 | row.Cells[1].Value = string.Join(";", Plugin.GetSupportedExtensions(fileName)); 140 | gridViewPlugin.FirstDisplayedScrollingRowIndex = gridViewPlugin.RowCount - 1; 141 | gridViewPlugin.Rows[index].Selected = true; 142 | } 143 | } 144 | } 145 | } 146 | 147 | private void AddPluginClick(object sender, EventArgs e) 148 | { 149 | var dialog = new OpenFileDialog() 150 | { 151 | RestoreDirectory = true, 152 | Filter = "Plugin files (*.wlx;*.wlx64)|*.wlx;*.wlx64|All files (*.*)|*.*" 153 | }; 154 | if (dialog.ShowDialog() == DialogResult.OK) 155 | { 156 | var fileName = dialog.FileName; 157 | if (fileName.StartsWith(AssemblyUtils.AssemblyDirectory, StringComparison.InvariantCultureIgnoreCase)) 158 | { 159 | fileName = fileName.Substring(AssemblyUtils.AssemblyDirectory.Length).TrimStart('\\'); 160 | } 161 | if (IsGridViewContainFile(fileName)) 162 | { 163 | MessageBox.Show("The file already exists in the list.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 164 | return; 165 | } 166 | var index = gridViewPlugin.Rows.Add(); 167 | var row = gridViewPlugin.Rows[index]; 168 | row.Cells[0].Value = fileName; 169 | row.Cells[1].Value = string.Join(";", Plugin.GetSupportedExtensions(fileName)); 170 | gridViewPlugin.FirstDisplayedScrollingRowIndex = gridViewPlugin.RowCount - 1; 171 | gridViewPlugin.Rows[index].Selected = true; 172 | } 173 | } 174 | 175 | private void DeletePluginClick(object sender, EventArgs e) 176 | { 177 | if (gridViewPlugin.SelectedRows.Count > 0) 178 | { 179 | var index = gridViewPlugin.SelectedRows[0].Index; 180 | gridViewPlugin.Rows.RemoveAt(index); 181 | index = (index < gridViewPlugin.Rows.Count) ? index : (gridViewPlugin.Rows.Count > 0) ? gridViewPlugin.Rows.Count - 1 : 0; 182 | if (gridViewPlugin.Rows.Count > 0) 183 | { 184 | gridViewPlugin.Rows[index].Selected = true; 185 | } 186 | } 187 | else 188 | { 189 | MessageBox.Show("You should select an item in the list.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information); 190 | } 191 | } 192 | 193 | private void EditPluginClick(object sender, EventArgs e) 194 | { 195 | if (gridViewPlugin.SelectedRows.Count > 0) 196 | { 197 | var row = gridViewPlugin.SelectedRows[0]; 198 | var pluginSettingsForm = new PluginSettingsForm((string)row.Cells[0].Value, (string)row.Cells[1].Value); 199 | if (pluginSettingsForm.ShowDialog() == DialogResult.OK) 200 | { 201 | var fileName = pluginSettingsForm.FileName; 202 | var extensions = pluginSettingsForm.Extensions; 203 | if (fileName.StartsWith(AssemblyUtils.AssemblyDirectory, StringComparison.InvariantCultureIgnoreCase)) 204 | { 205 | fileName = fileName.Substring(AssemblyUtils.AssemblyDirectory.Length).TrimStart('\\'); 206 | } 207 | row.Cells[0].Value = fileName; 208 | row.Cells[1].Value = extensions; 209 | } 210 | } 211 | else 212 | { 213 | MessageBox.Show("You should select an item in the list.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information); 214 | } 215 | } 216 | 217 | private void DownPluginClick(object sender, EventArgs e) 218 | { 219 | if (gridViewPlugin.SelectedRows.Count > 0) 220 | { 221 | var index = gridViewPlugin.SelectedRows[0].Index; 222 | var newIndex = index < gridViewPlugin.Rows.Count - 1 ? index + 1 : gridViewPlugin.Rows.Count - 1; 223 | var selectedRow = gridViewPlugin.SelectedRows[0]; 224 | gridViewPlugin.Rows.RemoveAt(index); 225 | gridViewPlugin.Rows.Insert(newIndex, selectedRow); 226 | gridViewPlugin.Rows[newIndex].Selected = true; 227 | } 228 | } 229 | 230 | private void UpPluginClick(object sender, EventArgs e) 231 | { 232 | if (gridViewPlugin.SelectedRows.Count > 0) 233 | { 234 | var index = gridViewPlugin.SelectedRows[0].Index; 235 | var newIndex = index > 0 ? index - 1 : 0; 236 | var selectedRow = gridViewPlugin.SelectedRows[0]; 237 | gridViewPlugin.Rows.RemoveAt(index); 238 | gridViewPlugin.Rows.Insert(newIndex, selectedRow); 239 | gridViewPlugin.Rows[newIndex].Selected = true; 240 | } 241 | } 242 | 243 | private void PluginListDoubleClick(object sender, DataGridViewCellMouseEventArgs e) 244 | { 245 | EditPluginClick(sender, (EventArgs)e); 246 | } 247 | 248 | private void OkClick(object sender, EventArgs e) 249 | { 250 | int listerWidth = 0; 251 | int listerHeight = 0; 252 | int highVersion = 0; 253 | int lowVersion = 0; 254 | string iniFile = ""; 255 | DialogResult = DialogResult.Cancel; 256 | 257 | try 258 | { 259 | listerWidth = int.Parse(txtListerWidth.Text); 260 | } 261 | catch 262 | { 263 | MessageBox.Show("Window width must be an integer number."); 264 | Close(); 265 | } 266 | 267 | try 268 | { 269 | listerHeight = int.Parse(txtListerHeight.Text); 270 | } 271 | catch 272 | { 273 | MessageBox.Show("Window height must be an integer number."); 274 | Close(); 275 | } 276 | 277 | try 278 | { 279 | highVersion = int.Parse(txtHighVersion.Text); 280 | } 281 | catch 282 | { 283 | MessageBox.Show("The integral part of version must be an integer number."); 284 | Close(); 285 | } 286 | 287 | try 288 | { 289 | lowVersion = int.Parse(txtLowVersion.Text); 290 | } 291 | catch 292 | { 293 | MessageBox.Show("The fractional part of version must be an integer number."); 294 | Close(); 295 | } 296 | 297 | try 298 | { 299 | var fileInfo = new FileInfo(txtIniFile.Text); 300 | if (!fileInfo.Exists) fileInfo.Create().Close(); 301 | iniFile = fileInfo.FullName; 302 | } 303 | catch 304 | { 305 | MessageBox.Show($"Failed to create the file \"{txtIniFile.Text}\""); 306 | Close(); 307 | } 308 | 309 | Settings = new ProgramSettings() 310 | { 311 | AutoStartProgram = chbAutoStart.Checked, 312 | ListerFormMaximized = chbListerMaximized.Checked, 313 | ListerFormWidth = listerWidth, 314 | ListerFormHeight = listerHeight, 315 | PluginLowVersion = lowVersion, 316 | PluginHighVersion = highVersion, 317 | PluginIniFile = txtIniFile.Text, 318 | ListerFormKey1 = (int)cmbListerFormKey1.SelectedValue, 319 | ListerFormKey2 = (int)cmbListerFormKey2.SelectedValue, 320 | ListerFormKey3 = (int)cmbListerFormKey3.SelectedValue, 321 | SearchDialogKey1 = (int)cmbSearchDialogKey1.SelectedValue, 322 | SearchDialogKey2 = (int)cmbSearchDialogKey2.SelectedValue, 323 | SearchDialogKey3 = (int)cmbSearchDialogKey3.SelectedValue, 324 | PrintDialogKey1 = (int)cmbPrintDialogKey1.SelectedValue, 325 | PrintDialogKey2 = (int)cmbPrintDialogKey2.SelectedValue, 326 | PrintDialogKey3 = (int)cmbPrintDialogKey3.SelectedValue 327 | }; 328 | 329 | foreach (DataGridViewRow row in gridViewPlugin.Rows) 330 | { 331 | var fileName = (string)row.Cells[0].Value; 332 | var extensions = ((string)row.Cells[1].Value).Split(';').ToList(); 333 | var pluginInfo = new PluginInfo(fileName, extensions); 334 | Settings.Plugins.Add(pluginInfo); 335 | } 336 | 337 | DialogResult = DialogResult.OK; 338 | Close(); 339 | } 340 | 341 | private void CancelClick(object sender, EventArgs e) 342 | { 343 | DialogResult = DialogResult.Cancel; 344 | Close(); 345 | } 346 | 347 | private void FormKeyDown(object sender, KeyEventArgs e) 348 | { 349 | if (e.KeyValue == 27) 350 | { 351 | CancelClick(sender, (EventArgs)e); 352 | } 353 | } 354 | 355 | private bool IsGridViewContainFile(string fileName) 356 | { 357 | foreach (DataGridViewRow row in gridViewPlugin.Rows) 358 | { 359 | if (string.Compare((string)row.Cells[0].Value, fileName, true) == 0) return true; 360 | } 361 | return false; 362 | } 363 | } 364 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/ProgramSettingsForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | True 122 | 123 | 124 | True 125 | 126 | 127 | 17, 17 128 | 129 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/SearchForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Forms 2 | { 3 | partial class SearchForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btnOk = new System.Windows.Forms.Button(); 32 | this.btnCancel = new System.Windows.Forms.Button(); 33 | this.txtSearchText = new System.Windows.Forms.TextBox(); 34 | this.lblSearchText = new System.Windows.Forms.Label(); 35 | this.chbWholeWordsOnly = new System.Windows.Forms.CheckBox(); 36 | this.chbCaseSensitive = new System.Windows.Forms.CheckBox(); 37 | this.chbSearchBackwards = new System.Windows.Forms.CheckBox(); 38 | this.chbSearchFromBeginning = new System.Windows.Forms.CheckBox(); 39 | this.SuspendLayout(); 40 | // 41 | // btnOk 42 | // 43 | this.btnOk.Location = new System.Drawing.Point(208, 120); 44 | this.btnOk.Name = "btnOk"; 45 | this.btnOk.Size = new System.Drawing.Size(75, 23); 46 | this.btnOk.TabIndex = 6; 47 | this.btnOk.Text = "Ok"; 48 | this.btnOk.UseVisualStyleBackColor = true; 49 | this.btnOk.Click += new System.EventHandler(this.OkClick); 50 | // 51 | // btnCancel 52 | // 53 | this.btnCancel.Location = new System.Drawing.Point(289, 120); 54 | this.btnCancel.Name = "btnCancel"; 55 | this.btnCancel.Size = new System.Drawing.Size(75, 23); 56 | this.btnCancel.TabIndex = 7; 57 | this.btnCancel.Text = "Cancel"; 58 | this.btnCancel.UseVisualStyleBackColor = true; 59 | this.btnCancel.Click += new System.EventHandler(this.CancelClick); 60 | // 61 | // txtSearchText 62 | // 63 | this.txtSearchText.Location = new System.Drawing.Point(12, 31); 64 | this.txtSearchText.Name = "txtSearchText"; 65 | this.txtSearchText.Size = new System.Drawing.Size(354, 20); 66 | this.txtSearchText.TabIndex = 1; 67 | // 68 | // lblSearchText 69 | // 70 | this.lblSearchText.AutoSize = true; 71 | this.lblSearchText.Location = new System.Drawing.Point(9, 15); 72 | this.lblSearchText.Name = "lblSearchText"; 73 | this.lblSearchText.Size = new System.Drawing.Size(56, 13); 74 | this.lblSearchText.TabIndex = 0; 75 | this.lblSearchText.Text = "Find what:"; 76 | // 77 | // chbWholeWordsOnly 78 | // 79 | this.chbWholeWordsOnly.AutoSize = true; 80 | this.chbWholeWordsOnly.Location = new System.Drawing.Point(12, 67); 81 | this.chbWholeWordsOnly.Name = "chbWholeWordsOnly"; 82 | this.chbWholeWordsOnly.Size = new System.Drawing.Size(110, 17); 83 | this.chbWholeWordsOnly.TabIndex = 2; 84 | this.chbWholeWordsOnly.Text = "Whole words only"; 85 | this.chbWholeWordsOnly.UseVisualStyleBackColor = true; 86 | // 87 | // chbCaseSensitive 88 | // 89 | this.chbCaseSensitive.AutoSize = true; 90 | this.chbCaseSensitive.Location = new System.Drawing.Point(12, 90); 91 | this.chbCaseSensitive.Name = "chbCaseSensitive"; 92 | this.chbCaseSensitive.Size = new System.Drawing.Size(94, 17); 93 | this.chbCaseSensitive.TabIndex = 3; 94 | this.chbCaseSensitive.Text = "Case sensitive"; 95 | this.chbCaseSensitive.UseVisualStyleBackColor = true; 96 | // 97 | // chbSearchBackwards 98 | // 99 | this.chbSearchBackwards.AutoSize = true; 100 | this.chbSearchBackwards.Location = new System.Drawing.Point(150, 90); 101 | this.chbSearchBackwards.Name = "chbSearchBackwards"; 102 | this.chbSearchBackwards.Size = new System.Drawing.Size(115, 17); 103 | this.chbSearchBackwards.TabIndex = 5; 104 | this.chbSearchBackwards.Text = "Search backwards"; 105 | this.chbSearchBackwards.UseVisualStyleBackColor = true; 106 | // 107 | // chbSearchFromBeginning 108 | // 109 | this.chbSearchFromBeginning.AutoSize = true; 110 | this.chbSearchFromBeginning.Location = new System.Drawing.Point(150, 67); 111 | this.chbSearchFromBeginning.Name = "chbSearchFromBeginning"; 112 | this.chbSearchFromBeginning.Size = new System.Drawing.Size(150, 17); 113 | this.chbSearchFromBeginning.TabIndex = 4; 114 | this.chbSearchFromBeginning.Text = "Search from the beginning"; 115 | this.chbSearchFromBeginning.UseVisualStyleBackColor = true; 116 | // 117 | // SearchForm 118 | // 119 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 120 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 121 | this.ClientSize = new System.Drawing.Size(376, 155); 122 | this.Controls.Add(this.chbSearchFromBeginning); 123 | this.Controls.Add(this.chbSearchBackwards); 124 | this.Controls.Add(this.chbCaseSensitive); 125 | this.Controls.Add(this.chbWholeWordsOnly); 126 | this.Controls.Add(this.lblSearchText); 127 | this.Controls.Add(this.txtSearchText); 128 | this.Controls.Add(this.btnCancel); 129 | this.Controls.Add(this.btnOk); 130 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 131 | this.KeyPreview = true; 132 | this.MaximizeBox = false; 133 | this.MinimizeBox = false; 134 | this.Name = "SearchForm"; 135 | this.ShowInTaskbar = false; 136 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 137 | this.Text = "Search text"; 138 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormKeyDown); 139 | this.ResumeLayout(false); 140 | this.PerformLayout(); 141 | 142 | } 143 | 144 | #endregion 145 | 146 | private System.Windows.Forms.Button btnOk; 147 | private System.Windows.Forms.Button btnCancel; 148 | private System.Windows.Forms.TextBox txtSearchText; 149 | private System.Windows.Forms.Label lblSearchText; 150 | private System.Windows.Forms.CheckBox chbWholeWordsOnly; 151 | private System.Windows.Forms.CheckBox chbCaseSensitive; 152 | private System.Windows.Forms.CheckBox chbSearchBackwards; 153 | private System.Windows.Forms.CheckBox chbSearchFromBeginning; 154 | } 155 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/SearchForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace Wlx2Explorer.Forms 5 | { 6 | partial class SearchForm : Form 7 | { 8 | public static string SearchingText { get; set; } 9 | 10 | public static bool SearchWholeWordsOnly { get; set; } 11 | 12 | public static bool SearchCaseSensitive { get; set; } 13 | 14 | public static bool SearchFromBeginning { get; set; } 15 | 16 | public static bool SearchBackwards { get; set; } 17 | 18 | static SearchForm() 19 | { 20 | SearchingText = ""; 21 | SearchWholeWordsOnly = false; 22 | SearchCaseSensitive = false; 23 | SearchFromBeginning = false; 24 | SearchBackwards = false; 25 | } 26 | 27 | public SearchForm() 28 | { 29 | InitializeComponent(); 30 | 31 | txtSearchText.Text = SearchingText; 32 | chbWholeWordsOnly.Checked = SearchWholeWordsOnly; 33 | chbCaseSensitive.Checked = SearchCaseSensitive; 34 | chbSearchFromBeginning.Checked = SearchFromBeginning; 35 | chbSearchBackwards.Checked = SearchBackwards; 36 | } 37 | 38 | private void OkClick(object sender, EventArgs e) 39 | { 40 | SearchingText = txtSearchText.Text; 41 | SearchWholeWordsOnly = chbWholeWordsOnly.Checked; 42 | SearchCaseSensitive = chbCaseSensitive.Checked; 43 | SearchFromBeginning = chbSearchFromBeginning.Checked; 44 | SearchBackwards = chbSearchBackwards.Checked; 45 | 46 | DialogResult = DialogResult.OK; 47 | Close(); 48 | } 49 | 50 | private void CancelClick(object sender, EventArgs e) 51 | { 52 | DialogResult = DialogResult.Cancel; 53 | Close(); 54 | } 55 | 56 | private void FormKeyDown(object sender, KeyEventArgs e) 57 | { 58 | switch (e.KeyValue) 59 | { 60 | case 13: 61 | { 62 | OkClick(sender, (EventArgs)e); 63 | } break; 64 | 65 | case 27: 66 | { 67 | CancelClick(sender, (EventArgs)e); 68 | } break; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Wlx2Explorer/Forms/SearchForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Wlx2Explorer/Hooks/KeyboardHook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Wlx2Explorer.Native; 4 | 5 | namespace Wlx2Explorer.Hooks 6 | { 7 | class KeyboardHook 8 | { 9 | private IntPtr _hookHandle; 10 | private KeyboardHookProc _hookProc; 11 | private int _key1; 12 | private int _key2; 13 | private int _key3; 14 | 15 | public event EventHandler Hooked; 16 | 17 | public bool Start(int key1, int key2, int key3) 18 | { 19 | _key1 = key1; 20 | _key2 = key2; 21 | _key3 = key3; 22 | _hookProc = HookProc; 23 | using var currentProcess = Process.GetCurrentProcess(); 24 | using var currentModule = currentProcess.MainModule; 25 | var moduleHandle = NativeMethods.GetModuleHandle(currentModule.ModuleName); 26 | _hookHandle = NativeMethods.SetWindowsHookEx(NativeConstants.WH_KEYBOARD_LL, _hookProc, moduleHandle, 0); 27 | var hookStarted = _hookHandle != IntPtr.Zero; 28 | return hookStarted; 29 | } 30 | 31 | public bool Stop() 32 | { 33 | if (_hookHandle == IntPtr.Zero) 34 | { 35 | return true; 36 | } 37 | var hookStoped = NativeMethods.UnhookWindowsHookEx(_hookHandle); 38 | return hookStoped; 39 | } 40 | 41 | private int HookProc(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) 42 | { 43 | if (code == NativeConstants.HC_ACTION) 44 | { 45 | if (wParam.ToInt32() == NativeConstants.WM_KEYDOWN || wParam.ToInt32() == NativeConstants.WM_SYSKEYDOWN) 46 | { 47 | var key1 = true; 48 | var key2 = true; 49 | 50 | if (_key1 != (int)VirtualKeyModifier.None) 51 | { 52 | var key1State = NativeMethods.GetAsyncKeyState(_key1) & 0x8000; 53 | key1 = Convert.ToBoolean(key1State); 54 | } 55 | 56 | if (_key2 != (int)VirtualKeyModifier.None) 57 | { 58 | var key2State = NativeMethods.GetAsyncKeyState(_key2) & 0x8000; 59 | key2 = Convert.ToBoolean(key2State); 60 | } 61 | 62 | if (key1 && key2 && lParam.vkCode == _key3) 63 | { 64 | var handler = Hooked; 65 | handler?.BeginInvoke(this, EventArgs.Empty, null, null); 66 | } 67 | } 68 | } 69 | return NativeMethods.CallNextHookEx(_hookHandle, code, wParam, ref lParam); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Wlx2Explorer/Hooks/VirtualKey.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Wlx2Explorer.Hooks 4 | { 5 | enum VirtualKey : int 6 | { 7 | VK_LBUTTON = 0x01, 8 | VK_RBUTTON = 0x02, 9 | VK_CANCEL = 0x03, 10 | VK_MBUTTON = 0x04, 11 | 12 | [Description("BACKSPACE")] 13 | VK_BACK = 0x08, 14 | 15 | [Description("TAB")] 16 | VK_TAB = 0x09, 17 | 18 | VK_CLEAR = 0x0C, 19 | VK_RETURN = 0x0D, 20 | VK_SHIFT = 0x10, 21 | VK_CONTROL = 0x11, 22 | VK_MENU = 0x12, 23 | 24 | [Description("PAUSE")] 25 | VK_PAUSE = 0x13, 26 | 27 | [Description("CAPS LOCK")] 28 | VK_CAPITAL = 0x14, 29 | 30 | [Description("ESC")] 31 | VK_ESCAPE = 0x1B, 32 | 33 | [Description("SPACE")] 34 | VK_SPACE = 0x20, 35 | 36 | [Description("PAGE UP")] 37 | VK_PRIOR = 0x21, 38 | 39 | [Description("PAGE DOWN")] 40 | VK_NEXT = 0x22, 41 | 42 | [Description("END")] 43 | VK_END = 0x23, 44 | 45 | [Description("HOME")] 46 | VK_HOME = 0x24, 47 | 48 | [Description("LEFT ARROW")] 49 | VK_LEFT = 0x25, 50 | 51 | [Description("UP ARROW")] 52 | VK_UP = 0x26, 53 | 54 | [Description("RIGHT ARROW")] 55 | VK_RIGHT = 0x27, 56 | 57 | [Description("DOWN ARROW")] 58 | VK_DOWN = 0x28, 59 | 60 | VK_SELECT = 0x29, 61 | VK_EXECUTE = 0x2B, 62 | 63 | [Description("PRINT SCREEN")] 64 | VK_SNAPSHOT = 0x2C, 65 | 66 | [Description("INS")] 67 | VK_INSERT = 0x2D, 68 | 69 | [Description("DEL")] 70 | VK_DELETE = 0x2E, 71 | 72 | [Description("HELP")] 73 | VK_HELP = 0x2F, 74 | 75 | [Description("0")] 76 | VK_0 = 0x30, 77 | 78 | [Description("1")] 79 | VK_1 = 0x31, 80 | 81 | [Description("2")] 82 | VK_2 = 0x32, 83 | 84 | [Description("3")] 85 | VK_3 = 0x33, 86 | 87 | [Description("4")] 88 | VK_4 = 0x34, 89 | 90 | [Description("5")] 91 | VK_5 = 0x35, 92 | 93 | [Description("6")] 94 | VK_6 = 0x36, 95 | 96 | [Description("7")] 97 | VK_7 = 0x37, 98 | 99 | [Description("8")] 100 | VK_8 = 0x38, 101 | 102 | [Description("9")] 103 | VK_9 = 0x39, 104 | 105 | [Description("A")] 106 | VK_A = 0x41, 107 | 108 | [Description("B")] 109 | VK_B = 0x42, 110 | 111 | [Description("C")] 112 | VK_C = 0x43, 113 | 114 | [Description("D")] 115 | VK_D = 0x44, 116 | 117 | [Description("E")] 118 | VK_E = 0x45, 119 | 120 | [Description("F")] 121 | VK_F = 0x46, 122 | 123 | [Description("G")] 124 | VK_G = 0x47, 125 | 126 | [Description("H")] 127 | VK_H = 0x48, 128 | 129 | [Description("I")] 130 | VK_I = 0x49, 131 | 132 | [Description("J")] 133 | VK_J = 0x4A, 134 | 135 | [Description("K")] 136 | VK_K = 0x4B, 137 | 138 | [Description("L")] 139 | VK_L = 0x4C, 140 | 141 | [Description("M")] 142 | VK_M = 0x4D, 143 | 144 | [Description("N")] 145 | VK_N = 0x4E, 146 | 147 | [Description("O")] 148 | VK_O = 0x4F, 149 | 150 | [Description("P")] 151 | VK_P = 0x50, 152 | 153 | [Description("Q")] 154 | VK_Q = 0x51, 155 | 156 | [Description("R")] 157 | VK_R = 0x52, 158 | 159 | [Description("S")] 160 | VK_S = 0x53, 161 | 162 | [Description("T")] 163 | VK_T = 0x54, 164 | 165 | [Description("U")] 166 | VK_U = 0x55, 167 | 168 | [Description("V")] 169 | VK_V = 0x56, 170 | 171 | [Description("W")] 172 | VK_W = 0x57, 173 | 174 | [Description("X")] 175 | VK_X = 0x58, 176 | 177 | [Description("Y")] 178 | VK_Y = 0x59, 179 | 180 | [Description("Z")] 181 | VK_Z = 0x5A, 182 | VK_LWIN = 0x5B, 183 | VK_RWIN = 0x5C, 184 | VK_APPS = 0x5D, 185 | 186 | [Description("NUMPAD 0")] 187 | VK_NUMPAD0 = 0x60, 188 | 189 | [Description("NUMPAD 1")] 190 | VK_NUMPAD1 = 0x61, 191 | 192 | [Description("NUMPAD 2")] 193 | VK_NUMPAD2 = 0x62, 194 | 195 | [Description("NUMPAD 3")] 196 | VK_NUMPAD3 = 0x63, 197 | 198 | [Description("NUMPAD 4")] 199 | VK_NUMPAD4 = 0x64, 200 | 201 | [Description("NUMPAD 5")] 202 | VK_NUMPAD5 = 0x65, 203 | 204 | [Description("NUMPAD 6")] 205 | VK_NUMPAD6 = 0x66, 206 | 207 | [Description("NUMPAD 7")] 208 | VK_NUMPAD7 = 0x67, 209 | 210 | [Description("NUMPAD 8")] 211 | VK_NUMPAD8 = 0x68, 212 | 213 | [Description("NUMPAD 9")] 214 | VK_NUMPAD9 = 0x69, 215 | 216 | [Description("MULTIPLY")] 217 | VK_MULTIPLY = 0x6A, 218 | 219 | [Description("ADD")] 220 | VK_ADD = 0x6B, 221 | 222 | [Description("SEPARATOR")] 223 | VK_SEPARATOR = 0x6C, 224 | 225 | [Description("SUBTRACT")] 226 | VK_SUBTRACT = 0x6D, 227 | 228 | [Description("DECIMAL")] 229 | VK_DECIMAL = 0x6E, 230 | 231 | [Description("DIVIDE")] 232 | VK_DIVIDE = 0x6F, 233 | 234 | [Description("F1")] 235 | VK_F1 = 0x70, 236 | 237 | [Description("F2")] 238 | VK_F2 = 0x71, 239 | 240 | [Description("F3")] 241 | VK_F3 = 0x72, 242 | 243 | [Description("F4")] 244 | VK_F4 = 0x73, 245 | 246 | [Description("F5")] 247 | VK_F5 = 0x74, 248 | 249 | [Description("F6")] 250 | VK_F6 = 0x75, 251 | 252 | [Description("F7")] 253 | VK_F7 = 0x76, 254 | 255 | [Description("F8")] 256 | VK_F8 = 0x77, 257 | 258 | [Description("F9")] 259 | VK_F9 = 0x78, 260 | 261 | [Description("F10")] 262 | VK_F10 = 0x79, 263 | 264 | [Description("F11")] 265 | VK_F11 = 0x7A, 266 | 267 | [Description("F12")] 268 | VK_F12 = 0x7B, 269 | 270 | [Description("F13")] 271 | VK_F13 = 0x7C, 272 | 273 | [Description("F14")] 274 | VK_F14 = 0x7D, 275 | 276 | [Description("F15")] 277 | VK_F15 = 0x7E, 278 | 279 | [Description("F16")] 280 | VK_F16 = 0x7F, 281 | 282 | [Description("F17")] 283 | VK_F17 = 0x80, 284 | 285 | [Description("F18")] 286 | VK_F18 = 0x81, 287 | 288 | [Description("F19")] 289 | VK_F19 = 0x82, 290 | 291 | [Description("F20")] 292 | VK_F20 = 0x83, 293 | 294 | [Description("F21")] 295 | VK_F21 = 0x84, 296 | 297 | [Description("F22")] 298 | VK_F22 = 0x85, 299 | 300 | [Description("F23")] 301 | VK_F23 = 0x86, 302 | 303 | [Description("F24")] 304 | VK_F24 = 0x87, 305 | 306 | [Description("NUM LOCK")] 307 | VK_NUMLOCK = 0x90, 308 | 309 | [Description("SCROLL LOCK")] 310 | VK_SCROLL = 0x91, 311 | VK_LSHIFT = 0xA0, 312 | VK_RSHIFT = 0xA1, 313 | VK_LCONTROL = 0xA2, 314 | VK_RCONTROL = 0xA3, 315 | VK_LMENU = 0xA4, 316 | VK_RMENU = 0xA5, 317 | VK_PACKET = 0xE7, 318 | VK_ATTN = 0xF6, 319 | VK_CRSEL = 0xF7, 320 | VK_EXSEL = 0xF8, 321 | VK_EREOF = 0xF9, 322 | VK_PLAY = 0xFA, 323 | VK_ZOOM = 0xFB, 324 | VK_NONAME = 0xFC, 325 | VK_PA1 = 0xFD, 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /Wlx2Explorer/Hooks/VirtualKeyModifier.cs: -------------------------------------------------------------------------------- 1 | namespace Wlx2Explorer.Hooks 2 | { 3 | enum VirtualKeyModifier : int 4 | { 5 | None = 0x00, 6 | Alt = 0x12, 7 | Shift = 0x10, 8 | Ctrl = 0x11 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Wlx2Explorer/Images/Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Images/Down.png -------------------------------------------------------------------------------- /Wlx2Explorer/Images/Start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Images/Start.png -------------------------------------------------------------------------------- /Wlx2Explorer/Images/Stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Images/Stop.png -------------------------------------------------------------------------------- /Wlx2Explorer/Images/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Images/Up.png -------------------------------------------------------------------------------- /Wlx2Explorer/Images/Wlx2Explorer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Images/Wlx2Explorer.ico -------------------------------------------------------------------------------- /Wlx2Explorer/Images/Wlx2Explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Images/Wlx2Explorer.png -------------------------------------------------------------------------------- /Wlx2Explorer/InitializationFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.IO; 5 | 6 | namespace Wlx2Explorer 7 | { 8 | class InitializationFile 9 | { 10 | private string _fileName = null; 11 | private Encoding _fileEncoding = null; 12 | private IDictionary> _content = null; 13 | 14 | public InitializationFile(string file) : this(file, Encoding.Default) 15 | { 16 | } 17 | 18 | public InitializationFile(string file, Encoding encoding) 19 | { 20 | _fileName = file; 21 | _fileEncoding = encoding; 22 | } 23 | 24 | public IDictionary GetSection(string sectionName) => _content.ContainsKey(sectionName) ? _content[sectionName] : null; 25 | 26 | public string GetValue(string sectionName, string keyName) => _content.ContainsKey(sectionName) && _content[sectionName].ContainsKey(keyName) ? _content[sectionName][keyName] : null; 27 | 28 | public void SetSection(string sectionName, IDictionary items) 29 | { 30 | _content[sectionName] = items; 31 | } 32 | 33 | public void SetValue(string sectionName, string keyName, string value) 34 | { 35 | if (!_content.ContainsKey(sectionName)) 36 | { 37 | _content[sectionName] = new Dictionary(); 38 | } 39 | _content[sectionName][keyName] = value; 40 | } 41 | 42 | public void LoadFile() => LoadFile(_fileName, _fileEncoding); 43 | 44 | public void LoadFile(string fileName) => LoadFile(fileName, _fileEncoding); 45 | 46 | public void LoadFile(string fileName, Encoding fileEncoding) 47 | { 48 | _content = Load(fileName, fileEncoding); 49 | } 50 | 51 | public void SaveFile() => SaveFile(_fileName, _fileEncoding); 52 | 53 | public void SaveFile(string fileName) => SaveFile(fileName, _fileEncoding); 54 | 55 | public void SaveFile(string fileName, Encoding fileEncoding) 56 | { 57 | using var file = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read); 58 | using var writer = new StreamWriter(file, fileEncoding); 59 | writer.Write(ToString()); 60 | } 61 | 62 | public override string ToString() 63 | { 64 | var content = new StringBuilder(); 65 | foreach (var pair in _content) 66 | { 67 | content.AppendFormat("[{0}]{1}", pair.Key, Environment.NewLine); 68 | foreach (var pairInner in pair.Value) 69 | { 70 | content.AppendFormat("{0}={1}{2}", pairInner.Key, pairInner.Value, Environment.NewLine); 71 | } 72 | content.AppendLine(); 73 | } 74 | return content.ToString(); 75 | } 76 | 77 | private Dictionary> Load(string fileName, Encoding fileEncoding) 78 | { 79 | var content = new Dictionary>(); 80 | using var file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 81 | using var reader = new StreamReader(file, _fileEncoding); 82 | string line = null; 83 | string section = null; 84 | while ((line = reader.ReadLine()) != null) 85 | { 86 | if (line.Length == 0) continue; 87 | if (line.StartsWith(";")) continue; 88 | if (line.Length > 2 && line[0] == '[' && line[line.Length - 1] == ']') 89 | { 90 | section = line.Substring(1, line.Length - 2); 91 | if (content.ContainsKey(section)) continue; 92 | content[section] = new Dictionary(); 93 | } 94 | else 95 | { 96 | if (section == null) continue; 97 | var pair = line.Split('='); 98 | if (pair.Length < 2) continue; 99 | var keyValue = new KeyValuePair(pair[0], pair[1]); 100 | if (content[section].Contains(keyValue)) continue; 101 | content[section].Add(keyValue); 102 | } 103 | } 104 | return content; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Wlx2Explorer/Libs/UnRAR.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Libs/UnRAR.dll -------------------------------------------------------------------------------- /Wlx2Explorer/Libs/UnRAR64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Libs/UnRAR64.dll -------------------------------------------------------------------------------- /Wlx2Explorer/Native/Interfaces/IServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Wlx2Explorer.Native.Interfaces 5 | { 6 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("6D5140C1-7436-11CE-8034-00AA006009FA")] 7 | interface IServiceProvider 8 | { 9 | void QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObject); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Wlx2Explorer/Native/Interfaces/IShellBrowser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Wlx2Explorer.Native.Interfaces 5 | { 6 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214E2-0000-0000-C000-000000000046")] 7 | interface IShellBrowser 8 | { 9 | void GetWindow(out IntPtr phwnd); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Wlx2Explorer/Native/NativeConstants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Wlx2Explorer.Native 4 | { 5 | static class NativeConstants 6 | { 7 | public const int WM_COMMAND = 0x0111; 8 | public const int WM_NOTIFY = 0x004E; 9 | public const int WM_MEASUREITEM = 0x002C; 10 | public const int WM_DRAWITEM = 0x002B; 11 | public const int WM_KEYDOWN = 0x0100; 12 | public const int WM_SYSKEYDOWN = 0x0104; 13 | public const int WH_KEYBOARD_LL = 0x0D; 14 | 15 | public const uint HC_ACTION = 0; 16 | 17 | public const int LCS_FINDFIRST = 0x01; 18 | public const int LCS_MATCHCASE = 0x02; 19 | public const int LCS_WHOLEWORDS = 0x04; 20 | public const int LCS_BACKWARDS = 0x08; 21 | 22 | public const uint LVM_FIRST = 0x1000; 23 | public const uint LVM_GETITEMCOUNT = LVM_FIRST + 4; 24 | public const uint LVM_GETITEMW = LVM_FIRST + 75; 25 | public const uint LVM_GETITEMPOSITION = LVM_FIRST + 16; 26 | public const uint LVM_GETITEMSTATE = LVM_FIRST + 44; 27 | 28 | public const uint PROCESS_VM_OPERATION = 0x0008; 29 | public const uint PROCESS_VM_READ = 0x0010; 30 | public const uint PROCESS_VM_WRITE = 0x0020; 31 | 32 | public const uint MEM_COMMIT = 0x1000; 33 | public const uint MEM_RELEASE = 0x8000; 34 | public const uint MEM_RESERVE = 0x2000; 35 | 36 | public const uint PAGE_READWRITE = 4; 37 | public const int LVIF_TEXT = 0x0001; 38 | public const uint LVIS_SELECTED = 0x2; 39 | 40 | public static readonly Guid SID_STopLevelBrowser = new Guid(0x4C96BE40, 0x915C, 0x11CF, 0x99, 0xD3, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37); 41 | } 42 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Native/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Wlx2Explorer.Native 6 | { 7 | class NativeMethods 8 | { 9 | public delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam); 10 | 11 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 12 | public static extern IntPtr LoadLibrary(string fileName); 13 | 14 | [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 15 | public static extern bool FreeLibrary(IntPtr hModule); 16 | 17 | [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] 18 | public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 19 | 20 | [DllImport("user32.dll")] 21 | public static extern IntPtr GetForegroundWindow(); 22 | 23 | [DllImport("user32.dll")] 24 | [return: MarshalAs(UnmanagedType.Bool)] 25 | public static extern bool DestroyWindow(IntPtr hwnd); 26 | 27 | [DllImport("user32.dll")] 28 | [return: MarshalAs(UnmanagedType.Bool)] 29 | public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int cx, int cy, uint flags); 30 | 31 | [DllImport("user32.dll", SetLastError = true)] 32 | public static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, uint threadId); 33 | 34 | [DllImport("user32.dll")] 35 | public static extern bool UnhookWindowsHookEx(IntPtr handleHook); 36 | 37 | [DllImport("user32.dll")] 38 | public static extern int CallNextHookEx(IntPtr handleHook, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); 39 | 40 | [DllImport("user32.dll")] 41 | public static extern int GetAsyncKeyState(int key); 42 | 43 | [DllImport("user32.dll")] 44 | public static extern IntPtr GetThreadDesktop(int threadId); 45 | 46 | [DllImport("user32.dll")] 47 | public static extern IntPtr SetFocus(IntPtr hwnd); 48 | 49 | [DllImport("user32.dll")] 50 | public static extern IntPtr GetParent(IntPtr hwnd); 51 | 52 | [DllImport("kernel32.dll")] 53 | public static extern IntPtr GetModuleHandle(string name); 54 | 55 | [DllImport("kernel32.dll")] 56 | public static extern uint GetCurrentThreadId(); 57 | 58 | [DllImport("user32")] 59 | public static extern int GetClassName(IntPtr hwnd, StringBuilder name, int count); 60 | 61 | [DllImport("kernel32.dll")] 62 | public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); 63 | 64 | [DllImport("kernel32.dll")] 65 | public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType); 66 | 67 | [DllImport("kernel32.dll")] 68 | public static extern bool CloseHandle(IntPtr handle); 69 | 70 | [DllImport("kernel32.dll")] 71 | public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, ref uint vNumberOfBytesRead); 72 | 73 | [DllImport("kernel32.dll")] 74 | public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, ref uint vNumberOfBytesRead); 75 | 76 | [DllImport("kernel32.dll")] 77 | public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId); 78 | 79 | [DllImport("user32.DLL")] 80 | public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); 81 | 82 | [DllImport("user32.DLL")] 83 | public static extern IntPtr FindWindow(string lpszClass, string lpszWindow); 84 | 85 | [DllImport("user32.DLL")] 86 | public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); 87 | 88 | [DllImport("user32.dll")] 89 | public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint dwProcessId); 90 | 91 | [DllImport("user32.dll")] 92 | [return: MarshalAs(UnmanagedType.Bool)] 93 | public static extern bool EnumWindows(EnumWindowProc lpEnumFunc, IntPtr lParam); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Wlx2Explorer/Native/NativeTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Wlx2Explorer.Native 5 | { 6 | [StructLayout(LayoutKind.Sequential)] 7 | struct KBDLLHOOKSTRUCT 8 | { 9 | public int vkCode; 10 | public int scanCode; 11 | public int flags; 12 | public int time; 13 | public IntPtr dwExtraInfo; 14 | } 15 | 16 | [StructLayout(LayoutKind.Sequential)] 17 | class ListDefaultParamStruct 18 | { 19 | public int size; 20 | public int interfaceVersionLow; 21 | public int interfaceVersionHigh; 22 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 23 | public string defaultIniFile; 24 | } 25 | 26 | [StructLayout(LayoutKind.Sequential)] 27 | class Rect 28 | { 29 | public int Left; 30 | public int Top; 31 | public int Right; 32 | public int Bottom; 33 | public int Width { get { return Right - Left; } } 34 | public int Height { get { return Bottom - Top; } } 35 | } 36 | 37 | struct LVITEM 38 | { 39 | public int mask; 40 | public int iItem; 41 | public int iSubItem; 42 | public int state; 43 | public int stateMask; 44 | public IntPtr pszText; // string 45 | public int cchTextMax; 46 | public int iImage; 47 | public IntPtr lParam; 48 | public int iIndent; 49 | public int iGroupId; 50 | public int cColumns; 51 | public IntPtr puColumns; 52 | } 53 | 54 | delegate int KeyboardHookProc(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam); 55 | } 56 | -------------------------------------------------------------------------------- /Wlx2Explorer/Plugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using System.Runtime.InteropServices; 6 | using System.Runtime.ExceptionServices; 7 | using Wlx2Explorer.Native; 8 | 9 | namespace Wlx2Explorer 10 | { 11 | class Plugin 12 | { 13 | private IntPtr _moduleHandle; 14 | private delegate IntPtr ListLoadDelegate(IntPtr hwndParent, string fileName, int flags); 15 | private delegate void ListCloseWindowDelegate(IntPtr hwndList); 16 | private delegate void ListGetDetectStringDelegate(StringBuilder detectString, int size); 17 | private delegate void ListNotificationReceivedDelegate(IntPtr hwndList, int message, IntPtr wParam, IntPtr lParam); 18 | private delegate void ListSetDefaultParamsDelegate(ListDefaultParamStruct defaultParams); 19 | private delegate int ListSearchTextDelegate(IntPtr hwndList, string searchString, int flags); 20 | private delegate int ListSearchDialogDelegate(IntPtr hwndList, int flags); 21 | private delegate int ListPrintDelegate(IntPtr hwndList, string fileName, string printerName, int flags, ref Rect margins); 22 | 23 | private delegate IntPtr ListLoadWDelegate(IntPtr hwndParent, [MarshalAs(UnmanagedType.LPTStr)] string fileName, int flags); 24 | private delegate int ListSearchTextWDelegate(IntPtr hwndList, [MarshalAs(UnmanagedType.LPTStr)] string searchString, int flags); 25 | private delegate int ListPrintWDelegate(IntPtr hwndList, [MarshalAs(UnmanagedType.LPTStr)] string fileName, [MarshalAs(UnmanagedType.LPTStr)] string printerName, int flags, ref Rect margins); 26 | 27 | 28 | public string ModuleName 29 | { 30 | get; 31 | private set; 32 | } 33 | 34 | public bool ListCloseWindowExist 35 | { 36 | get 37 | { 38 | var listCloseWindow = (ListCloseWindowDelegate)LoadFunction("ListCloseWindow"); 39 | var exist = listCloseWindow != null; 40 | return exist; 41 | } 42 | } 43 | 44 | public bool ListGetDetectStringExist 45 | { 46 | get 47 | { 48 | var listGetDetectString = (ListGetDetectStringDelegate)LoadFunction("ListGetDetectString"); 49 | var exist = listGetDetectString != null; 50 | return exist; 51 | } 52 | } 53 | 54 | public bool ListSetDefaultParamsExist 55 | { 56 | get 57 | { 58 | var listSetDefaultParams = (ListSetDefaultParamsDelegate)LoadFunction("ListSetDefaultParams"); 59 | var exist = listSetDefaultParams != null; 60 | return exist; 61 | } 62 | } 63 | 64 | public bool ListSearchTextExist 65 | { 66 | get 67 | { 68 | var listSearchTextW = (ListSearchTextWDelegate)LoadFunction("ListSearchTextW"); 69 | var listSearchText = (ListSearchTextDelegate)LoadFunction("ListSearchText"); 70 | var exist = listSearchTextW != null || listSearchText != null; 71 | return exist; 72 | } 73 | } 74 | 75 | public bool ListSearchDialogExist 76 | { 77 | get 78 | { 79 | var listSearchDialog = (ListSearchDialogDelegate)LoadFunction("ListSearchDialog"); 80 | var exist = listSearchDialog != null; 81 | return exist; 82 | } 83 | } 84 | 85 | public bool ListPrintExist 86 | { 87 | get 88 | { 89 | var listPrintW = (ListPrintWDelegate)LoadFunction("ListPrintW"); 90 | var listPrint = (ListPrintDelegate)LoadFunction("ListPrint"); 91 | var exist = listPrintW != null || listPrint != null; 92 | return exist; 93 | } 94 | } 95 | 96 | 97 | public Plugin(string moduleName) 98 | { 99 | ModuleName = moduleName; 100 | _moduleHandle = IntPtr.Zero; 101 | } 102 | 103 | public bool LoadModule() 104 | { 105 | UnloadModule(); 106 | _moduleHandle = NativeMethods.LoadLibrary(ModuleName); 107 | var result = _moduleHandle != IntPtr.Zero; 108 | return result; 109 | } 110 | 111 | public bool UnloadModule() 112 | { 113 | if (_moduleHandle == IntPtr.Zero) 114 | { 115 | return true; 116 | } 117 | var result = NativeMethods.FreeLibrary(_moduleHandle); 118 | return result; 119 | } 120 | 121 | public IntPtr ListLoad(IntPtr hwndParent, string fileName) 122 | { 123 | var listLoadW = (ListLoadWDelegate)LoadFunction("ListLoadW"); 124 | if (listLoadW != null) 125 | { 126 | var hwnd = listLoadW(hwndParent, fileName, 0); 127 | return hwnd; 128 | } 129 | else 130 | { 131 | var listLoad = (ListLoadDelegate)LoadFunction("ListLoad"); 132 | if (listLoad == null) 133 | { 134 | return IntPtr.Zero; 135 | } 136 | var hwnd = listLoad(hwndParent, fileName, 0); 137 | return hwnd; 138 | } 139 | } 140 | 141 | public void ListCloseWindow(IntPtr hwndList) 142 | { 143 | var function = (ListCloseWindowDelegate)LoadFunction("ListCloseWindow"); 144 | function(hwndList); 145 | } 146 | 147 | public string ListGetDetectString() 148 | { 149 | var function = (ListGetDetectStringDelegate)LoadFunction("ListGetDetectString"); 150 | var detectString = new StringBuilder(1024 * 10); 151 | function(detectString, detectString.Capacity); 152 | return detectString.ToString(); 153 | } 154 | 155 | public void ListNotificationReceived(IntPtr hwndList, int message, IntPtr wParam, IntPtr lParam) 156 | { 157 | var function = (ListNotificationReceivedDelegate)LoadFunction("ListNotificationReceived"); 158 | function(hwndList, message, wParam, lParam); 159 | } 160 | 161 | public void ListSetDefaultParams(int interfaceVersionLow, int interfaceVersionHigh, string iniFile) 162 | { 163 | var function = (ListSetDefaultParamsDelegate)LoadFunction("ListSetDefaultParams"); 164 | var defaultParams = new ListDefaultParamStruct(); 165 | defaultParams.interfaceVersionLow = interfaceVersionLow; 166 | defaultParams.interfaceVersionHigh = interfaceVersionHigh; 167 | defaultParams.defaultIniFile = iniFile; 168 | defaultParams.size = Marshal.SizeOf(defaultParams); 169 | function(defaultParams); 170 | } 171 | 172 | public int ListSearchText(IntPtr hwndList, string searchString, int flags) 173 | { 174 | var listSearchTextW = (ListSearchTextWDelegate)LoadFunction("ListSearchTextW"); 175 | if (listSearchTextW != null) 176 | { 177 | var result = listSearchTextW(hwndList, searchString, flags); 178 | return result; 179 | } 180 | else 181 | { 182 | var listSearchText = (ListSearchTextDelegate)LoadFunction("ListSearchText"); 183 | var result = listSearchText(hwndList, searchString, flags); 184 | return result; 185 | } 186 | } 187 | 188 | public int ListSearchDialog(IntPtr hwndList, int flags) 189 | { 190 | var function = (ListSearchDialogDelegate)LoadFunction("ListSearchDialog"); 191 | var result = function(hwndList, flags); 192 | return result; 193 | } 194 | 195 | public int ListPrint(IntPtr hwndList, string fileName, string printerName, int flags, ref Rect margins) 196 | { 197 | var listPrintW = (ListPrintWDelegate)LoadFunction("ListPrintW"); 198 | if (listPrintW != null) 199 | { 200 | var result = listPrintW(hwndList, fileName, printerName, flags, ref margins); 201 | return result; 202 | 203 | } 204 | else 205 | { 206 | var listPrint = (ListPrintDelegate)LoadFunction("ListPrint"); 207 | var result = listPrint(hwndList, fileName, printerName, flags, ref margins); 208 | return result; 209 | } 210 | } 211 | 212 | [HandleProcessCorruptedStateExceptions] 213 | public static string[] GetSupportedExtensions(string fileName) 214 | { 215 | try 216 | { 217 | var plugin = new Plugin(fileName); 218 | var pluginLoaded = plugin.LoadModule(); 219 | if (!pluginLoaded) return new string[0]; 220 | var detectString = plugin.ListGetDetectStringExist ? plugin.ListGetDetectString() : string.Empty; 221 | var regExp = new Regex("EXT=\\\"(\\w+)\\\"", RegexOptions.IgnoreCase | RegexOptions.Compiled); 222 | var matches = regExp.Matches(detectString); 223 | var result = matches.Cast().Select(m => m.Groups[1].Value).ToArray(); 224 | plugin.UnloadModule(); 225 | return result; 226 | } 227 | catch 228 | { 229 | return new string[0]; 230 | } 231 | } 232 | 233 | private Delegate LoadFunction(string functionName) 234 | { 235 | if (_moduleHandle == IntPtr.Zero) throw new Exception("Plugin module is not loaded."); 236 | var functionAddress = NativeMethods.GetProcAddress(_moduleHandle, functionName); 237 | if (functionAddress == IntPtr.Zero) 238 | { 239 | return null; 240 | } 241 | var function = Marshal.GetDelegateForFunctionPointer(functionAddress, typeof(T)); 242 | return function; 243 | } 244 | } 245 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | using System.Threading; 5 | using System.IO; 6 | using System.Linq; 7 | using Wlx2Explorer.Forms; 8 | using Wlx2Explorer.Utils; 9 | using Wlx2Explorer.Settings; 10 | 11 | namespace Wlx2Explorer 12 | { 13 | static class Program 14 | { 15 | private static Mutex _mutex; 16 | 17 | /// 18 | /// The main entry point for the application. 19 | /// 20 | [STAThread] 21 | static void Main(string[] args) 22 | { 23 | AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException; 24 | Application.ThreadException += OnThreadException; 25 | Environment.CurrentDirectory = AssemblyUtils.AssemblyDirectory; 26 | 27 | // Command Line Interface 28 | var toggleParser = new ToggleParser(args); 29 | if (toggleParser.HasToggle("h") || toggleParser.HasToggle("help")) 30 | { 31 | var messageBoxForm = new MessageBoxForm(); 32 | messageBoxForm.Message = BuildHelpString(); 33 | messageBoxForm.Text = "Help"; 34 | messageBoxForm.ShowDialog(); 35 | return; 36 | } 37 | 38 | if (toggleParser.HasToggle("f") || toggleParser.HasToggle("file")) 39 | { 40 | var suppressmsg = toggleParser.HasToggle("f") || toggleParser.HasToggle("suppressmsg"); 41 | var fileName = toggleParser.GetToggleValueOrDefault("f", null) ?? toggleParser.GetToggleValueOrDefault("file", null); 42 | if (!File.Exists(fileName)) 43 | { 44 | if (!suppressmsg) 45 | { 46 | MessageBox.Show($"{fileName} does not exist.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 47 | } 48 | } 49 | else 50 | { 51 | ProgramSettings settings; 52 | try 53 | { 54 | settings = ProgramSettings.Read(); 55 | } 56 | catch 57 | { 58 | if (!suppressmsg) 59 | { 60 | MessageBox.Show("Failed to read a program setting file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 61 | } 62 | return; 63 | } 64 | 65 | var plugins = new List(); 66 | foreach (var pluginInfo in settings.Plugins) 67 | { 68 | var plugin = new Plugin(pluginInfo.Path); 69 | var pluginLoaded = false; 70 | var pluginInitialized = true; 71 | 72 | try 73 | { 74 | pluginLoaded = plugin.LoadModule(); 75 | } 76 | catch 77 | { 78 | pluginLoaded = false; 79 | } 80 | 81 | try 82 | { 83 | if (plugin.ListSetDefaultParamsExist) 84 | { 85 | var pluginExtension = Path.GetExtension(pluginInfo.Path); 86 | var pluginIniFile = Path.GetFullPath(pluginInfo.Path).Replace(pluginExtension, ".ini"); 87 | if (!File.Exists(pluginIniFile)) 88 | { 89 | plugin.ListSetDefaultParams(settings.PluginLowVersion, settings.PluginHighVersion, settings.PluginIniFile); 90 | } 91 | } 92 | } 93 | catch 94 | { 95 | pluginInitialized = false; 96 | } 97 | 98 | if (pluginLoaded && pluginInitialized) 99 | { 100 | plugins.Add(plugin); 101 | } 102 | else if (!pluginLoaded) 103 | { 104 | if (!suppressmsg) 105 | { 106 | MessageBox.Show($@"Failed to load the plugin {Environment.NewLine} ""{pluginInfo.Path}"".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 107 | } 108 | } 109 | else 110 | { 111 | if (!suppressmsg) 112 | { 113 | MessageBox.Show($@"Failed to initialize the plugin with default settings {Environment.NewLine} ""{pluginInfo.Path}"".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 114 | } 115 | } 116 | } 117 | 118 | if (plugins.Any()) 119 | { 120 | var listerForm = new ListerForm(settings, plugins, fileName); 121 | listerForm.ShowDialog(); 122 | } 123 | } 124 | return; 125 | } 126 | 127 | var mutexName = "Wlx2Explorer"; 128 | _mutex = new Mutex(false, mutexName, out var createNew); 129 | if (!createNew) 130 | { 131 | return; 132 | } 133 | 134 | Application.EnableVisualStyles(); 135 | Application.SetCompatibleTextRenderingDefault(false); 136 | Application.Run(new MainForm()); 137 | } 138 | 139 | static void OnCurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) 140 | { 141 | var ex = e.ExceptionObject as Exception; 142 | ex = ex ?? new Exception("OnCurrentDomainUnhandledException"); 143 | OnThreadException(sender, new ThreadExceptionEventArgs(ex)); 144 | } 145 | 146 | static void OnThreadException(object sender, ThreadExceptionEventArgs e) => 147 | MessageBox.Show(e.Exception.ToString(), AssemblyUtils.AssemblyProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 148 | 149 | static string BuildHelpString() => 150 | @"-h --help The help 151 | -f --file Path to file 152 | -s --suppressmsg Suppress messages 153 | 154 | Example: 155 | Wlx2Explorer.exe -s --file ""C:\Temp\Image.jpeg"""; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Wlx2Explorer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Total Commander lister plugin from File Explorer and Desktop")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Alexander Illarionov")] 11 | [assembly: AssemblyProduct("Wlx2Explorer")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("166879d2-29e4-4753-a30e-414cf690c2d9")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.6.0")] 35 | [assembly: AssemblyFileVersion("1.6.0")] -------------------------------------------------------------------------------- /Wlx2Explorer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Wlx2Explorer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wlx2Explorer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Down { 67 | get { 68 | object obj = ResourceManager.GetObject("Down", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap Start { 77 | get { 78 | object obj = ResourceManager.GetObject("Start", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap Stop { 87 | get { 88 | object obj = ResourceManager.GetObject("Stop", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap Up { 97 | get { 98 | object obj = ResourceManager.GetObject("Up", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap Wlx2Explorer { 107 | get { 108 | object obj = ResourceManager.GetObject("Wlx2Explorer", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Wlx2Explorer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Images\Down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Images\Start.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Images\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Images\Up.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Images\Wlx2Explorer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | -------------------------------------------------------------------------------- /Wlx2Explorer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.1008 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Wlx2Explorer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Wlx2Explorer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Wlx2Explorer/Settings/PluginInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Wlx2Explorer.Settings 4 | { 5 | class PluginInfo 6 | { 7 | public string Path { get; set; } 8 | 9 | public IList Extensions { get; set; } 10 | 11 | public PluginInfo() : this("", new List()) 12 | { 13 | } 14 | 15 | public PluginInfo(string path, IList extensions) 16 | { 17 | Path = path; 18 | Extensions = extensions; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Wlx2Explorer/Settings/ProgramSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Xml.Linq; 4 | using System.Xml.XPath; 5 | using System.IO; 6 | using System.Text; 7 | using Wlx2Explorer.Utils; 8 | 9 | namespace Wlx2Explorer.Settings 10 | { 11 | class ProgramSettings 12 | { 13 | public IList Plugins { get; set; } 14 | 15 | public int ListerFormKey1 { get; set; } 16 | 17 | public int ListerFormKey2 { get; set; } 18 | 19 | public int ListerFormKey3 { get; set; } 20 | 21 | public int SearchDialogKey1 { get; set; } 22 | 23 | public int SearchDialogKey2 { get; set; } 24 | 25 | public int SearchDialogKey3 { get; set; } 26 | 27 | public int PrintDialogKey1 { get; set; } 28 | 29 | public int PrintDialogKey2 { get; set; } 30 | 31 | public int PrintDialogKey3 { get; set; } 32 | 33 | public int ListerFormWidth { get; set; } 34 | 35 | public int ListerFormHeight { get; set; } 36 | 37 | public bool ListerFormMaximized { get; set; } 38 | 39 | public bool AutoStartProgram { get; set; } 40 | 41 | public int PluginHighVersion { get; set; } 42 | 43 | public int PluginLowVersion { get; set; } 44 | 45 | public string PluginIniFile { get; set; } 46 | 47 | 48 | public ProgramSettings() 49 | { 50 | Plugins = new List(); 51 | } 52 | 53 | public static ProgramSettings Read() 54 | { 55 | var fileName = AssemblyUtils.AssemblyFileNameWithoutExtension + ".xml"; 56 | fileName = Path.Combine(AssemblyUtils.AssemblyDirectory, fileName); 57 | var document = XDocument.Load(fileName); 58 | var settings = Read(document); 59 | return settings; 60 | } 61 | 62 | public static ProgramSettings Read(XDocument document) => new ProgramSettings 63 | { 64 | ListerFormKey1 = int.Parse(document.XPathSelectElement("//Settings/ListerFormHotKeys").Attribute("key1").Value), 65 | ListerFormKey2 = int.Parse(document.XPathSelectElement("//Settings/ListerFormHotKeys").Attribute("key2").Value), 66 | ListerFormKey3 = int.Parse(document.XPathSelectElement("//Settings/ListerFormHotKeys").Attribute("key3").Value), 67 | SearchDialogKey1 = int.Parse(document.XPathSelectElement("//Settings/SearchDialogHotKeys").Attribute("key1").Value), 68 | SearchDialogKey2 = int.Parse(document.XPathSelectElement("//Settings/SearchDialogHotKeys").Attribute("key2").Value), 69 | SearchDialogKey3 = int.Parse(document.XPathSelectElement("//Settings/SearchDialogHotKeys").Attribute("key3").Value), 70 | PrintDialogKey1 = int.Parse(document.XPathSelectElement("//Settings/PrintDialogHotKeys").Attribute("key1").Value), 71 | PrintDialogKey2 = int.Parse(document.XPathSelectElement("//Settings/PrintDialogHotKeys").Attribute("key2").Value), 72 | PrintDialogKey3 = int.Parse(document.XPathSelectElement("//Settings/PrintDialogHotKeys").Attribute("key3").Value), 73 | ListerFormMaximized = bool.Parse(document.XPathSelectElement("//Settings/ListerForm").Attribute("maximized").Value), 74 | ListerFormWidth = int.Parse(document.XPathSelectElement("//Settings/ListerForm").Attribute("width").Value), 75 | ListerFormHeight = int.Parse(document.XPathSelectElement("//Settings/ListerForm").Attribute("height").Value), 76 | PluginHighVersion = int.Parse(document.XPathSelectElement("//Settings/PluginDefaultSettings").Attribute("highVersion").Value), 77 | PluginLowVersion = int.Parse(document.XPathSelectElement("//Settings/PluginDefaultSettings").Attribute("lowVersion").Value), 78 | PluginIniFile = new FileInfo(document.XPathSelectElement("//Settings/PluginDefaultSettings").Attribute("iniFile").Value).FullName, 79 | Plugins = document.XPathSelectElements("//Settings/Plugins/Plugin") 80 | .Select(el => new PluginInfo(el.Attribute("path").Value, string.IsNullOrWhiteSpace(el.Attribute("extensions").Value) ? new List() : el.Attribute("extensions").Value.Split(';').ToList())).ToList() 81 | }; 82 | 83 | public static void Write(ProgramSettings settings) 84 | { 85 | var fileName = AssemblyUtils.AssemblyFileNameWithoutExtension + ".xml"; 86 | fileName = Path.Combine(AssemblyUtils.AssemblyDirectory, fileName); 87 | Write(settings, fileName); 88 | } 89 | 90 | public static void Write(ProgramSettings settings, string fileName) 91 | { 92 | var document = new XDocument(new XDeclaration("1.0", "utf-8", null), 93 | new XElement("Settings", 94 | new XElement("Plugins", settings.Plugins.Select(x => new XElement("Plugin", 95 | new XAttribute("path", x.Path), 96 | new XAttribute("extensions", string.Join(";", x.Extensions.ToArray()))))), 97 | new XElement("ListerFormHotKeys", 98 | new XAttribute("key1", settings.ListerFormKey1.ToString()), 99 | new XAttribute("key2", settings.ListerFormKey2.ToString()), 100 | new XAttribute("key3", settings.ListerFormKey3.ToString())), 101 | new XElement("SearchDialogHotKeys", 102 | new XAttribute("key1", settings.SearchDialogKey1.ToString()), 103 | new XAttribute("key2", settings.SearchDialogKey2.ToString()), 104 | new XAttribute("key3", settings.SearchDialogKey3.ToString())), 105 | new XElement("PrintDialogHotKeys", 106 | new XAttribute("key1", settings.PrintDialogKey1.ToString()), 107 | new XAttribute("key2", settings.PrintDialogKey2.ToString()), 108 | new XAttribute("key3", settings.PrintDialogKey3.ToString())), 109 | new XElement("ListerForm", 110 | new XAttribute("maximized", settings.ListerFormMaximized.ToString()), 111 | new XAttribute("width", settings.ListerFormWidth.ToString()), 112 | new XAttribute("height", settings.ListerFormHeight.ToString())), 113 | new XElement("PluginDefaultSettings", 114 | new XAttribute("highVersion", settings.PluginHighVersion.ToString()), 115 | new XAttribute("lowVersion", settings.PluginLowVersion.ToString()), 116 | new XAttribute("iniFile", settings.PluginIniFile)))); 117 | 118 | Save(document, fileName); 119 | } 120 | 121 | private static void Save(XDocument document, string fileName) 122 | { 123 | using var writer = new Utf8StringWriter(); 124 | document.Save(writer, SaveOptions.None); 125 | File.WriteAllText(fileName, writer.ToString()); 126 | } 127 | 128 | private class Utf8StringWriter : StringWriter 129 | { 130 | public override Encoding Encoding { get { return Encoding.UTF8; } } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /Wlx2Explorer/StartUpManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | 3 | namespace Wlx2Explorer 4 | { 5 | static class StartUpManager 6 | { 7 | private const string RUN_LOCATION = @"Software\Microsoft\Windows\CurrentVersion\Run"; 8 | 9 | public static void AddToStartup(string keyName, string assemblyLocation) 10 | { 11 | using var key = Registry.CurrentUser.OpenSubKey(RUN_LOCATION, true); 12 | key.SetValue(keyName, assemblyLocation); 13 | } 14 | 15 | public static void RemoveFromStartup(string keyName) 16 | { 17 | using var key = Registry.CurrentUser.OpenSubKey(RUN_LOCATION, true); 18 | key.DeleteValue(keyName); 19 | } 20 | 21 | public static bool IsInStartup(string keyName, string assemblyLocation) 22 | { 23 | using var key = Registry.CurrentUser.OpenSubKey(RUN_LOCATION, true); 24 | if (key == null) 25 | { 26 | return false; 27 | } 28 | var value = (string)key.GetValue(keyName); 29 | if (string.IsNullOrEmpty(value)) 30 | { 31 | return false; 32 | } 33 | var result = (value == assemblyLocation); 34 | return result; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Wlx2Explorer/ToggleParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Wlx2Explorer 6 | { 7 | class ToggleParser 8 | { 9 | private readonly Dictionary toggles; 10 | 11 | public ToggleParser(string[] args) 12 | { 13 | toggles = 14 | args.Zip(args.Skip(1).Concat(new[] { string.Empty }), (first, second) => new { first, second }) 15 | .Where(pair => IsToggle(pair.first)) 16 | .ToDictionary(pair => RemovePrefix(pair.first).ToLowerInvariant(), g => IsToggle(g.second) ? string.Empty : g.second); 17 | } 18 | 19 | private static string RemovePrefix(string toggle) => new string(toggle.SkipWhile(c => c == '-').ToArray()); 20 | 21 | private static bool IsToggle(string arg) => arg.StartsWith("-", StringComparison.InvariantCulture); 22 | 23 | public bool HasToggle(string toggle) => toggles.ContainsKey(toggle.ToLowerInvariant()); 24 | 25 | public string GetToggleValueOrDefault(string toggle, string defaultValue) => toggles.TryGetValue(toggle.ToLowerInvariant(), out var value) ? value : defaultValue; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Wlx2Explorer/Utils/AssemblyUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.IO; 3 | using System.Linq; 4 | 5 | namespace Wlx2Explorer.Utils 6 | { 7 | static class AssemblyUtils 8 | { 9 | public static string AssemblyLocation => Assembly.GetExecutingAssembly().Location; 10 | 11 | public static string AssemblyDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 12 | 13 | public static string AssemblyFileNameWithoutExtension => Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location); 14 | 15 | public static string AssemblyTitle => Assembly 16 | .GetExecutingAssembly() 17 | .GetCustomAttributes(typeof(AssemblyTitleAttribute), false) 18 | .OfType() 19 | .FirstOrDefault()?.Title ?? string.Empty; 20 | 21 | 22 | public static string AssemblyProductName => Assembly 23 | .GetExecutingAssembly() 24 | .GetCustomAttributes(typeof(AssemblyProductAttribute), false) 25 | .OfType() 26 | .FirstOrDefault()?.Product ?? string.Empty; 27 | 28 | 29 | public static string AssemblyProductVersion 30 | { 31 | get 32 | { 33 | var version = Assembly.GetExecutingAssembly().GetName().Version; 34 | return $"{version.Major}.{version.Minor}.{version.Build}"; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Wlx2Explorer/Utils/WindowUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Runtime.InteropServices; 8 | using Wlx2Explorer.Native; 9 | using IWshRuntimeLibrary; 10 | using SHDocVw; 11 | using Shell32; 12 | 13 | namespace Wlx2Explorer.Utils 14 | { 15 | static class WindowUtils 16 | { 17 | public static string GetSelectedFileFromDesktopOrExplorer() 18 | { 19 | var hwnd = NativeMethods.GetForegroundWindow(); 20 | var className = GetClassName(hwnd); 21 | if (className == "WorkerW" || className == "Progman") 22 | { 23 | var hwndSysListView32 = GetSysListView32(); 24 | var fileName = GetSelectedFileFromDesktop(hwndSysListView32); 25 | return fileName; 26 | } 27 | else 28 | { 29 | var fileName = GetSelectedFileFromExplorer(hwnd); 30 | return fileName; 31 | } 32 | } 33 | 34 | private static string GetSelectedFileFromExplorer(IntPtr hwnd) 35 | { 36 | var hwndActiveTab = NativeMethods.FindWindowEx(hwnd, IntPtr.Zero, "ShellTabWindowClass", null); 37 | hwndActiveTab = hwndActiveTab != IntPtr.Zero ? hwndActiveTab : NativeMethods.FindWindowEx(hwnd, IntPtr.Zero, "TabWindowClass", null); 38 | 39 | var fileNames = new List(); 40 | var shellAppType = Type.GetTypeFromProgID("Shell.Application"); 41 | var shellObject = Activator.CreateInstance(shellAppType); 42 | var shellWindows = (IShellWindows)shellAppType.InvokeMember("Windows", BindingFlags.InvokeMethod, null, shellObject, new object[] { }); 43 | foreach (IWebBrowser2 window in shellWindows) 44 | { 45 | if (window.HWND != hwnd.ToInt32()) 46 | { 47 | continue; 48 | } 49 | 50 | if (hwndActiveTab != IntPtr.Zero && window is Native.Interfaces.IServiceProvider serviceProvider) 51 | { 52 | object shellBrowserObject; 53 | serviceProvider.QueryService(NativeConstants.SID_STopLevelBrowser, typeof(Native.Interfaces.IShellBrowser).GUID, out shellBrowserObject); 54 | var shellBrowser = (Native.Interfaces.IShellBrowser)shellBrowserObject; 55 | var hwndThisTab = IntPtr.Zero; 56 | shellBrowser.GetWindow(out hwndThisTab); 57 | if (hwndThisTab != IntPtr.Zero && hwndActiveTab != hwndThisTab) 58 | { 59 | continue; 60 | } 61 | } 62 | 63 | if (window.Document is IShellFolderViewDual2 document2) 64 | { 65 | foreach (FolderItem folderItem in document2.SelectedItems()) 66 | { 67 | fileNames.Add(folderItem.Path); 68 | } 69 | } 70 | else if (window.Document is IShellFolderViewDual document) 71 | { 72 | foreach (FolderItem folderItem in document.SelectedItems()) 73 | { 74 | fileNames.Add(folderItem.Path); 75 | } 76 | } 77 | } 78 | return fileNames.Any() ? fileNames[0] : string.Empty; 79 | } 80 | 81 | private static string GetSelectedFileFromDesktop(IntPtr hwnd) 82 | { 83 | var processPointer = IntPtr.Zero; 84 | var virtualAllocPointer = IntPtr.Zero; 85 | try 86 | { 87 | var itemNames = new List(); 88 | var processId = (uint)0; 89 | NativeMethods.GetWindowThreadProcessId(hwnd, out processId); 90 | var itemCount = NativeMethods.SendMessage(hwnd, NativeConstants.LVM_GETITEMCOUNT, 0, 0); 91 | processPointer = NativeMethods.OpenProcess(NativeConstants.PROCESS_VM_OPERATION | NativeConstants.PROCESS_VM_READ | NativeConstants.PROCESS_VM_WRITE, false, processId); 92 | virtualAllocPointer = NativeMethods.VirtualAllocEx(processPointer, IntPtr.Zero, 4096, NativeConstants.MEM_RESERVE | NativeConstants.MEM_COMMIT, NativeConstants.PAGE_READWRITE); 93 | 94 | for (int i = 0; i < itemCount; i++) 95 | { 96 | var buffer = new byte[256]; 97 | var item = new LVITEM[1]; 98 | item[0].mask = NativeConstants.LVIF_TEXT; 99 | item[0].iItem = i; 100 | item[0].iSubItem = 0; 101 | item[0].cchTextMax = buffer.Length; 102 | item[0].pszText = (IntPtr)((int)virtualAllocPointer + Marshal.SizeOf(typeof(LVITEM))); 103 | var numberOfBytesRead = (uint)0; 104 | 105 | NativeMethods.WriteProcessMemory(processPointer, virtualAllocPointer, Marshal.UnsafeAddrOfPinnedArrayElement(item, 0), Marshal.SizeOf(typeof(LVITEM)), ref numberOfBytesRead); 106 | NativeMethods.SendMessage(hwnd, NativeConstants.LVM_GETITEMW, i, virtualAllocPointer.ToInt32()); 107 | NativeMethods.ReadProcessMemory(processPointer, (IntPtr)((int)virtualAllocPointer + Marshal.SizeOf(typeof(LVITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0), buffer.Length, ref numberOfBytesRead); 108 | 109 | var text = Encoding.Unicode.GetString(buffer, 0, (int)numberOfBytesRead); 110 | text = text.Substring(0, text.IndexOf('\0')); 111 | var result = NativeMethods.SendMessage(hwnd, NativeConstants.LVM_GETITEMSTATE, i, (int)NativeConstants.LVIS_SELECTED); 112 | if (result == NativeConstants.LVIS_SELECTED) 113 | { 114 | itemNames.Add(text); 115 | } 116 | } 117 | 118 | if (itemNames.Any()) 119 | { 120 | var desktopDirectoryName = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 121 | var commonDesktopDirectoryName = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory); 122 | var itemName = itemNames[0]; 123 | var fileNames = Directory.GetFiles(desktopDirectoryName, itemName + ".*").ToList(); 124 | fileNames.AddRange(Directory.GetFiles(commonDesktopDirectoryName, itemName + ".*")); 125 | if (fileNames.Any()) 126 | { 127 | var fileName = fileNames[0]; 128 | if (Path.GetExtension(fileName).ToLower() == ".lnk") 129 | { 130 | WshShell shell = new WshShell(); 131 | IWshShortcut link = (IWshShortcut)shell.CreateShortcut(fileName); 132 | return link.TargetPath; 133 | } 134 | return fileName; 135 | } 136 | } 137 | return string.Empty; 138 | } 139 | finally 140 | { 141 | if (processPointer != IntPtr.Zero && virtualAllocPointer != IntPtr.Zero) 142 | { 143 | NativeMethods.VirtualFreeEx(processPointer, virtualAllocPointer, 0, NativeConstants.MEM_RELEASE); 144 | } 145 | 146 | if (processPointer != IntPtr.Zero) 147 | { 148 | NativeMethods.CloseHandle(processPointer); 149 | } 150 | } 151 | } 152 | 153 | public static bool IsChildWindow(IntPtr hwnd, IntPtr parentHwnd) 154 | { 155 | var result = false; 156 | var currentHwnd = hwnd; 157 | for ( ; ; ) 158 | { 159 | if (currentHwnd == parentHwnd) 160 | { 161 | result = true; 162 | break; 163 | } 164 | 165 | if (currentHwnd == IntPtr.Zero) 166 | { 167 | result = false; 168 | break; 169 | } 170 | 171 | currentHwnd = NativeMethods.GetParent(currentHwnd); 172 | } 173 | return result; 174 | } 175 | 176 | public static string GetClassName(IntPtr hwnd) 177 | { 178 | var builder = new StringBuilder(1024); 179 | NativeMethods.GetClassName(hwnd, builder, builder.Capacity); 180 | var className = builder.ToString(); 181 | return className; 182 | } 183 | 184 | public static IntPtr GetSysListView32() 185 | { 186 | if (Environment.OSVersion.Version.Major == 5) 187 | { 188 | var hwndProgman = NativeMethods.FindWindow("Progman", null); 189 | var hwndShell = NativeMethods.FindWindowEx(hwndProgman, IntPtr.Zero, "SHELLDLL_DefView", null); 190 | var hwnd = NativeMethods.FindWindowEx(hwndShell, IntPtr.Zero, "SysListView32", "FolderView"); 191 | return hwnd; 192 | } 193 | else 194 | { 195 | var hwnd = IntPtr.Zero; 196 | NativeMethods.EnumWindows(new NativeMethods.EnumWindowProc((tophandle, topparamhandle) => 197 | { 198 | var parent = NativeMethods.FindWindowEx(tophandle, IntPtr.Zero, "SHELLDLL_DefView", null); 199 | if (parent != IntPtr.Zero) 200 | { 201 | hwnd = NativeMethods.FindWindowEx(parent, IntPtr.Zero, "SysListView32", null); 202 | return false; 203 | } 204 | 205 | return true; 206 | }), IntPtr.Zero); 207 | return hwnd; 208 | } 209 | } 210 | } 211 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Win32WindowWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace Wlx2Explorer 5 | { 6 | class Win32WindowWrapper : IWin32Window 7 | { 8 | public IntPtr Handle { get; private set; } 9 | 10 | public Win32WindowWrapper(IntPtr handle) 11 | { 12 | Handle = handle; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Wlx2Explorer/Wlx2Explorer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {82A3A166-142C-4C62-8D57-6CF8678402AA} 9 | WinExe 10 | Properties 11 | Wlx2Explorer 12 | Wlx2Explorer 13 | v4.0 14 | Client 15 | 512 16 | 9 17 | 18 | 19 | x86 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | true 28 | 29 | 30 | x86 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | Wlx2Explorer.ico 40 | 41 | 42 | true 43 | bin\x64\Debug\ 44 | DEBUG;TRACE 45 | full 46 | x64 47 | prompt 48 | MinimumRecommendedRules.ruleset 49 | 50 | 51 | bin\x64\Release\ 52 | TRACE 53 | true 54 | pdbonly 55 | x64 56 | prompt 57 | MinimumRecommendedRules.ruleset 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Form 74 | 75 | 76 | MessageBoxForm.cs 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | Form 97 | 98 | 99 | AboutForm.cs 100 | 101 | 102 | Form 103 | 104 | 105 | SearchForm.cs 106 | 107 | 108 | Form 109 | 110 | 111 | ListerForm.cs 112 | 113 | 114 | Form 115 | 116 | 117 | MainForm.cs 118 | 119 | 120 | Form 121 | 122 | 123 | PluginSettingsForm.cs 124 | 125 | 126 | Form 127 | 128 | 129 | ProgramSettingsForm.cs 130 | 131 | 132 | 133 | 134 | 135 | AboutForm.cs 136 | 137 | 138 | MessageBoxForm.cs 139 | 140 | 141 | SearchForm.cs 142 | 143 | 144 | ListerForm.cs 145 | 146 | 147 | MainForm.cs 148 | 149 | 150 | PluginSettingsForm.cs 151 | 152 | 153 | ProgramSettingsForm.cs 154 | 155 | 156 | ResXFileCodeGenerator 157 | Resources.Designer.cs 158 | Designer 159 | 160 | 161 | True 162 | Resources.resx 163 | True 164 | 165 | 166 | SettingsSingleFileGenerator 167 | Settings.Designer.cs 168 | 169 | 170 | True 171 | Settings.settings 172 | True 173 | 174 | 175 | PreserveNewest 176 | 177 | 178 | 179 | 180 | {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B} 181 | 1 182 | 0 183 | 0 184 | tlbimp 185 | False 186 | True 187 | 188 | 189 | {EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B} 190 | 1 191 | 1 192 | 0 193 | tlbimp 194 | False 195 | True 196 | 197 | 198 | {50A7E9B0-70EF-11D1-B75A-00A0C90564FE} 199 | 1 200 | 0 201 | 0 202 | tlbimp 203 | False 204 | True 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | PreserveNewest 219 | 220 | 221 | 222 | 223 | 224 | call "$(DevEnvDir)..\tools\vsdevcmd.bat" 225 | editbin.exe /NXCOMPAT:NO "$(TargetPath)" 226 | copy /Y "$(ProjectDir)Libs\*.dll" "$(TargetDir)" 227 | 228 | 229 | 236 | -------------------------------------------------------------------------------- /Wlx2Explorer/Wlx2Explorer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderPro/Wlx2Explorer/da03c8aa3b6882362b2d772b46f7f2a2f8b3c7d5/Wlx2Explorer/Wlx2Explorer.ico -------------------------------------------------------------------------------- /Wlx2Explorer/Wlx2Explorer.ini: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Wlx2Explorer/Wlx2Explorer.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------