diff --git a/DLSiteDumperCS.sln b/DLSiteDumperCS.sln new file mode 100644 index 0000000..4794696 --- /dev/null +++ b/DLSiteDumperCS.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DLSiteDumperCS", "DLSiteDumperCS\DLSiteDumperCS.csproj", "{833A0652-30AE-4036-8F2D-FA1CE33C32D9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Debug|x64.ActiveCfg = Debug|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Debug|x64.Build.0 = Debug|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Debug|x86.ActiveCfg = Debug|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Debug|x86.Build.0 = Debug|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Release|Any CPU.Build.0 = Release|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Release|x64.ActiveCfg = Release|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Release|x64.Build.0 = Release|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Release|x86.ActiveCfg = Release|Any CPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5B0D083E-842D-43DD-BDB0-A295223D2752} + EndGlobalSection +EndGlobal diff --git a/DLSiteDumperCS/App.config b/DLSiteDumperCS/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/DLSiteDumperCS/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DLSiteDumperCS/DLSiteDumperCS.csproj b/DLSiteDumperCS/DLSiteDumperCS.csproj new file mode 100644 index 0000000..b12232b --- /dev/null +++ b/DLSiteDumperCS/DLSiteDumperCS.csproj @@ -0,0 +1,112 @@ + + + + + Debug + AnyCPU + {833A0652-30AE-4036-8F2D-FA1CE33C32D9} + WinExe + DLSiteDumperCS + DLSiteDumperCS + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + + True + True + Resources.resx + + + + + + + + Form + + + WorkingDialog.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + WorkingDialog.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + \ No newline at end of file diff --git a/DLSiteDumperCS/ExplorerLikeFilenameComparer.cs b/DLSiteDumperCS/ExplorerLikeFilenameComparer.cs new file mode 100644 index 0000000..946e80c --- /dev/null +++ b/DLSiteDumperCS/ExplorerLikeFilenameComparer.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Runtime.InteropServices; +/// +/// Enable to compare filename like a boss. +/// +public class ExplorerLikeFilenameComparer : IComparer +{ + [DllImport( "shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true )] + static extern int StrCmpLogicalW( string x, string y ); + + public int Compare( string x, string y ) + { + return StrCmpLogicalW( x, y ); + } + +} \ No newline at end of file diff --git a/DLSiteDumperCS/Gdi32.cs b/DLSiteDumperCS/Gdi32.cs new file mode 100644 index 0000000..31d3f23 --- /dev/null +++ b/DLSiteDumperCS/Gdi32.cs @@ -0,0 +1,42 @@ +using System.Runtime.InteropServices; + +public static class Gdi32 +{ + public enum BitmapCompressionMode : uint + { + BI_RGB = 0, + BI_RLE8 = 1, + BI_RLE4 = 2, + BI_BITFIELDS = 3, + BI_JPEG = 4, + BI_PNG = 5 + } + + [StructLayout( LayoutKind.Sequential )] + public struct BITMAPINFOHEADER + { + public uint biSize; + public int biWidth; + public int biHeight; + public ushort biPlanes; + public ushort biBitCount; + public BitmapCompressionMode biCompression; + public uint biSizeImage; + public int biXPelsPerMeter; + public int biYPelsPerMeter; + public uint biClrUsed; + public uint biClrImportant; + } + + [StructLayout( LayoutKind.Sequential, Pack = 2 )] + public struct BITMAPFILEHEADER + { + public ushort bfType; + public uint bfSize; + public ushort bfReserved1; + public ushort bfReserved2; + public uint bfOffBits; + } + + +} diff --git a/DLSiteDumperCS/HtmlImageReaderGenerator.cs b/DLSiteDumperCS/HtmlImageReaderGenerator.cs new file mode 100644 index 0000000..8ad43a5 --- /dev/null +++ b/DLSiteDumperCS/HtmlImageReaderGenerator.cs @@ -0,0 +1,64 @@ +using System; +using System.Diagnostics; +using System.Text; +using System.IO; + +class HtmlImageReaderGenerator +{ + public string[] FileList; + public bool IsRightToLeft; + public string OutputPath; + public int ImageZoomPercent; + + /// + /// It expects 3 string to replace + /// /*READ_DIRECTION_FLAG*/ + /// /*IMAGE_WIDTH*/ + /// /*CONTENT*/ + /// + public string TemplateData; + + StringBuilder sb; + StringBuilder contentSb; + + public bool Generate( ) + { + if( sb == null ) + sb = new StringBuilder( ); + sb.Clear( ); + sb.Append( TemplateData ); + + string readDirStyle; + if( IsRightToLeft ) + readDirStyle = "direction: rtl"; // This is going into CSS part + else + readDirStyle = ""; + sb.Replace( "/*READ_DIRECTION_FLAG*/", readDirStyle ); + + string imageWidth = "width: 50%"; + if( ImageZoomPercent > 0 && ImageZoomPercent <= 100 ) // Must be in valid range + imageWidth = $"width: {ImageZoomPercent}%"; + sb.Replace( "/*IMAGE_WIDTH*/", imageWidth ); + + // For all contents + if( contentSb == null ) + contentSb = new StringBuilder( ); + contentSb.Clear( ); + foreach( string line in FileList ) + { + contentSb.AppendLine( $"" ); + } + sb.Replace( "/*CONTENT*/", contentSb.ToString( ) ); + + try + { + File.WriteAllText( OutputPath, sb.ToString( ) ); + } + catch( Exception e ) + { + Debug.Print( e.ToString( ) ); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/DLSiteDumperCS/Kernel32.cs b/DLSiteDumperCS/Kernel32.cs new file mode 100644 index 0000000..5229f22 --- /dev/null +++ b/DLSiteDumperCS/Kernel32.cs @@ -0,0 +1,164 @@ + +using System; +using System.Diagnostics; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +public static class Kernel32 +{ + // https://www.pinvoke.net/default.aspx/kernel32.openprocess + [DllImport( "kernel32.dll", SetLastError = true )] + public static extern IntPtr OpenProcess( + uint processAccess, + bool bInheritHandle, + int processId + ); + + [Flags] + public enum ProcessAccessTypes + { + PROCESS_TERMINATE = 0x00000001, + PROCESS_CREATE_THREAD = 0x00000002, + PROCESS_SET_SESSIONID = 0x00000004, + PROCESS_VM_OPERATION = 0x00000008, + PROCESS_VM_READ = 0x00000010, + PROCESS_VM_WRITE = 0x00000020, + PROCESS_DUP_HANDLE = 0x00000040, + PROCESS_CREATE_PROCESS = 0x00000080, + PROCESS_SET_QUOTA = 0x00000100, + PROCESS_SET_INFORMATION = 0x00000200, + PROCESS_QUERY_INFORMATION = 0x00000400, + STANDARD_RIGHTS_REQUIRED = 0x000F0000, + SYNCHRONIZE = 0x00100000, + PROCESS_ALL_ACCESS = PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SET_SESSIONID | PROCESS_VM_OPERATION | + PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_SET_QUOTA | + PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION | STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE + } + + public static IntPtr OpenProcess( Process proc, ProcessAccessTypes flags ) + { + return OpenProcess( (uint)flags, false, proc.Id ); + } + + // https://www.pinvoke.net/default.aspx/kernel32.CloseHandle + [DllImport( "kernel32.dll", SetLastError = true )] + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] + [SuppressUnmanagedCodeSecurity] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool CloseHandle( IntPtr hObject ); + + [DllImport( "kernel32.dll" )] + public static extern int VirtualQueryEx( IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength ); + + [StructLayout( LayoutKind.Sequential )] + public struct MEMORY_BASIC_INFORMATION + { + public IntPtr BaseAddress; + public IntPtr AllocationBase; + public uint AllocationProtect; + public IntPtr RegionSize; + public uint State; + public uint Protect; + public uint Type; + } + + public enum PageAllocationProtect : uint + { + PAGE_EXECUTE = 0x00000010, + PAGE_EXECUTE_READ = 0x00000020, + PAGE_EXECUTE_READWRITE = 0x00000040, + PAGE_EXECUTE_WRITECOPY = 0x00000080, + PAGE_NOACCESS = 0x00000001, + PAGE_READONLY = 0x00000002, + PAGE_READWRITE = 0x00000004, + PAGE_WRITECOPY = 0x00000008, + PAGE_GUARD = 0x00000100, + PAGE_NOCACHE = 0x00000200, + PAGE_WRITECOMBINE = 0x00000400 + } + + public enum MemState : uint + { + MEM_COMMIT = 0x1000, + MEM_FREE = 0x10000, + MEM_RESERVE = 0x2000 + } + + public enum MemType : uint + { + MEM_IMAGE = 0x1000000, + MEM_MAPPED = 0x40000, + MEM_PRIVATE = 0x20000 + } + + [DllImport( "kernel32.dll", SetLastError = true )] + public static extern bool ReadProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesRead ); + + public static byte[] StructToBytes( T str ) where T : struct + { + int size = Marshal.SizeOf(str); + byte[] arr = new byte[size]; + + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr( str, ptr, true ); + Marshal.Copy( ptr, arr, 0, size ); + Marshal.FreeHGlobal( ptr ); + return arr; + } + + [Flags] + public enum VirtualAllocExTypes + { + WRITE_WATCH_FLAG_RESET = 0x00000001, // Win98 only + MEM_COMMIT = 0x00001000, + MEM_RESERVE = 0x00002000, + MEM_COMMIT_OR_RESERVE = 0x00003000, + MEM_DECOMMIT = 0x00004000, + MEM_RELEASE = 0x00008000, + MEM_FREE = 0x00010000, + MEM_PUBLIC = 0x00020000, + MEM_MAPPED = 0x00040000, + MEM_RESET = 0x00080000, // Win2K only + MEM_TOP_DOWN = 0x00100000, + MEM_WRITE_WATCH = 0x00200000, // Win98 only + MEM_PHYSICAL = 0x00400000, // Win2K only + //MEM_4MB_PAGES = 0x80000000, // ?? + SEC_IMAGE = 0x01000000, + MEM_IMAGE = SEC_IMAGE + } + + [Flags] + public enum AccessProtectionFlags + { + PAGE_NOACCESS = 0x001, + PAGE_READONLY = 0x002, + PAGE_READWRITE = 0x004, + PAGE_WRITECOPY = 0x008, + PAGE_EXECUTE = 0x010, + PAGE_EXECUTE_READ = 0x020, + PAGE_EXECUTE_READWRITE = 0x040, + PAGE_EXECUTE_WRITECOPY = 0x080, + PAGE_GUARD = 0x100, + PAGE_NOCACHE = 0x200, + PAGE_WRITECOMBINE = 0x400 + } + + [DllImport( "kernel32.dll" )] + public static extern IntPtr VirtualAllocEx( + IntPtr hProcess, + IntPtr address, + UInt32 size, + VirtualAllocExTypes allocationType, + AccessProtectionFlags flags + ); + + [DllImport( "kernel32.dll" )] + public static extern bool VirtualFreeEx( + IntPtr hProcess, + IntPtr address, + UInt32 size, + VirtualAllocExTypes dwFreeType + ); +} \ No newline at end of file diff --git a/DLSiteDumperCS/MainForm.Designer.cs b/DLSiteDumperCS/MainForm.Designer.cs new file mode 100644 index 0000000..49172e4 --- /dev/null +++ b/DLSiteDumperCS/MainForm.Designer.cs @@ -0,0 +1,571 @@ + +namespace DLSiteDumperCS +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if( disposing && (components != null) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.rip = new System.Windows.Forms.Button(); + this.autoDetectPidButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.pidTextBox = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.startPageInput = new System.Windows.Forms.NumericUpDown(); + this.savePathTextBox = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.browseButton = new System.Windows.Forms.Button(); + this.label7 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.effectivePathTextBox = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.imageExtSelect = new System.Windows.Forms.ComboBox(); + this.testButton = new System.Windows.Forms.Button(); + this.label10 = new System.Windows.Forms.Label(); + this.betweenPageDelay = new System.Windows.Forms.NumericUpDown(); + this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.openHtmlOption = new System.Windows.Forms.CheckBox(); + this.genHtmlButton = new System.Windows.Forms.Button(); + this.label13 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.readStyleSelect = new System.Windows.Forms.ComboBox(); + this.label11 = new System.Windows.Forms.Label(); + this.pageZoomPercent = new System.Windows.Forms.NumericUpDown(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.linkLabel3 = new System.Windows.Forms.LinkLabel(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.linkLabel4 = new System.Windows.Forms.LinkLabel(); + this.label14 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + ((System.ComponentModel.ISupportInitialize)(this.startPageInput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.betweenPageDelay)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pageZoomPercent)).BeginInit(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // rip + // + this.rip.Location = new System.Drawing.Point(16, 356); + this.rip.Name = "rip"; + this.rip.Size = new System.Drawing.Size(182, 42); + this.rip.TabIndex = 0; + this.rip.Text = "Batch dump from current to last page"; + this.rip.UseVisualStyleBackColor = true; + this.rip.Click += new System.EventHandler(this.OnRipClick); + // + // autoDetectPidButton + // + this.autoDetectPidButton.Location = new System.Drawing.Point(177, 20); + this.autoDetectPidButton.Name = "autoDetectPidButton"; + this.autoDetectPidButton.Size = new System.Drawing.Size(75, 23); + this.autoDetectPidButton.TabIndex = 1; + this.autoDetectPidButton.Text = "Auto detect"; + this.autoDetectPidButton.UseVisualStyleBackColor = true; + this.autoDetectPidButton.Click += new System.EventHandler(this.autoDetectPidButton_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(29, 13); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(152, 13); + this.label1.TabIndex = 2; + this.label1.Text = "DLSite Viewer process id (PID)"; + // + // pidTextBox + // + this.pidTextBox.Location = new System.Drawing.Point(16, 22); + this.pidTextBox.Name = "pidTextBox"; + this.pidTextBox.Size = new System.Drawing.Size(155, 20); + this.pidTextBox.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(15, 26); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(229, 13); + this.label2.TabIndex = 5; + this.label2.Text = "Not satisfied? Mod it yourself, fork this bad boy."; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(13, 424); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(304, 52); + this.label3.TabIndex = 6; + this.label3.Text = "Have problem?\r\nIf you have too new viewer version.\r\nYou might need an older versi" + + "on of DLSite viewer. \r\nTested with 1.0.34 (1.0.4.2) Someone left a link in forum" + + " below:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(13, 55); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(349, 52); + this.label4.TabIndex = 6; + this.label4.Text = resources.GetString("label4.Text"); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(13, 115); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(128, 13); + this.label5.TabIndex = 2; + this.label5.Text = "Write first file as page No."; + // + // startPageInput + // + this.startPageInput.Location = new System.Drawing.Point(150, 113); + this.startPageInput.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.startPageInput.Name = "startPageInput"; + this.startPageInput.Size = new System.Drawing.Size(74, 20); + this.startPageInput.TabIndex = 9; + this.startPageInput.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.startPageInput.ValueChanged += new System.EventHandler(this.startPageInput_ValueChanged); + // + // savePathTextBox + // + this.savePathTextBox.Location = new System.Drawing.Point(16, 200); + this.savePathTextBox.Name = "savePathTextBox"; + this.savePathTextBox.Size = new System.Drawing.Size(334, 20); + this.savePathTextBox.TabIndex = 3; + this.savePathTextBox.TextChanged += new System.EventHandler(this.savePathTextBox_TextChanged); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(13, 184); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(102, 13); + this.label6.TabIndex = 2; + this.label6.Text = "Image save location"; + // + // browseButton + // + this.browseButton.Location = new System.Drawing.Point(275, 171); + this.browseButton.Name = "browseButton"; + this.browseButton.Size = new System.Drawing.Size(75, 23); + this.browseButton.TabIndex = 1; + this.browseButton.Text = "Browse"; + this.browseButton.UseVisualStyleBackColor = true; + this.browseButton.Click += new System.EventHandler(this.browseButton_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(15, 62); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(155, 13); + this.label7.TabIndex = 6; + this.label7.Text = "Original author project: Thanks!"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(13, 223); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(158, 13); + this.label8.TabIndex = 2; + this.label8.Text = "Preview effective save location:"; + // + // effectivePathTextBox + // + this.effectivePathTextBox.Location = new System.Drawing.Point(16, 239); + this.effectivePathTextBox.Name = "effectivePathTextBox"; + this.effectivePathTextBox.ReadOnly = true; + this.effectivePathTextBox.Size = new System.Drawing.Size(334, 20); + this.effectivePathTextBox.TabIndex = 7; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(13, 143); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(77, 13); + this.label9.TabIndex = 2; + this.label9.Text = "Save as image"; + // + // imageExtSelect + // + this.imageExtSelect.FormattingEnabled = true; + this.imageExtSelect.Items.AddRange(new object[] { + "png", + "jpg"}); + this.imageExtSelect.Location = new System.Drawing.Point(150, 139); + this.imageExtSelect.Name = "imageExtSelect"; + this.imageExtSelect.Size = new System.Drawing.Size(121, 21); + this.imageExtSelect.TabIndex = 10; + this.imageExtSelect.SelectedIndexChanged += new System.EventHandler(this.imageExtSelect_SelectedIndexChanged); + // + // testButton + // + this.testButton.Location = new System.Drawing.Point(204, 356); + this.testButton.Name = "testButton"; + this.testButton.Size = new System.Drawing.Size(146, 42); + this.testButton.TabIndex = 0; + this.testButton.Text = "Test dump current page in viewer"; + this.testButton.UseVisualStyleBackColor = true; + this.testButton.Click += new System.EventHandler(this.OnTestButton); + // + // label10 + // + this.label10.Location = new System.Drawing.Point(13, 283); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(338, 54); + this.label10.TabIndex = 2; + this.label10.Text = "Wait N milisecond before capture.\r\nViewer needs some time between page to redraw," + + " \r\nif capture too fast you will get garbaged image.\r\nStandard is 1000ms. Can try" + + " lower this to 500 with fast PC."; + // + // betweenPageDelay + // + this.betweenPageDelay.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.betweenPageDelay.Location = new System.Drawing.Point(277, 283); + this.betweenPageDelay.Maximum = new decimal(new int[] { + 5000, + 0, + 0, + 0}); + this.betweenPageDelay.Minimum = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.betweenPageDelay.Name = "betweenPageDelay"; + this.betweenPageDelay.Size = new System.Drawing.Size(74, 20); + this.betweenPageDelay.TabIndex = 9; + this.betweenPageDelay.Value = new decimal(new int[] { + 1000, + 0, + 0, + 0}); + // + // backgroundWorker1 + // + this.backgroundWorker1.WorkerReportsProgress = true; + this.backgroundWorker1.WorkerSupportsCancellation = true; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.openHtmlOption); + this.groupBox1.Controls.Add(this.genHtmlButton); + this.groupBox1.Controls.Add(this.label13); + this.groupBox1.Controls.Add(this.label12); + this.groupBox1.Controls.Add(this.readStyleSelect); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.pageZoomPercent); + this.groupBox1.Location = new System.Drawing.Point(407, 198); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(374, 331); + this.groupBox1.TabIndex = 11; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "HTML Generator"; + // + // openHtmlOption + // + this.openHtmlOption.AutoSize = true; + this.openHtmlOption.Checked = true; + this.openHtmlOption.CheckState = System.Windows.Forms.CheckState.Checked; + this.openHtmlOption.Location = new System.Drawing.Point(22, 240); + this.openHtmlOption.Name = "openHtmlOption"; + this.openHtmlOption.Size = new System.Drawing.Size(154, 17); + this.openHtmlOption.TabIndex = 12; + this.openHtmlOption.Text = "Open HTML after generate"; + this.openHtmlOption.UseVisualStyleBackColor = true; + // + // genHtmlButton + // + this.genHtmlButton.Location = new System.Drawing.Point(22, 266); + this.genHtmlButton.Name = "genHtmlButton"; + this.genHtmlButton.Size = new System.Drawing.Size(337, 43); + this.genHtmlButton.TabIndex = 11; + this.genHtmlButton.Text = "Generate HTML"; + this.genHtmlButton.UseVisualStyleBackColor = true; + this.genHtmlButton.Click += new System.EventHandler(this.genHtmlButton_Click); + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(19, 138); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(349, 52); + this.label13.TabIndex = 10; + this.label13.Text = resources.GetString("label13.Text"); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(18, 114); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(150, 13); + this.label12.TabIndex = 10; + this.label12.Text = "Image zoom vs page width (%)"; + // + // readStyleSelect + // + this.readStyleSelect.FormattingEnabled = true; + this.readStyleSelect.Items.AddRange(new object[] { + "Right to Left (Manga)", + "Left to Right (Comic)"}); + this.readStyleSelect.Location = new System.Drawing.Point(21, 204); + this.readStyleSelect.Name = "readStyleSelect"; + this.readStyleSelect.Size = new System.Drawing.Size(337, 21); + this.readStyleSelect.TabIndex = 10; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(19, 22); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(310, 78); + this.label11.TabIndex = 0; + this.label11.Text = resources.GetString("label11.Text"); + // + // pageZoomPercent + // + this.pageZoomPercent.Increment = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.pageZoomPercent.Location = new System.Drawing.Point(174, 112); + this.pageZoomPercent.Minimum = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.pageZoomPercent.Name = "pageZoomPercent"; + this.pageZoomPercent.Size = new System.Drawing.Size(74, 20); + this.pageZoomPercent.TabIndex = 9; + this.pageZoomPercent.Value = new decimal(new int[] { + 45, + 0, + 0, + 0}); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(15, 41); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(241, 13); + this.linkLabel1.TabIndex = 12; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "https://github.com/wappenull/DLSiteDumperGUI"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OpenUrlFromLinkLabel); + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(13, 478); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(274, 13); + this.linkLabel2.TabIndex = 12; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "https://forums.e-hentai.org/index.php?showtopic=92167"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OpenUrlFromLinkLabel); + // + // linkLabel3 + // + this.linkLabel3.AutoSize = true; + this.linkLabel3.Location = new System.Drawing.Point(15, 77); + this.linkLabel3.Name = "linkLabel3"; + this.linkLabel3.Size = new System.Drawing.Size(200, 13); + this.linkLabel3.TabIndex = 12; + this.linkLabel3.TabStop = true; + this.linkLabel3.Text = "https://github.com/typcn/DLSiteDumper"; + this.linkLabel3.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OpenUrlFromLinkLabel); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.linkLabel4); + this.groupBox2.Controls.Add(this.linkLabel3); + this.groupBox2.Controls.Add(this.label14); + this.groupBox2.Controls.Add(this.label15); + this.groupBox2.Controls.Add(this.label7); + this.groupBox2.Controls.Add(this.linkLabel1); + this.groupBox2.Location = new System.Drawing.Point(407, 13); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(374, 177); + this.groupBox2.TabIndex = 13; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Credit and acknowledgement"; + // + // linkLabel4 + // + this.linkLabel4.AutoSize = true; + this.linkLabel4.Location = new System.Drawing.Point(15, 114); + this.linkLabel4.Name = "linkLabel4"; + this.linkLabel4.Size = new System.Drawing.Size(203, 13); + this.linkLabel4.TabIndex = 12; + this.linkLabel4.TabStop = true; + this.linkLabel4.Text = "https://github.com/fuzetsu/manga-loader"; + this.linkLabel4.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OpenUrlFromLinkLabel); + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(15, 138); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(325, 26); + this.label14.TabIndex = 6; + this.label14.Text = "This GUI is designed by programmer who has no sense with UI/UX.\r\nPlease dont hate" + + " me."; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(15, 99); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(167, 13); + this.label15.TabIndex = 6; + this.label15.Text = "HTML reader template stolen from"; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.browseButton); + this.groupBox3.Controls.Add(this.linkLabel2); + this.groupBox3.Controls.Add(this.imageExtSelect); + this.groupBox3.Controls.Add(this.betweenPageDelay); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Controls.Add(this.startPageInput); + this.groupBox3.Controls.Add(this.effectivePathTextBox); + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.savePathTextBox); + this.groupBox3.Controls.Add(this.pidTextBox); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.label6); + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Controls.Add(this.label5); + this.groupBox3.Controls.Add(this.testButton); + this.groupBox3.Controls.Add(this.autoDetectPidButton); + this.groupBox3.Controls.Add(this.rip); + this.groupBox3.Controls.Add(this.label10); + this.groupBox3.Location = new System.Drawing.Point(16, 14); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(374, 514); + this.groupBox3.TabIndex = 14; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Dumper"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 540); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.Text = "DLSite viewer dumper | by K.G. & typcn | C#GUI by Wappen | V1.0"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed); + this.Load += new System.EventHandler(this.Form1_Load); + ((System.ComponentModel.ISupportInitialize)(this.startPageInput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.betweenPageDelay)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pageZoomPercent)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button rip; + private System.Windows.Forms.Button autoDetectPidButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox pidTextBox; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.NumericUpDown startPageInput; + private System.Windows.Forms.TextBox savePathTextBox; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button browseButton; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox effectivePathTextBox; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.ComboBox imageExtSelect; + private System.Windows.Forms.Button testButton; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.NumericUpDown betweenPageDelay; + private System.ComponentModel.BackgroundWorker backgroundWorker1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.ComboBox readStyleSelect; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.NumericUpDown pageZoomPercent; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.LinkLabel linkLabel3; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.CheckBox openHtmlOption; + private System.Windows.Forms.Button genHtmlButton; + private System.Windows.Forms.LinkLabel linkLabel4; + private System.Windows.Forms.Label label15; + } +} + diff --git a/DLSiteDumperCS/MainForm.cs b/DLSiteDumperCS/MainForm.cs new file mode 100644 index 0000000..a1e6747 --- /dev/null +++ b/DLSiteDumperCS/MainForm.cs @@ -0,0 +1,328 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.IO; + +namespace DLSiteDumperCS +{ + public partial class MainForm : Form + { + const string DefaultExt = "png"; + + ViewerDumper m_Vd; + string m_UsingImageExt; + + public MainForm( ) + { + InitializeComponent( ); + + backgroundWorker1.DoWork += BackgroundWorker1_DoWork; + backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted; + backgroundWorker1.ProgressChanged += BackgroundWorker1_ProgressChanged; + } + + private void Form1_Load( object sender, EventArgs e ) + { + // Auto detect PID on load + int foundPid = _AutoDetectProcess( ); + pidTextBox.Text = foundPid.ToString( ); + + // Select PNG on start + imageExtSelect.SelectedIndex = imageExtSelect.FindString( DefaultExt ); + m_UsingImageExt = DefaultExt; + + // Auto pick some save path + string initialSave = Environment.GetFolderPath( Environment.SpecialFolder.MyDocuments ); + initialSave = Path.Combine( initialSave, "My Fap Cave" ); + savePathTextBox.Text = initialSave; + _UpdateEffectivePath( ); + + // Default options for HTML generation + readStyleSelect.SelectedIndex = 0; + } + + private void MainForm_FormClosed( object sender, FormClosedEventArgs e ) + { + if( m_Vd != null ) + { + m_Vd.Dispose( ); + m_Vd = null; + } + } + + private void OnRipClick( object sender, EventArgs e ) + { + Dump( true ); + } + + private void OnTestButton( object sender, EventArgs e ) + { + Dump( false ); + } + + void Dump( bool isBatch ) + { + if( m_Vd == null ) + m_Vd = new ViewerDumper( this ); + + if( !int.TryParse( pidTextBox.Text, out int pid ) || pid == 0 ) + { + ErrorMsg( "Hey, type in valid value into PID box, seriously!" ); + return; + } + + _UpdateEffectivePath( ); + // Check if file already exists + if( File.Exists( effectivePathTextBox.Text ) ) + { + InfoMsg( $"Looks like there is file exists at\n{effectivePathTextBox.Text}\nPlease fix this manually, for safety reason (loss of data), program will not continue." ); + return; + } + + // Try create directory once + if( !Directory.Exists( savePathTextBox.Text ) ) + Directory.CreateDirectory( savePathTextBox.Text ); + + if( !Directory.Exists( savePathTextBox.Text ) ) + { + ErrorMsg( $"Save path \n{savePathTextBox.Text}\nis invalid" ); + return; + } + + // Resetup if PID changed + if( m_Vd.TargetPid != pid ) + m_Vd.Setup( pid ); + + m_Vd.BasePageOffset = (int)startPageInput.Value; + m_Vd.BaseSavePath = savePathTextBox.Text; + m_Vd.TargetImageExt = m_UsingImageExt; + m_Vd.BetweenPageDelayMs = (int)betweenPageDelay.Value; + + if( !m_Vd.IsReady ) + { + ErrorMsg( $"Cannot open DLSiteViewer process ID {pid}" ); + return; + } + + if( m_Popup == null ) + m_Popup = new WorkingDialog( this ); + + backgroundWorker1.RunWorkerAsync( isBatch ); + m_Popup.ShowDialog( this ); // ShowDialog is blocking call + } + + public bool AskYesNo( string v ) + { + return MessageBox.Show( this, v, "Make decision wisely.", MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes; + } + + public void ErrorMsg( string v ) + { + MessageBox.Show( this, v, "Are you JOKING with me?", MessageBoxButtons.OK, MessageBoxIcon.Error ); + } + + public void InfoMsg( string v ) + { + MessageBox.Show( this, v, "FYI", MessageBoxButtons.OK, MessageBoxIcon.Information ); + } + + const string DetectingProcessName = "DLsiteViewer"; + int _AutoDetectProcess( ) + { + Process[] pcs = Process.GetProcessesByName( DetectingProcessName ); + if( pcs.Length > 0 ) + return pcs[0].Id; + return 0; + } + + private void autoDetectPidButton_Click( object sender, EventArgs e ) + { + int foundPid = _AutoDetectProcess( ); + pidTextBox.Text = foundPid.ToString( ); + + if( foundPid == 0 ) + { + MessageBox.Show( this, $"I cannot find any process named {DetectingProcessName} running.\n" + + "Also maybe due to lacking priviledge or virus scanner preventing.\n" + + "If you think you are a wizkid, you could type in PID manually.", "DARN", MessageBoxButtons.OK, MessageBoxIcon.Warning ); + } + } + + private void browseButton_Click( object sender, EventArgs e ) + { + string forecastFilename = ViewerDumper.GetFileNameForPage( (int)startPageInput.Value, m_UsingImageExt ); + + var sfd = new SaveFileDialog( ); + sfd.InitialDirectory = savePathTextBox.Text; + sfd.FileName = forecastFilename; + sfd.DefaultExt = m_UsingImageExt; + sfd.Filter = "Image file|*.*"; + sfd.ValidateNames = false; + sfd.CheckFileExists = false; + sfd.CheckPathExists = true; + sfd.RestoreDirectory = true; + + if( sfd.ShowDialog( ) == DialogResult.OK ) + { + savePathTextBox.Text = Path.GetDirectoryName( sfd.FileName ); + _UpdateEffectivePath( ); + } + } + + private void savePathTextBox_TextChanged( object sender, EventArgs e ) + { + _UpdateEffectivePath( ); + } + + private void imageExtSelect_SelectedIndexChanged( object sender, EventArgs e ) + { + m_UsingImageExt = imageExtSelect.Text; + _UpdateEffectivePath( ); + } + + private void startPageInput_ValueChanged( object sender, EventArgs e ) + { + _UpdateEffectivePath( ); + } + + private void _UpdateEffectivePath( ) + { + effectivePathTextBox.Text = Path.Combine( savePathTextBox.Text, ViewerDumper.GetFileNameForPage( (int)startPageInput.Value, m_UsingImageExt ) ); + } + + private void OpenUrlFromLinkLabel( object sender, LinkLabelLinkClickedEventArgs e ) + { + LinkLabel lb = (LinkLabel)sender; + string url; + if( e.Link.LinkData != null ) + url = e.Link.LinkData.ToString( ); + else + url = lb.Text; + + if( !url.Contains( "://" ) ) + url = "https://" + url; + + var si = new ProcessStartInfo(url); + Process.Start( si ); + lb.LinkVisited = true; + } + + /* Calls for progress popup //////////////////////////////*/ + + WorkingDialog m_Popup; + + public void SetStatusText( string txt ) + { + // Forward to text box + if( m_Popup != null ) + m_Popup.SetStatusText( txt ); + } + + public void NotifyAbort( ) + { + if( backgroundWorker1.IsBusy ) + backgroundWorker1.CancelAsync( ); + } + + /* Background worker //////////////////////////*/ + + private void BackgroundWorker1_DoWork( object sender, DoWorkEventArgs e ) + { + bool isBatch = (bool)e.Argument; + + BackgroundWorker worker = sender as BackgroundWorker; + +#if false // my BackgroundWorker test + for( int i=0 ; i<100 ; i++ ) + { + worker.ReportProgress( i, "Doing something " + i ); + System.Threading.Thread.Sleep( 100 ); + + if( worker.CancellationPending ) + { + e.Cancel = true; + break; + } + } +#endif + + m_Vd.SetupBackgroundWorker( worker, e ); + if( isBatch ) + m_Vd.DumpBatch( ); + else + m_Vd.DumpOne( ); + } + + private void BackgroundWorker1_ProgressChanged( object sender, ProgressChangedEventArgs e ) + { + SetStatusText( (string)e.UserState ); + } + + private void BackgroundWorker1_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) + { + m_Popup.Close( ); + + if( e.Cancelled ) + InfoMsg( "User cancelled operation. Are you joking to me?" ); + else + { + string s = e.Result as string; + InfoMsg( s + "\nYou can also try using HTML generator to make a viewer HTML." ); + } + } + + /* HTML gen service ///////////////////////////////////////*/ + + private void genHtmlButton_Click( object sender, EventArgs e ) + { + // Gather all files in that folder + if( !Directory.Exists( savePathTextBox.Text ) ) + { + ErrorMsg( $"Cannot open {savePathTextBox.Text}" ); + return; + } + + List images = new List( ); + List extensions = new List( ){ ".jpg", ".png" }; + foreach( string file in Directory.EnumerateFiles( savePathTextBox.Text, "*.*", SearchOption.TopDirectoryOnly ) ) + { + if( extensions.Contains( Path.GetExtension( file ) ) ) + images.Add( Path.GetFileName( file ) ); // Strip to only filename + } + + ExplorerLikeFilenameComparer cmp = new ExplorerLikeFilenameComparer( ); + images.Sort( cmp ); // Hopefully in ascending order + + var hg = new HtmlImageReaderGenerator( ); + hg.FileList = images.ToArray( ); + hg.TemplateData = Resources.HtmlTemplate; + hg.IsRightToLeft = readStyleSelect.SelectedIndex == 0; + hg.OutputPath = Path.Combine( savePathTextBox.Text, "_reader.html" ); + hg.ImageZoomPercent = (int)pageZoomPercent.Value; + + bool succeed = hg.Generate( ); + if( !succeed ) + ErrorMsg( $"Cannot write output to {hg.OutputPath}" ); + else + InfoMsg( $"HTML reader created at {hg.OutputPath}" ); + + if( succeed && openHtmlOption.Checked ) + { + Process myProcess = new Process(); + myProcess.StartInfo.UseShellExecute = true; + myProcess.StartInfo.FileName = hg.OutputPath; + myProcess.StartInfo.CreateNoWindow = true; + myProcess.Start( ); + } + } + + + } + +} diff --git a/DLSiteDumperCS/MainForm.resx b/DLSiteDumperCS/MainForm.resx new file mode 100644 index 0000000..b0377e2 --- /dev/null +++ b/DLSiteDumperCS/MainForm.resx @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Ripper will start capturing from current page you left on viewer. +This is handy for resuming from crash. +But it does not know what page number you are on viewer. +So adjust starting page number in the box below to get the right filename. + + + 17, 17 + + + If image zoom is 45% or below, you get multiple images per row. +- 45% is recommended for dual page view +- 30% for 3 pages per row +Specify that you want Left2Right (Comic) reading or Right2Left (Manga)? + + + This will create a reader HTML inside your specified folder. +Here is what it will do: +- It will search for all image files (png/jpg) in 'save location' folder. +- Sort it by name so that it goes 000 ... 001 ...002 +- Generate a reader html named "_reader.html" +(under score for filename to appear first) + + \ No newline at end of file diff --git a/DLSiteDumperCS/Program.cs b/DLSiteDumperCS/Program.cs new file mode 100644 index 0000000..3512584 --- /dev/null +++ b/DLSiteDumperCS/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace DLSiteDumperCS +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main( ) + { + Application.EnableVisualStyles( ); + Application.SetCompatibleTextRenderingDefault( false ); + Application.Run( new MainForm( ) ); + } + } +} diff --git a/DLSiteDumperCS/Properties/AssemblyInfo.cs b/DLSiteDumperCS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5645abe --- /dev/null +++ b/DLSiteDumperCS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "DLSiteDumperCS" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "" )] +[assembly: AssemblyProduct( "DLSiteDumperCS" )] +[assembly: AssemblyCopyright( "Copyright © 2021" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "833a0652-30ae-4036-8f2d-fa1ce33c32d9" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/DLSiteDumperCS/Properties/Resources.Designer.cs b/DLSiteDumperCS/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8a6bfb0 --- /dev/null +++ b/DLSiteDumperCS/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +namespace DLSiteDumperCS.Properties +{ + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0" )] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute( )] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute( )] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + internal Resources( ) + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if( (resourceMan == null) ) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DLSiteDumperCS.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/DLSiteDumperCS/Properties/Resources.resx b/DLSiteDumperCS/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/DLSiteDumperCS/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DLSiteDumperCS/Properties/Settings.Designer.cs b/DLSiteDumperCS/Properties/Settings.Designer.cs new file mode 100644 index 0000000..32c981c --- /dev/null +++ b/DLSiteDumperCS/Properties/Settings.Designer.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + + +namespace DLSiteDumperCS.Properties +{ + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute( )] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0" )] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/DLSiteDumperCS/Properties/Settings.settings b/DLSiteDumperCS/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/DLSiteDumperCS/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/DLSiteDumperCS/Resources.Designer.cs b/DLSiteDumperCS/Resources.Designer.cs new file mode 100644 index 0000000..a796bd0 --- /dev/null +++ b/DLSiteDumperCS/Resources.Designer.cs @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DLSiteDumperCS { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DLSiteDumperCS.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + public static string HtmlTemplate { + get { + return ResourceManager.GetString("HtmlTemplate", resourceCulture); + } + } + } +} diff --git a/DLSiteDumperCS/Resources.resx b/DLSiteDumperCS/Resources.resx new file mode 100644 index 0000000..a56e514 --- /dev/null +++ b/DLSiteDumperCS/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Resources\HtmlTemplate.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + \ No newline at end of file diff --git a/DLSiteDumperCS/Resources/HtmlTemplate.txt b/DLSiteDumperCS/Resources/HtmlTemplate.txt new file mode 100644 index 0000000..e312678 --- /dev/null +++ b/DLSiteDumperCS/Resources/HtmlTemplate.txt @@ -0,0 +1,140 @@ + + + + + + Viewr Generator + + + + + + +
+ Generated by Wappen DLSiteViewer dumper. WARNING: This tool is intended for convenient viewing for legitimate owner of content, if you do not own this comic/manga content, please consider buy it on DLSite. +
+
+ /*CONTENT*/ +
+
+ Generated by Wappen DLSiteViewer dumper. WARNING: This tool is intended for convenient viewing for legitimate owner of content, if you do not own this comic/manga content, please consider buy it on DLSite. +
+ + + \ No newline at end of file diff --git a/DLSiteDumperCS/User32.cs b/DLSiteDumperCS/User32.cs new file mode 100644 index 0000000..38eb695 --- /dev/null +++ b/DLSiteDumperCS/User32.cs @@ -0,0 +1,1388 @@ + +using System; +using System.Diagnostics; +using System.Drawing; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +// https://github.com/SonyWWS/ATF/blob/master/Framework/Atf.Gui/User32.cs +//Copyright © 2014 Sony Computer Entertainment America LLC. See License.txt. + +/// +/// Interop for structures and functions in user32.dll +public static class User32 +{ + // Windows Message Constants WM_XXXX, etc., from winuser.h + public const int WM_NULL = 0x0000; + public const int WM_CREATE = 0x0001; + public const int WM_DESTROY = 0x0002; + public const int WM_MOVE = 0x0003; + public const int WM_SIZE = 0x0005; + + public const int WM_ACTIVATE = 0x0006; + + //WM_ACTIVATE state values + public const int WA_INACTIVE = 0; + public const int WA_ACTIVE = 1; + public const int WA_CLICKACTIVE = 2; + + public const int WM_SETFOCUS = 0x0007; + public const int WM_KILLFOCUS = 0x0008; + public const int WM_ENABLE = 0x000A; + public const int WM_SETREDRAW = 0x000B; + public const int WM_SETTEXT = 0x000C; + public const int WM_GETTEXT = 0x000D; + public const int WM_GETTEXTLENGTH = 0x000E; + public const int WM_PAINT = 0x000F; + public const int WM_CLOSE = 0x0010; + public const int WM_ERASEBKGND = 0x0014; + public const int WM_SETCURSOR = 32; + + public const int WM_GETMINMAXINFO = 0x0024; + public const int WM_HELP = 0x0053; + public const int WM_NCHITTEST = 0x0084; + public const int WM_NCPAINT = 0x0085; + public const int WM_NCLBUTTONDOWN = 0x00A1; + public const int WM_NCLBUTTONUP = 0x00A2; + public const int WM_KEYDOWN = 0x0100; + public const int WM_SYSKEYDOWN = 0x0104; + public const int WM_INITDIALOG = 0x110; + public const int WM_COMMAND = 0x0111; + public const int WM_SYSCOMMAND = 0x0112; + public const int WM_HSCROLL = 0x114; + public const int WM_VSCROLL = 0x115; + public const int WM_UPDATEUISTATE = 0x0128; + public const int WM_SIZING = 0x0214; + public const int WM_LBUTTONDOWN = 0x0201; + public const int WM_LBUTTONUP = 0x0202; + public const int WM_LBUTTONDBLCLK = 0x0203; + public const int WM_MOUSEMOVE = 0x0200; + public const int WM_MOUSEWHEEL = 0x020A; + public const int WM_CUT = 0x0300; + public const int WM_COPY = 0x0301; + public const int WM_PASTE = 0x0302; + public const int WM_CLEAR = 0x0303; + public const int WM_UNDO = 0x0304; + public const int WM_USER = 0x0400; + public const int WM_REFLECT = WM_USER + 0x1C00; + public const int WM_NOTIFY = 0x004E; + + // Combo Box return Values + public const int CB_OKAY = 0; + public const int CB_ERR = -1; + public const int CB_ERRSPACE = -2; + + // Combo Box Notification Codes + public const int CBN_ERRSPACE = -1; + public const int CBN_SELCHANGE = 1; + public const int CBN_DBLCLK = 2; + public const int CBN_SETFOCUS = 3; + public const int CBN_KILLFOCUS = 4; + public const int CBN_EDITCHANGE = 5; + public const int CBN_EDITUPDATE = 6; + public const int CBN_DROPDOWN = 7; + public const int CBN_CLOSEUP = 8; + public const int CBN_SELENDOK = 9; + public const int CBN_SELENDCANCEL = 10; + + // Combo Box styles + public const int CBS_SIMPLE = 0x0001; + public const int CBS_DROPDOWN = 0x0002; + public const int CBS_DROPDOWNLIST = 0x0003; + public const int CBS_OWNERDRAWFIXED = 0x0010; + public const int CBS_OWNERDRAWVARIABLE = 0x0020; + public const int CBS_AUTOHSCROLL = 0x0040; + public const int CBS_OEMCONVERT = 0x0080; + public const int CBS_SORT = 0x0100; + public const int CBS_HASSTRINGS = 0x0200; + public const int CBS_NOINTEGRALHEIGHT = 0x0400; + public const int CBS_DISABLENOSCROLL = 0x0800; + public const int CBS_UPPERCASE = 0x2000; + public const int CBS_LOWERCASE = 0x4000; + + // Combo Box messages + public const int CB_GETEDITSEL = 0x0140; + public const int CB_LIMITTEXT = 0x0141; + public const int CB_SETEDITSEL = 0x0142; + public const int CB_ADDSTRING = 0x0143; + public const int CB_DELETESTRING = 0x0144; + public const int CB_DIR = 0x0145; + public const int CB_GETCOUNT = 0x0146; + public const int CB_GETCURSEL = 0x0147; + public const int CB_GETLBTEXT = 0x0148; + public const int CB_GETLBTEXTLEN = 0x0149; + public const int CB_INSERTSTRING = 0x014A; + public const int CB_RESETCONTENT = 0x014B; + public const int CB_FINDSTRING = 0x014C; + public const int CB_SELECTSTRING = 0x014D; + public const int CB_SETCURSEL = 0x014E; + public const int CB_SHOWDROPDOWN = 0x014F; + public const int CB_GETITEMDATA = 0x0150; + public const int CB_SETITEMDATA = 0x0151; + public const int CB_GETDROPPEDCONTROLRECT = 0x0152; + public const int CB_SETITEMHEIGHT = 0x0153; + public const int CB_GETITEMHEIGHT = 0x0154; + public const int CB_SETEXTENDEDUI = 0x0155; + public const int CB_GETEXTENDEDUI = 0x0156; + public const int CB_GETDROPPEDSTATE = 0x0157; + public const int CB_FINDSTRINGEXACT = 0x0158; + public const int CB_SETLOCALE = 0x0159; + public const int CB_GETLOCALE = 0x015A; + public const int CB_GETTOPINDEX = 0x015b; + public const int CB_SETTOPINDEX = 0x015c; + public const int CB_GETHORIZONTALEXTENT = 0x015d; + public const int CB_SETHORIZONTALEXTENT = 0x015e; + public const int CB_GETDROPPEDWIDTH = 0x015f; + public const int CB_SETDROPPEDWIDTH = 0x0160; + public const int CB_INITSTORAGE = 0x0161; + public const int CB_MULTIPLEADDSTRING = 0x0163; + public const int CB_GETCOMBOBOXINFO = 0x0164; + public const int CB_MSGMAX = 0x0165; + + // ListView messages + public const int LVM_FIRST = 0x1000; + public const int HDM_FIRST = 0x1200; + public const int HDM_SETFOCUSEDITEM = HDM_FIRST + 28; + + //parameters for ListView headers + public const int HDI_FORMAT = 0x0004; + public const int HDF_LEFT = 0x0000; + public const int HDF_STRING = 0x4000; + public const int HDF_SORTUP = 0x0400; + public const int HDF_SORTDOWN = 0x0200; + public const int LVM_GETHEADER = 0x1000 + 31; // LVM_FIRST + 31 + public const int HDM_GETITEM = 0x1200 + 11; // HDM_FIRST + 11 + public const int HDM_SETITEM = 0x1200 + 12; + + /// + /// Contains information about an item in a header control + /// https://msdn.microsoft.com/en-us/library/windows/desktop/bb775247(v=vs.85).aspx + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )] + public struct HDITEM + { + public uint mask; + public int cxy; + public String pszText; //works for sending strings, but not for receiving. todo: use StringBuilder? + public IntPtr hbm; + public int cchTextMax; + public int fmt; + public IntPtr lParam; + public int iImage; + public int iOrder; + public uint type; + public IntPtr pvFilter; // this is void* + public uint state; + } + + + // Button control styles, messages and notifications + public const int BS_PUSHBUTTON = 0x00000000; + public const int BS_DEFPUSHBUTTON = 0x00000001; + public const int BS_CHECKBOX = 0x00000002; + public const int BS_AUTOCHECKBOX = 0x00000003; + public const int BS_RADIOBUTTON = 0x00000004; + public const int BS_3STATE = 0x00000005; + public const int BS_AUTO3STATE = 0x00000006; + public const int BS_GROUPBOX = 0x00000007; + public const int BS_AUTORADIOBUTTON = 0x00000009; + public const int BS_OWNERDRAW = 0x0000000B; + public const int BS_LEFTTEXT = 0x00000020; + public const int BS_TEXT = 0x00000000; + public const int BS_LEFT = 0x00000100; + public const int BS_RIGHT = 0x00000200; + public const int BS_CENTER = 0x00000300; + public const int BS_TOP = 0x00000400; + public const int BS_BOTTOM = 0x00000800; + public const int BS_VCENTER = 0x00000C00; + public const int BS_PUSHLIKE = 0x00001000; + public const int BS_MULTILINE = 0x00002000; + public const int BS_NOTIFY = 0x00004000; + public const int BS_RIGHTBUTTON = BS_LEFTTEXT; + + public const int BN_CLICKED = 0; + public const int BN_PAINT = 1; + public const int BN_DBLCLK = 5; + public const int BN_SETFOCUS = 6; + public const int BN_KILLFOCUS = 7; + + public const int QS_MOUSEMOVE = 0x0002; + public const int QS_MOUSEBUTTON = 0x0004; + public const int QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON; + public const int QS_KEY = 0x0001; + public const int QS_RAWINPUT = 0x0400; + + public const int PM_QS_INPUT = (QS_MOUSE | QS_KEY | QS_RAWINPUT) << 16; + public const int PM_NOREMOVE = 0x0000; + public const int PM_REMOVE = 0x0001; + public const int PM_NOYIELD = 0x0002; + + public const int TME_HOVER = 0x1; + public const int HOVER_DEFAULT = -1; //0xFFFFFFFF; + + // WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes + + public const int HTCAPTION = 0x2; + + // Class Styles Constants + + public const int CS_NOCLOSE = 0x0200; + + public const int EM_GETEVENTMASK = (WM_USER + 59); + public const int EM_SETEVENTMASK = (WM_USER + 69); + + public const int NM_FIRST = 0x0000; + + public const int HDN_FIRST = (NM_FIRST - 300); + public const int HDN_ITEMCHANGINGA = (HDN_FIRST - 0); + public const int HDN_ITEMCHANGINGW = (HDN_FIRST - 20); + public const int HDN_ITEMCHANGEDA = (HDN_FIRST - 1); + public const int HDN_ITEMCHANGEDW = (HDN_FIRST - 21); + public const int HDN_ITEMCLICKA = (HDN_FIRST - 2); + public const int HDN_ITEMCLICKW = (HDN_FIRST - 22); + public const int HDN_ITEMDBLCLICKA = (HDN_FIRST - 3); + public const int HDN_ITEMDBLCLICKW = (HDN_FIRST - 23); + public const int HDN_DIVIDERDBLCLICKA = (HDN_FIRST - 5); + public const int HDN_DIVIDERDBLCLICKW = (HDN_FIRST - 25); + public const int HDN_BEGINTRACKA = (HDN_FIRST - 6); + public const int HDN_BEGINTRACKW = (HDN_FIRST - 26); + public const int HDN_ENDTRACKA = (HDN_FIRST - 7); + public const int HDN_ENDTRACKW = (HDN_FIRST - 27); + public const int HDN_TRACKA = (HDN_FIRST - 8); + public const int HDN_TRACKW = (HDN_FIRST - 28); + public const int HDN_GETDISPINFOA = (HDN_FIRST - 9); + public const int HDN_GETDISPINFOW = (HDN_FIRST - 29); + public const int HDN_BEGINDRAG = (HDN_FIRST - 10); + public const int HDN_ENDDRAG = (HDN_FIRST - 11); + public const int HDN_FILTERCHANGE = (HDN_FIRST - 12); + public const int HDN_FILTERBTNCLICK = (HDN_FIRST - 13); + + // structs + + /// + /// POINT structure to interoperate with user32.dll + [StructLayout( LayoutKind.Sequential )] + public struct POINT + { + public int X; + public int Y; + + public POINT( int x, int y ) + { + this.X = x; + this.Y = y; + } + + public static implicit operator System.Drawing.Point( POINT p ) + { + return new System.Drawing.Point( p.X, p.Y ); + } + + public static implicit operator POINT( System.Drawing.Point p ) + { + return new POINT( p.X, p.Y ); + } + } + + /// + /// RECT structure to interoperate with user32.dll + [StructLayout( LayoutKind.Sequential )] + public struct RECT + { + public int Left, Top, Right, Bottom; + + public RECT( int left, int top, int right, int bottom ) + { + Left = left; + Top = top; + Right = right; + Bottom = bottom; + } + + public RECT( System.Drawing.Rectangle r ) : this( r.Left, r.Top, r.Right, r.Bottom ) { } + + public int X + { + get { return Left; } + set { Right -= (Left - value); Left = value; } + } + + public int Y + { + get { return Top; } + set { Bottom -= (Top - value); Top = value; } + } + + public int Height + { + get { return Bottom - Top; } + set { Bottom = value + Top; } + } + + public int Width + { + get { return Right - Left; } + set { Right = value + Left; } + } + + public System.Drawing.Point Location + { + get { return new System.Drawing.Point( Left, Top ); } + set { X = value.X; Y = value.Y; } + } + + public System.Drawing.Size Size + { + get { return new System.Drawing.Size( Width, Height ); } + set { Width = value.Width; Height = value.Height; } + } + + public static implicit operator System.Drawing.Rectangle( RECT r ) + { + return new System.Drawing.Rectangle( r.Left, r.Top, r.Width, r.Height ); + } + + public static implicit operator RECT( System.Drawing.Rectangle r ) + { + return new RECT( r ); + } + + public static bool operator ==( RECT r1, RECT r2 ) + { + return r1.Equals( r2 ); + } + + public static bool operator !=( RECT r1, RECT r2 ) + { + return !r1.Equals( r2 ); + } + + public bool Equals( RECT r ) + { + return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom; + } + + public override bool Equals( object obj ) + { + if( obj is RECT ) + return Equals( (RECT)obj ); + else if( obj is System.Drawing.Rectangle ) + return Equals( new RECT( (System.Drawing.Rectangle)obj ) ); + return false; + } + + public override int GetHashCode( ) + { + return ((System.Drawing.Rectangle)this).GetHashCode( ); + } + + public override string ToString( ) + { + return string.Format( System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom ); + } + } + + /// + /// Information about a window's maximized size and position and its minimum and maximum + /// tracking size. + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms632605%28v=vs.85%29.aspx. + [StructLayout( LayoutKind.Sequential )] + public struct MINMAXINFO + { + public POINT ptReserved; + public POINT ptMaxSize; + public POINT ptMaxPosition; + public POINT ptMinTrackSize; + public POINT ptMaxTrackSize; + } + + /// + /// Structure with information about the size and position of a window + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms632612%28v=vs.85%29.aspx. + [StructLayout( LayoutKind.Sequential )] + public struct WINDOWPOS + { + public IntPtr hwnd; + public IntPtr hwndInsertAfter; + public int x; + public int y; + public int cx; + public int cy; + public uint flags; + } + + /// + /// Message structure for Windows messages to controls and applications. Defined in winuser.h. + [StructLayout( LayoutKind.Sequential )] + public struct MSG + + { + public IntPtr hWnd; + public Int32 msg; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public POINT p; + } + + /// + /// TRACKMOUSEEVENT structure to interoperate with user32.dll + [StructLayout( LayoutKind.Sequential )] + public struct TRACKMOUSEEVENT + { + public int cbSize; + public int dwFlags; + public IntPtr hwndTrack; + public int dwHoverTime; + public TRACKMOUSEEVENT( IntPtr hWnd ) + { + cbSize = Marshal.SizeOf( typeof( TRACKMOUSEEVENT ) ); + hwndTrack = hWnd; + dwHoverTime = HOVER_DEFAULT; + dwFlags = TME_HOVER; + } + } + + /// + /// NMHDR structure to interoperate with user32.dll + [StructLayout( LayoutKind.Sequential )] + public struct NMHDR + { + public IntPtr hwndFrom; + public IntPtr idFrom; + public int code; + } + + /// + /// Sends specified message to a window or windows + /// Handle to the window + /// Message to be sent + /// Additional message-specific information + /// Additional message-specific information + /// Specifies result of message processing, depending on message sent + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern IntPtr SendMessage( IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam ); + + /// + /// Sends specified message to a header control. A header control is a window that is usually positioned + /// above columns of text or numbers. It contains a title for each column, and it can be divided into parts. + /// Handle to the header control + /// User32.HDM_GETITEM or User32.HDM_SETITEM + /// Additional message-specific information + /// HDITEM object + /// Specifies result of message processing, depending on message sent + /// For details on the Win32 SendMessage: + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx + /// For HDM_GETITEM: https://msdn.microsoft.com/en-us/library/windows/desktop/bb775335(v=vs.85).aspx + /// For HDM_SETITEM: https://msdn.microsoft.com/en-us/library/windows/desktop/bb775367(v=vs.85).aspx + [DllImport( DllName, EntryPoint = "SendMessage" )] + public static extern IntPtr SendMessageITEM( IntPtr handle, Int32 msg, IntPtr wParam, ref HDITEM lParam ); + + [DllImport( "user32.dll" )] + public static extern bool PostMessage( IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam ); + + /// + /// Retrieves handle to window that has the keyboard focus + /// Handle to window + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms646294%28v=vs.85%29.aspx + [DllImport( DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi )] + public static extern IntPtr GetFocus( ); + + /// + /// Retrieves handle to the given window's parent + /// Handle to the parent window + /// For details, see https://msdn.microsoft.com/en-us/library/windows/desktop/ms633510(v=vs.85).aspx + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern IntPtr GetParent( IntPtr hWnd ); + + /// + /// Provides access to function required to delete handle. This method is used internally + /// and is not required to be called separately. + /// Pointer to icon handle + /// Zero iff error occurred + [DllImport( DllName )] + public static extern int DestroyIcon( IntPtr hIcon ); + + /// + /// Loads the icon with the given name + /// Current instance + /// Icon name + /// Handle to icon with the given name + [DllImport( DllName )] + public static extern IntPtr LoadIcon( IntPtr hInstance, IntPtr iconName ); + + /// + /// Gets the scroll bar position for a given control + /// Control's handle + /// Orientation + /// Scroll bar position + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern int GetScrollPos( IntPtr hWnd, int nBar ); + + // ShowWindow Constants + + public const int SW_HIDE = 0; + public const int SW_SHOWNORMAL = 1; + public const int SW_NORMAL = 1; + public const int SW_SHOWMINIMIZED = 2; + public const int SW_SHOWMAXIMIZED = 3; + public const int SW_MAXIMIZE = 3; + public const int SW_SHOWNOACTIVATE = 4; + public const int SW_SHOW = 5; + public const int SW_MINIMIZE = 6; + public const int SW_SHOWMINNOACTIVE = 7; + public const int SW_SHOWNA = 8; + public const int SW_RESTORE = 9; + public const int SW_SHOWDEFAULT = 10; + public const int SW_FORCEMINIMIZE = 11; + public const int SW_MAX = 11; + + /// + /// Returns the high-order word (highest 16 bits) of int + /// Word whose highest 16 bits are obtained + /// Highest 16 bits of word + public static int HIWORD( int n ) + { + return (n >> 16) & 0xffff; + } + + /// + /// Returns the high-order word (highest 16 bits) of int + /// Pointer to word whose highest 16 bits are obtained + /// Highest 16 bits of word + public static int HIWORD( IntPtr n ) + { + return HIWORD( unchecked((int)(long)n) ); + } + + /// + /// Returns the low-order word (lowest 16 bits) of int + /// Word whose lowest 16 bits are obtained + /// Lowest 16 bits of word + public static int LOWORD( int n ) + { + return n & 0xffff; + } + + /// + /// Returns the low-order word (lowest 16 bits) of int + /// Pointer to word whose lowest 16 bits are obtained + /// Lowest 16 bits of word + public static int LOWORD( IntPtr n ) + { + return LOWORD( unchecked((int)(long)n) ); + } + + /// + /// Sets window's show state + /// Window HWND + /// Constant indicating how window is to be shown + /// Zero iff window was previously hidden; non-zero otherwise + [DllImport( DllName )] + public static extern bool ShowWindow( IntPtr hWnd, int nCmdShow ); + + /// + /// Brings window to foreground + /// Handle to window + /// Zero iff window was not brought to foreground + [DllImport( DllName )] + public static extern bool SetForegroundWindow( IntPtr hWnd ); + + /// + /// Tests if a window is minimized (iconic) + /// Handle to window + /// Zero iff window not iconic + [DllImport( DllName )] + public static extern bool IsIconic( IntPtr hWnd ); + + /// + /// Gets handle to window representing desktop + /// Handle to window representing desktop + [DllImport( DllName )] + public static extern IntPtr GetDesktopWindow( ); + + /// + /// Gets device context for client area of specified window + /// Window handle + /// Window's device context + [DllImport( DllName, EntryPoint = "GetDC" )] + public static extern IntPtr GetDC( IntPtr hwnd ); + + /// + /// Gets window's device context + /// Window handle + /// Window's device context + [DllImport( DllName )] + public static extern IntPtr GetWindowDC( IntPtr hWnd ); + + /// + /// Releases window's device context + /// Window handle + /// Device context to release + /// Zero if device context not released; 1 if device context released + [DllImport( DllName )] + public static extern IntPtr ReleaseDC( IntPtr hWnd, IntPtr hDC ); + + /// + /// Gets window's rectangle + /// Window handle + /// Rectangle obtained by function + /// Zero iff failed to get rectangle + [DllImport( DllName )] + public static extern IntPtr GetWindowRect( IntPtr hWnd, ref RECT rect ); + + /// + /// Gets window's client area rectangle + /// Window handle + /// Rectangle obtained by function + /// Zero iff failed to get rectangle + [DllImport( DllName, CharSet = CharSet.Unicode, ExactSpelling = true )] + public static extern bool GetClientRect( IntPtr hWnd, ref Rectangle r ); + + /// + /// Copies a visual window into the specified device context + /// A handle to the window that will be copied + /// A handle to the device context + /// The drawing options. PW_CLIENTONLY to copy client area only; otherwise copy entire window. + /// Zero iff not successful + [DllImport( DllName )] + public static extern bool PrintWindow( IntPtr hWnd, IntPtr hdcBlt, int nFlags ); + + /// + /// Copies the text of the specified window's title bar + /// (if it has one) into a buffer. If the specified window is a control, the text of + /// the control is copied. However, GetWindowText cannot retrieve the text of a + /// control in another application. + /// Handle to window + /// Pointer to area that receives text + /// Maximum number of characters to copy, including terminating NULL character + /// If the function succeeds, the return value is the length, in characters, + /// of the copied string, not including the terminating NULL character. If the window + /// has no title bar or text, if the title bar is empty, or if the window or control + /// handle is invalid, the return value is zero. To get extended error information, + /// call GetLastError. + [DllImport( DllName, CharSet = CharSet.Unicode, SetLastError = true )] + public static extern int GetWindowText( IntPtr hWnd, [Out, MarshalAs( UnmanagedType.LPTStr )] StringBuilder lpString, int nMaxCount ); + + /// + /// Retrieves a handle to the window that contains the specified point. + /// The point to be checked + /// The return value is a handle to the window that contains the point. + /// If no window exists at the given point, the return value is IntPtr.Zero. + /// If the point is over a static text control, the return value is a handle to + /// the window under the static text control. + [DllImport( DllName )] + public static extern IntPtr WindowFromPoint( Point point ); + + /// + /// Examines messages that are in the Windows message queue for this thread + /// Pointer to area that receives message + /// Handle to window + /// Value to indicate first message to receive. + /// Set to WM_KEYFIRST (0x0100) for the first keyboard message or + /// WM_MOUSEFIRST (0x0200) for the first mouse message. + /// Value to indicate last message to receive. + /// Set to WM_KEYLAST for the last keyboard message or WM_MOUSELAST for the last mouse message. + /// Flags indicating how messages are handled. + /// Zero iff no messages are available + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern bool PeekMessage( out MSG msg, Int32 hWnd, + uint messageFilterMin, uint messageFilterMax, uint flags ); + + /// + /// Posts messages when mouse leaves or hovers over a window + /// Pointer to TRACKMOUSEEVENT structure + /// Zero iff function fails + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern bool TrackMouseEvent( ref TRACKMOUSEEVENT lpEventTrack ); + + /// + /// Waits until one or more objects are in the signaled state or timeout occurs + /// Number of object handles in pHandles + /// Array of handles for objects being monitored + /// True to wait for all objects to get signaled. False if only wait until one object is signaled; + /// in this case, the return value indicated which object was signaled + /// Time out period in milliseconds + /// Mask values that indicate what signals the function waits for + /// WAIT_FAILED iff function timed out. Otherwise, returns a value indicating what event caused the function to return, + /// such as an object being signaled. + [DllImport( DllName )] + public static extern int MsgWaitForMultipleObjects( + int nCount, // number of handles in array + int pHandles, // object-handle array + bool bWaitAll, // wait option + int dwMilliseconds, // time-out interval + int dwWakeMask // input-event type + ); + + /// + /// Retrieves the clipboard sequence number, which is incremented each time the system + /// clipboard changes. For details, see http://msdn.microsoft.com/en-us/library/ms649042(v=vs.85).aspx. + /// Clipboard sequence number + [DllImport( DllName )] + public static extern uint GetClipboardSequenceNumber( ); + + /// + /// Resumes drawing to the specified window handle + /// Handle to window + public static void StartDrawing( IntPtr hwnd ) + { + SendMessage( hwnd, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero ); + } + + /// + /// Stops drawing of the specified window handle + /// Handle to window + public static void StopDrawing( IntPtr hwnd ) + { + SendMessage( hwnd, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero ); + } + + /// + /// Helper class to do the StopDrawing/StartDrawing function pair + public class StopDrawingHelper : IDisposable + { + /// + /// Constructor + /// Handle to window + public StopDrawingHelper( IntPtr hwnd ) + { + m_hwnd = hwnd; + StopDrawing( m_hwnd ); + } + + /// + /// Dispose + void IDisposable.Dispose( ) + { + StartDrawing( m_hwnd ); + } + + private readonly IntPtr m_hwnd; + } + + + /// + /// This delegate is used with SetWindowsHookEx(). For more details, see + /// http://msdn.microsoft.com/en-us/library/ms644990. + /// The message ID depends on the HookType that was used. It will be ShellEvents + /// for WH_SHELL or it will be CbtEvents for WH_CBT, for example. If it's less than zero, then that + /// typically means that no processing should be done and the results of calling CallNextHookEx should + /// be returned. + /// Additional message-specific information + /// Additional message-specific information + /// The result of calling CallNextHookEx() is typically returned. + public delegate IntPtr WindowsHookCallback( int code, IntPtr wParam, IntPtr lParam ); + + /// + /// These are the different hook types when registering a callback with SetWindowsHookEx(). + /// For more details, see http://msdn.microsoft.com/en-us/library/ms644990. + public enum HookType + { + WH_JOURNALRECORD = 0, + WH_JOURNALPLAYBACK = 1, + WH_KEYBOARD = 2, + WH_GETMESSAGE = 3, + WH_CALLWNDPROC = 4, + WH_CBT = 5, + WH_SYSMSGFILTER = 6, + WH_MOUSE = 7, + WH_HARDWARE = 8, + WH_DEBUG = 9, + WH_SHELL = 10, + WH_FOREGROUNDIDLE = 11, + WH_CALLWNDPROCRET = 12, + WH_KEYBOARD_LL = 13, + WH_MOUSE_LL = 14 + } + + /// + /// These are the message IDs that can be passed in as the code parameter + /// of the WindowsHookCallback that was registered with HookType.WH_SHELL. + public enum ShellEvents + { + //This even only gets raised for the top-level unowned Forms, like the main form, + // not for various other floating windows Forms like open-file dialog boxes or user + // preferences. + HSHELL_WINDOWCREATED = 1, + + HSHELL_WINDOWDESTROYED = 2, + HSHELL_ACTIVATESHELLWINDOW = 3, + HSHELL_WINDOWACTIVATED = 4, + HSHELL_GETMINRECT = 5, + HSHELL_REDRAW = 6, + HSHELL_TASKMAN = 7, + HSHELL_LANGUAGE = 8, + HSHELL_ACCESSIBILITYSTATE = 11 + } + + /// + /// These are the message IDs that can be passed in as the code parameter + /// of the WindowsHookCallback that was registered with HookType.WH_CBT. + /// For details, see http://msdn.microsoft.com/en-us/library/ms644977. + public enum CbtEvents + { + HCBT_MOVESIZE = 0, + HCBT_MINMAX = 1, + HCBT_QS = 2, + HCBT_CREATEWND = 3, + HCBT_DESTROYWND = 4, + HCBT_ACTIVATE = 5, + HCBT_CLICKSKIPPED = 6, + HCBT_KEYSKIPPED = 7, + HCBT_SYSCOMMAND = 8, + HCBT_SETFOCUS = 9 + } + + /// + /// Sets a callback function to receive certain kinds of Windows events. + /// For details, see http://msdn.microsoft.com/en-us/library/ms644990. + /// The type of hook + /// The callback method delegate. Be sure to create this delegate explicitly and to + /// hold on to it explicitly because otherwise the implicit delegate can get garbage collected. For example: + /// private static readonly User32.WindowsHookCallback s_callbackDelegate = ShellHookCallback; + /// Should be IntPtr.Zero unless the hook type is WH_KEYBOARD_LL or + /// WH_MOUSE_LL. For details, see http://pinvoke.net/default.aspx/user32/SetWindowsHookEx.html. + /// The thread ID from calling AppDomain.GetCurrentThreadId(). + /// Use the pragma "warning disable 612,618" and "warning restore 612,618" to get rid + /// of the compiler warning. + /// If successful, handle to the hook procedure. If fails, NULL. + /// To get extended error information, call GetLastError(). + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern IntPtr SetWindowsHookEx( HookType code, WindowsHookCallback func, IntPtr hInstance, int threadID ); + + /// + /// Passes hook information to next hook procedure in current hook chain + /// Ignored + /// Hook code passed to current hook procedure + /// wParam value passed to the current hook procedure + /// lParam value passed to the current hook procedure + /// Value returned by the next hook procedure in the chain + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644974%28v=vs.85%29.aspx + [DllImport( DllName, CharSet = CharSet.Unicode )] + public static extern IntPtr CallNextHookEx( IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam ); + + /// + /// Removes a hook procedure installed in a hook chain by the SetWindowsHookEx() + /// Handle to the hook to be removed + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644993%28v=vs.85%29.aspx + [DllImport( DllName, CharSet = CharSet.Unicode, SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool UnhookWindowsHookEx( IntPtr hhk ); + + /// + /// Adds rectangle to specified window's update region + /// Handle to window + /// Pointer to a RECT structure for rectangle added to the update region + /// Specifies whether background within update region is erased + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool InvalidateRect( IntPtr hWnd, IntPtr lpRect, bool bErase ); + + /// + /// Creates new shape for system caret and assigns ownership of caret to specified window + /// Handle to window that owns caret + /// Handle to bitmap that defines caret shape + /// Width of caret + /// Height of caret + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms648399%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool CreateCaret( IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight ); + /// + /// Makes caret visible on screen at caret's current position + /// Handle to window that owns caret + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms648406%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool ShowCaret( IntPtr hWnd ); + /// + /// Copies caret's position to specified POINT structure + /// Pointer to POINT structure to receive client coordinates of caret + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms648402%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool GetCaretPos( out Point lpPoint ); + /// + /// Removes caret from screen + /// Handle to window that owns caret + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms648403%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool HideCaret( IntPtr hWnd ); + /// + /// Moves caret to specified coordinates + /// New x-coordinate of the caret + /// New y-coordinate of the caret + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms648405%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool SetCaretPos( int x, int y ); + /// + /// caret's current shape, frees caret from window, and caret from screen + /// Nonzero iff function succeeds + /// For details, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms648400%28v=vs.85%29.aspx + [DllImport( DllName )] + public static extern bool DestroyCaret( ); + + /// + /// ToolTip related constant, found in CommCtrl.h. + const int TTN_FIRST = -520; + + /// + /// ToolTip related constant, found in CommCtrl.h. + public const int TTN_SHOW = (TTN_FIRST - 1); + + /// + /// ToolTip related constant, found in CommCtrl.h. + public const int TTN_POP = (TTN_FIRST - 2); + + /// + /// ToolTip related constant, found in CommCtrl.h. + public const int TTN_LINKCLICK = (TTN_FIRST - 3); + + /// + /// ToolTip related constant, found in CommCtrl.h. + public const int TTN_GETDISPINFO = (TTN_FIRST - 10); + + /// + /// ToolTip related constant. + public const int TTM_SETMAXTIPWIDTH = 0x400 + 24; + + /// + /// ToolTip related structure. Hard to find documentation on this. I took this from ObjectListView. + /// For ObjectListView, see http://objectlistview.sourceforge.net/cs/index.html + [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )] + public struct NMTTDISPINFO + { + public NMHDR hdr; + [MarshalAs(UnmanagedType.LPTStr)] + public string lpszText; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] + public string szText; + public IntPtr hinst; + public int uFlags; + public IntPtr lParam; + //public int hbmp; This is documented but doesn't work. Also, it's not in the native version in CommCtrl.h. + } + + private const string DllName = "user32.dll"; + + /* Wappen added //////////////////////////////////////////*/ + + // http://pinvoke.net/default.aspx/user32.GetWindowThreadProcessId + [DllImport( "user32.dll", SetLastError = true )] + public static extern uint GetWindowThreadProcessId( IntPtr hWnd, out int lpdwProcessId ); + + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool IsWindowVisible( IntPtr hWnd ); + + [DllImport( "user32.dll" )] + public static extern IntPtr GetDlgItem( IntPtr hDlg, int nIDDlgItem ); + + [DllImport( "user32.dll", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool GetWindowPlacement( IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl ); + + /// + /// Sets the show state and the restored, minimized, and maximized positions of the specified window. + /// + /// + /// A handle to the window. + /// + /// + /// A pointer to a WINDOWPLACEMENT structure that specifies the new show state and window positions. + /// + /// Before calling SetWindowPlacement, set the length member of the WINDOWPLACEMENT structure to sizeof(WINDOWPLACEMENT). SetWindowPlacement fails if the length member is not set correctly. + /// + /// + /// + /// If the function succeeds, the return value is nonzero. + /// + /// If the function fails, the return value is zero. To get extended error information, call GetLastError. + /// + /// + [DllImport( "user32.dll", SetLastError = true )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool SetWindowPlacement( IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl ); + + /// + /// Contains information about the placement of a window on the screen. + /// + [Serializable] + [StructLayout( LayoutKind.Sequential )] + public struct WINDOWPLACEMENT + { + /// + /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT). + /// + /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly. + /// + /// + public int Length; + + /// + /// Specifies flags that control the position of the minimized window and the method by which the window is restored. + /// + public int Flags; + + /// + /// The current show state of the window. + /// + public ShowWindowCommands ShowCmd; + + /// + /// The coordinates of the window's upper-left corner when the window is minimized. + /// + public POINT MinPosition; + + /// + /// The coordinates of the window's upper-left corner when the window is maximized. + /// + public POINT MaxPosition; + + /// + /// The window's coordinates when the window is in the restored position. + /// + public RECT NormalPosition; + + /// + /// Gets the default (empty) value. + /// + public static WINDOWPLACEMENT Default + { + get + { + WINDOWPLACEMENT result = new WINDOWPLACEMENT(); + result.Length = Marshal.SizeOf( result ); + return result; + } + } + } + + public enum ShowWindowCommands + { + /// + /// Hides the window and activates another window. + /// + Hide = 0, + /// + /// Activates and displays a window. If the window is minimized or + /// maximized, the system restores it to its original size and position. + /// An application should specify this flag when displaying the window + /// for the first time. + /// + Normal = 1, + /// + /// Activates the window and displays it as a minimized window. + /// + ShowMinimized = 2, + /// + /// Maximizes the specified window. + /// + Maximize = 3, // is this the right value? + /// + /// Activates the window and displays it as a maximized window. + /// + ShowMaximized = 3, + /// + /// Displays a window in its most recent size and position. This value + /// is similar to , except + /// the window is not activated. + /// + ShowNoActivate = 4, + /// + /// Activates the window and displays it in its current size and position. + /// + Show = 5, + /// + /// Minimizes the specified window and activates the next top-level + /// window in the Z order. + /// + Minimize = 6, + /// + /// Displays the window as a minimized window. This value is similar to + /// , except the + /// window is not activated. + /// + ShowMinNoActive = 7, + /// + /// Displays the window in its current size and position. This value is + /// similar to , except the + /// window is not activated. + /// + ShowNA = 8, + /// + /// Activates and displays the window. If the window is minimized or + /// maximized, the system restores it to its original size and position. + /// An application should specify this flag when restoring a minimized window. + /// + Restore = 9, + /// + /// Sets the show state based on the SW_* value specified in the + /// STARTUPINFO structure passed to the CreateProcess function by the + /// program that started the application. + /// + ShowDefault = 10, + /// + /// Windows 2000/XP: Minimizes a window, even if the thread + /// that owns the window is not responding. This flag should only be + /// used when minimizing windows from a different thread. + /// + ForceMinimize = 11 + } + + // Additional from http://pinvoke.net/default.aspx/user32/SendMessage.html + [DllImport( "user32.dll", CharSet = CharSet.Auto )] + public static extern IntPtr SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto )] + public static extern IntPtr SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, [MarshalAs( UnmanagedType.LPWStr )] string lParam ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto )] + public static extern IntPtr SendMessage( IntPtr hWnd, int Msg, int wParam, [MarshalAs( UnmanagedType.LPWStr )] string lParam ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto )] + public static extern IntPtr SendMessage( IntPtr hWnd, int Msg, int wParam, ref IntPtr lParam ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto )] + public static extern IntPtr SendMessage( IntPtr hWnd, int Msg, int wParam, IntPtr lParam ); + + /// + /// Simple version with no arg. + /// + public static IntPtr SendMessage( IntPtr hWnd, int Msg ) + { + return SendMessage( hWnd, Msg, IntPtr.Zero, IntPtr.Zero ); + } + + public static int MAKEWPARAM( int l, int h ) + { + return (l & 0xFFFF) | (h << 16); + } + + public static IntPtr MAKELPARAM( int l, int h ) + { + return new IntPtr( (h << 16) | (l & 0xFFFF) ); + } + + + [DllImport( "user32.dll", SetLastError = true )] + public static extern bool SetWindowPos( IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags ); + + [Flags] + public enum SetWindowPosFlags : uint + { + /// If the calling thread and the thread that owns the window are attached to different input queues, + /// the system posts the request to the thread that owns the window. This prevents the calling thread from + /// blocking its execution while other threads process the request. + /// SWP_ASYNCWINDOWPOS + AsynchronousWindowPosition = 0x4000, + /// Prevents generation of the WM_SYNCPAINT message. + /// SWP_DEFERERASE + DeferErase = 0x2000, + /// Draws a frame (defined in the window's class description) around the window. + /// SWP_DRAWFRAME + DrawFrame = 0x0020, + /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to + /// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE + /// is sent only when the window's size is being changed. + /// SWP_FRAMECHANGED + FrameChanged = 0x0020, + /// Hides the window. + /// SWP_HIDEWINDOW + HideWindow = 0x0080, + /// Does not activate the window. If this flag is not set, the window is activated and moved to the + /// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter + /// parameter). + /// SWP_NOACTIVATE + DoNotActivate = 0x0010, + /// Discards the entire contents of the client area. If this flag is not specified, the valid + /// contents of the client area are saved and copied back into the client area after the window is sized or + /// repositioned. + /// SWP_NOCOPYBITS + DoNotCopyBits = 0x0100, + /// Retains the current position (ignores X and Y parameters). + /// SWP_NOMOVE + IgnoreMove = 0x0002, + /// Does not change the owner window's position in the Z order. + /// SWP_NOOWNERZORDER + DoNotChangeOwnerZOrder = 0x0200, + /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to + /// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent + /// window uncovered as a result of the window being moved. When this flag is set, the application must + /// explicitly invalidate or redraw any parts of the window and parent window that need redrawing. + /// SWP_NOREDRAW + DoNotRedraw = 0x0008, + /// Same as the SWP_NOOWNERZORDER flag. + /// SWP_NOREPOSITION + DoNotReposition = 0x0200, + /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message. + /// SWP_NOSENDCHANGING + DoNotSendChangingEvent = 0x0400, + /// Retains the current size (ignores the cx and cy parameters). + /// SWP_NOSIZE + IgnoreResize = 0x0001, + /// Retains the current Z order (ignores the hWndInsertAfter parameter). + /// SWP_NOZORDER + IgnoreZOrder = 0x0004, + /// Displays the window. + /// SWP_SHOWWINDOW + ShowWindow = 0x0040, + } + + public enum GWL + { + GWL_WNDPROC = (-4), + GWL_HINSTANCE = (-6), + GWL_HWNDPARENT = (-8), + GWL_STYLE = (-16), + GWL_EXSTYLE = (-20), + GWL_USERDATA = (-21), + GWL_ID = (-12) + } + + [DllImport( "user32.dll", EntryPoint = "GetWindowLong" )] + public static extern IntPtr GetWindowLongPtr( IntPtr hWnd, int nIndex ); + + [DllImport( "user32.dll", EntryPoint = "GetWindowLong" )] + public static extern IntPtr GetWindowLong( IntPtr hWnd, int nIndex ); + + public static bool GetWindowLongHasFlag( IntPtr hWnd, GWL nIndex, WindowStyles checkingStyle ) + { + IntPtr v = GetWindowLong( hWnd, (int)nIndex ); + return (v.ToInt32( ) & (int)checkingStyle) != 0; + } + + /// + /// Window Styles. + /// The following styles can be specified wherever a window style is required. After the control has been created, these styles cannot be modified, except as noted. + /// + [Flags] + public enum WindowStyles : uint + { + /// The window has a thin-line border. + WS_BORDER = 0x800000, + + /// The window has a title bar (includes the WS_BORDER style). + WS_CAPTION = 0xc00000, + + /// The window is a child window. A window with this style cannot have a menu bar. This style cannot be used with the WS_POPUP style. + WS_CHILD = 0x40000000, + + /// Excludes the area occupied by child windows when drawing occurs within the parent window. This style is used when creating the parent window. + WS_CLIPCHILDREN = 0x2000000, + + /// + /// Clips child windows relative to each other; that is, when a particular child window receives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated. + /// If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, when drawing within the client area of a child window, to draw within the client area of a neighboring child window. + /// + WS_CLIPSIBLINGS = 0x4000000, + + /// The window is initially disabled. A disabled window cannot receive input from the user. To change this after a window has been created, use the EnableWindow function. + WS_DISABLED = 0x8000000, + + /// The window has a border of a style typically used with dialog boxes. A window with this style cannot have a title bar. + WS_DLGFRAME = 0x400000, + + /// + /// The window is the first control of a group of controls. The group consists of this first control and all controls defined after it, up to the next control with the WS_GROUP style. + /// The first control in each group usually has the WS_TABSTOP style so that the user can move from group to group. The user can subsequently change the keyboard focus from one control in the group to the next control in the group by using the direction keys. + /// You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use the SetWindowLong function. + /// + WS_GROUP = 0x20000, + + /// The window has a horizontal scroll bar. + WS_HSCROLL = 0x100000, + + /// The window is initially maximized. + WS_MAXIMIZE = 0x1000000, + + /// The window has a maximize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified. + WS_MAXIMIZEBOX = 0x10000, + + /// The window is initially minimized. + WS_MINIMIZE = 0x20000000, + + /// The window has a minimize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified. + WS_MINIMIZEBOX = 0x20000, + + /// The window is an overlapped window. An overlapped window has a title bar and a border. + WS_OVERLAPPED = 0x0, + + /// The window is an overlapped window. + WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_SIZEFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, + + /// The window is a pop-up window. This style cannot be used with the WS_CHILD style. + WS_POPUP = 0x80000000u, + + /// The window is a pop-up window. The WS_CAPTION and WS_POPUPWINDOW styles must be combined to make the window menu visible. + WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU, + + /// The window has a sizing border. + WS_SIZEFRAME = 0x40000, + + /// The window has a window menu on its title bar. The WS_CAPTION style must also be specified. + WS_SYSMENU = 0x80000, + + /// + /// The window is a control that can receive the keyboard focus when the user presses the TAB key. + /// Pressing the TAB key changes the keyboard focus to the next control with the WS_TABSTOP style. + /// You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use the SetWindowLong function. + /// For user-created windows and modeless dialogs to work with tab stops, alter the message loop to call the IsDialogMessage function. + /// + WS_TABSTOP = 0x10000, + + /// The window is initially visible. This style can be turned on and off by using the ShowWindow or SetWindowPos function. + WS_VISIBLE = 0x10000000, + + /// The window has a vertical scroll bar. + WS_VSCROLL = 0x200000 + } + + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + public static extern bool GetScrollInfo( IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi ); + + public enum ScrollInfoMask : uint + { + SIF_RANGE = 0x1, + SIF_PAGE = 0x2, + SIF_POS = 0x4, + SIF_DISABLENOSCROLL = 0x8, + SIF_TRACKPOS = 0x10, + SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS), + } + + public enum SBOrientation : int + { + SB_HORZ = 0x0, + SB_VERT = 0x1, + SB_CTL = 0x2, + SB_BOTH = 0x3 + } + + [Serializable, StructLayout( LayoutKind.Sequential )] + public struct SCROLLINFO + { + public uint cbSize; + public uint fMask; + public int nMin; + public int nMax; + public uint nPage; + public int nPos; + public int nTrackPos; + } + + public const int MK_LBUTTON = 0x0001; + + public const int SB_SETPARTS = WM_USER + 4; + public const int SB_GETPARTS = WM_USER + 6; + public const int SB_GETTEXTLENGTH = WM_USER + 12; + public const int SB_GETTEXT = WM_USER + 13; +} diff --git a/DLSiteDumperCS/ViewerDumper.cs b/DLSiteDumperCS/ViewerDumper.cs new file mode 100644 index 0000000..364a6bc --- /dev/null +++ b/DLSiteDumperCS/ViewerDumper.cs @@ -0,0 +1,340 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using static Gdi32; +using static Kernel32; +using static User32; +using HWND = System.IntPtr; + +class ViewerDumper : IDisposable +{ + readonly DLSiteDumperCS.MainForm parentDialog; + + public string BaseSavePath { get; set; } + public int TargetPid { get; set; } + public int BasePageOffset { get; set; } = 1; + public string TargetImageExt { get; set; } = "png"; + public int BetweenPageDelayMs { get; set; } = 1000; + + public ViewerDumper( DLSiteDumperCS.MainForm parentDialog ) + { + this.parentDialog = parentDialog; + } + + /// + /// Indicates that PID is valid and we can open process. + /// + public bool IsReady => viewer_process != HWND.Zero && viewer_area_main != HWND.Zero; + + Process viewerProcess; + HWND viewer_process; + HWND viewer_window_main; + + const int VIEWER_BUTTON_PARENT_CODE = 0xE805; + const int VIEWER_BUTTON_FIRST_CODE = 0x8023; + const int VIEWER_BUTTON_NEXT_CODE = 0x8020; + const int VIEWER_BUTTON_ZOOM_CODE = 0x800A; + const int VIEWER_AREA_PARENT_CODE = 0xE900; + const int VIEWER_AREA_MAIN_CODE = 0xE900; + const int STATUS_BAR = 59393; + + HWND viewer_button_parent; + HWND viewer_button_first; + HWND viewer_button_next; + HWND viewer_button_zoom; + HWND viewer_area_parent; + HWND viewer_area_main; + //Win32StatusBar m_ViewerStatusBar; + + public void Dispose( ) + { + if( viewer_process != IntPtr.Zero ) + CloseHandle( viewer_process ); + } + + public void Setup( int processId ) + { + TargetPid = processId; + viewerProcess = Process.GetProcessById( processId ); + viewer_process = OpenProcess( viewerProcess, ProcessAccessTypes.PROCESS_VM_READ | ProcessAccessTypes.PROCESS_QUERY_INFORMATION ); + + viewer_window_main = WndSearcher.SearchForWindowWithPid( viewerProcess.Id ); + + // Find all the subwindow by control ID + viewer_button_parent = GetDlgItem( viewer_window_main, VIEWER_BUTTON_PARENT_CODE ); + viewer_button_first = GetDlgItem( viewer_button_parent, VIEWER_BUTTON_FIRST_CODE ); + viewer_button_next = GetDlgItem( viewer_button_parent, VIEWER_BUTTON_NEXT_CODE ); + viewer_button_zoom = GetDlgItem( viewer_button_parent, VIEWER_BUTTON_ZOOM_CODE ); + viewer_area_parent = GetDlgItem( viewer_window_main, VIEWER_AREA_PARENT_CODE ); + viewer_area_main = GetDlgItem( viewer_area_parent, VIEWER_AREA_MAIN_CODE ); + + // Note: I tried to read status bar that displaying page number, + // but looks like its text is hidden. So no auto page detection for now +#if false + HWND statusBarHwnd = GetDlgItem( viewer_window_main, STATUS_BAR ); + m_ViewerStatusBar = new Win32StatusBar( viewer_process, statusBarHwnd ); + + int panels = m_ViewerStatusBar.GetPanelCount( ); + for( int i=0 ; i> 3) * h; + if( m_ImageDumpBuffer == null || m_ImageDumpBuffer.Length < imageSize ) + m_ImageDumpBuffer = new byte[imageSize]; + + // Prepare BMP header for hijacking + BITMAPFILEHEADER bmf = default; + BITMAPINFOHEADER bmi = default; + + bmf.bfType = 0x4d42; + bmf.bfSize = (uint)(Marshal.SizeOf( bmf ) + Marshal.SizeOf( bmi ) + imageSize); + bmf.bfOffBits = (uint)(Marshal.SizeOf( bmf ) + Marshal.SizeOf( bmi )); + + bmi.biSize = 40; // Size of info header, must be 40 + bmi.biWidth = w; + bmi.biHeight = -h; + bmi.biPlanes = 1; + bmi.biBitCount = 32; // Data dumped from mem is 32bpp + bmi.biCompression = 0; + //bmi.biSizeImage = (uint)imageSize; // biSizeImage is not required if there is no compression + + byte[] bmfHeaderBytes = StructToBytes( bmf ); + byte[] bmiHeaderBytes = StructToBytes( bmi ); + + for( IntPtr address = default; ; ) + { + MEMORY_BASIC_INFORMATION mbi = default; + int actualByteRead = -1; + while( VirtualQueryEx( viewer_process, address, out mbi, (uint)Marshal.SizeOf( mbi ) ) != 0 ) + { + if( mbi.State == (uint)MemState.MEM_COMMIT && mbi.Type == (uint)MemType.MEM_PRIVATE && mbi.Protect == (uint)PageAllocationProtect.PAGE_READWRITE && mbi.RegionSize.ToInt32( ) >= imageSize ) + { + IntPtr byteRead; + if( !ReadProcessMemory( viewer_process, mbi.BaseAddress, m_ImageDumpBuffer, imageSize, out byteRead ) ) + { + Debug.Print( $"ReadProcessMemory failed at PID {viewer_process} addess 0x{mbi.BaseAddress:X} size {imageSize}. But it will continue..." ); + continue; + } + + actualByteRead = byteRead.ToInt32( ); + Debug.Print( "ReadProcessMemory success\n" ); + } + + // Iterate to see next memory page + address = IntPtr.Add( mbi.BaseAddress, mbi.RegionSize.ToInt32( ) ); + } + + // Write to file + // Three digit decimal with padding + if( actualByteRead > 0 ) + { + string filename = GetFileNameForPage( pageNumber, TargetImageExt ); + string outputPath = Path.Combine( BaseSavePath, filename ); + + worker.ReportProgress( 0, $"Dumping page {pageNumber}\nto {outputPath}" ); + +#if false // This was saving plain BMP file + try + { + using( FileStream ls = new FileStream( outputPath, FileMode.Create ) ) + { + ls.Write( bmfHeaderBytes, 0, bmfHeaderBytes.Length ); + ls.Write( bmiHeaderBytes, 0, bmiHeaderBytes.Length ); + ls.Write( m_ImageDumpBuffer, 0, actualByteRead ); + } + } + catch( Exception e ) + { + Debug.Print( $"Failed to write to {outputPath}\n{e.Message}" ); + } +#endif + using( MemoryStream ms = new MemoryStream( bmfHeaderBytes.Length + bmiHeaderBytes.Length + actualByteRead ) ) + { + ms.Write( bmfHeaderBytes, 0, bmfHeaderBytes.Length ); + ms.Write( bmiHeaderBytes, 0, bmiHeaderBytes.Length ); + ms.Write( m_ImageDumpBuffer, 0, actualByteRead ); + + Image bmp = Image.FromStream( ms ); + + if( TargetImageExt == "png" ) + bmp.Save( outputPath, ImageFormat.Png ); + else if( TargetImageExt == "jpg" ) + bmp.Save( outputPath, ImageFormat.Jpeg ); + } + } + + Debug.Print( "Image dump ok, switch page." ); + break; + } + } + + + void _NextPage( ) + { + // Once image memory is ours, 'click' to the next image + SendMessage( viewer_button_next, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM( 1, 1 ) ); + SendMessage( viewer_button_next, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM( 1, 1 ) ); + + // There is delay for DLS to decode-display an image + // So wait a bit + Thread.Sleep( BetweenPageDelayMs ); + } + + public static string GetFileNameForPage( int page, string ext ) + { + return $"{page:D3}.{ext}"; + } +} \ No newline at end of file diff --git a/DLSiteDumperCS/Win32StatusBar.cs b/DLSiteDumperCS/Win32StatusBar.cs new file mode 100644 index 0000000..d07bf14 --- /dev/null +++ b/DLSiteDumperCS/Win32StatusBar.cs @@ -0,0 +1,84 @@ +using static User32; +using static Kernel32; +using System; + +public class Win32StatusBar +{ + private IntPtr m_Hwnd; + private IntPtr m_ParentProcess; + + public Win32StatusBar( IntPtr hProcess, IntPtr hWnd ) + { + this.m_Hwnd = hWnd; + this.m_ParentProcess = hProcess; + } + + public int GetPanelCount( ) + { + if( this.m_Hwnd != IntPtr.Zero ) + return (int)SendMessage( m_Hwnd, SB_GETPARTS ); + + return 0; + } + + public string GetCaption( int index ) + { + int length = (int)SendMessage( m_Hwnd, SB_GETTEXTLENGTH, index, IntPtr.Zero ); + + // Low part is the count. High part is the window type. Mask out the high bits. + // The returned text will also be unicode so double the length to accomodate our buffer + length = (length & 0x0000ffff) * 2; + + IntPtr hProcess = IntPtr.Zero; + IntPtr allocated = IntPtr.Zero; + + try + { + // Allocate memory in the remote process + allocated = VirtualAllocEx( m_ParentProcess, IntPtr.Zero, (uint)length, (VirtualAllocExTypes.MEM_COMMIT_OR_RESERVE), AccessProtectionFlags.PAGE_READWRITE ); + + if( allocated != IntPtr.Zero ) + { + IntPtr bytesRead = default; + byte[] buffer = new byte[length]; + + // SB_GETTEXT tells the remote process to write out text to the remote memory we allocated. + SendMessage( this.m_Hwnd, SB_GETTEXT, (IntPtr)index, allocated ); + + // Now we need to read that memory from the remote process into a local buffer. + bool success = ReadProcessMemory( hProcess, allocated, buffer, length, out bytesRead ); + + if( success ) + { + // Each char takes 2 bytes. + char[] characters = new char[length / 2]; + + for( int i = 0; i < buffer.Length; i = i + 2 ) + { + // Even though the second byte will probably always be 0 for en-us let's so a bit shift + // then "or" the first and second bytes together before casting to char. + uint a = (uint)buffer[i]; + uint b = (uint)buffer[i + 1] << 8; + + characters[i / 2] = (char)(a | b); + } + + return new string( characters ); + } + } + } + finally + { + if( hProcess != IntPtr.Zero ) + { + if( allocated != IntPtr.Zero ) + { + // Free the memory in the remote process + VirtualFreeEx( hProcess, allocated, 0, VirtualAllocExTypes.MEM_RELEASE ); + } + } + } + + return string.Empty; + } +} \ No newline at end of file diff --git a/DLSiteDumperCS/WndSearcher.cs b/DLSiteDumperCS/WndSearcher.cs new file mode 100644 index 0000000..0631ac5 --- /dev/null +++ b/DLSiteDumperCS/WndSearcher.cs @@ -0,0 +1,80 @@ + +using System; +using System.Runtime.InteropServices; +using System.Text; +// http://pinvoke.net/default.aspx/user32.EnumWindows +public class WndSearcher +{ + public static IntPtr SearchForWindowWithPid( int processId ) + { + SearchData sd = new SearchData { pid=processId }; + EnumWindows( new EnumWindowsProc( EnumProc ), ref sd ); + return sd.hWnd; + } + + public static IntPtr SearchForWindow( string wndclass, string title ) + { + SearchData sd = new SearchData { Wndclass=wndclass, Title=title }; + EnumWindows( new EnumWindowsProc( EnumProc ), ref sd ); + return sd.hWnd; + } + + public static bool EnumProc( IntPtr hWnd, ref SearchData data ) + { + if( data.pid != 0 ) + { + // Search using PID + User32.GetWindowThreadProcessId( hWnd, out int processId ); + if( data.pid == processId ) + { + // Any given process may have many invisible top level windows + // DMMViewer has about 4, but should only have one visible (the main window) + if( User32.IsWindowVisible( hWnd ) ) + { + data.hWnd = hWnd; + return false; // Finally found it + } + } + } + else + { + // Check classname and title + // This is different from FindWindow() in that the code below allows partial matches + StringBuilder sb = new StringBuilder(1024); + GetClassName( hWnd, sb, sb.Capacity ); + if( sb.ToString( ).StartsWith( data.Wndclass ) ) + { + sb = new StringBuilder( 1024 ); + GetWindowText( hWnd, sb, sb.Capacity ); + if( sb.ToString( ).StartsWith( data.Title ) ) + { + data.hWnd = hWnd; + return false; // Found the wnd, halt enumeration + } + } + } + return true; + } + + public class SearchData + { + public int pid; + + public string Wndclass; + + public string Title; + public IntPtr hWnd; + } + + private delegate bool EnumWindowsProc( IntPtr hWnd, ref SearchData data ); + + [DllImport( "user32.dll" )] + [return: MarshalAs( UnmanagedType.Bool )] + private static extern bool EnumWindows( EnumWindowsProc lpEnumFunc, ref SearchData data ); + + [DllImport( "user32.dll", SetLastError = true, CharSet = CharSet.Auto )] + public static extern int GetClassName( IntPtr hWnd, StringBuilder lpClassName, int nMaxCount ); + + [DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = true )] + public static extern int GetWindowText( IntPtr hWnd, StringBuilder lpString, int nMaxCount ); +} \ No newline at end of file diff --git a/DLSiteDumperCS/WorkingDialog.Designer.cs b/DLSiteDumperCS/WorkingDialog.Designer.cs new file mode 100644 index 0000000..4a04cb1 --- /dev/null +++ b/DLSiteDumperCS/WorkingDialog.Designer.cs @@ -0,0 +1,98 @@ + +namespace DLSiteDumperCS +{ + partial class WorkingDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + protected override void Dispose( bool disposing ) + { + if( disposing && (components != null) ) + { + components.Dispose( ); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent( ) + { + this.okButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.statusText = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // okButton + // + this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.okButton.Location = new System.Drawing.Point(164, 85); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(99, 23); + this.okButton.TabIndex = 24; + this.okButton.Text = "&Abort"; + this.okButton.Click += new System.EventHandler(this.okButton_Click); + // + // label1 + // + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(401, 36); + this.label1.TabIndex = 25; + this.label1.Text = "Working very hard to populate your fap cave.\r\nHands off! Dont touch anything!"; + this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // statusText + // + this.statusText.Anchor = System.Windows.Forms.AnchorStyles.None; + this.statusText.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.statusText.Location = new System.Drawing.Point(12, 45); + this.statusText.Name = "statusText"; + this.statusText.Size = new System.Drawing.Size(401, 37); + this.statusText.TabIndex = 25; + this.statusText.Text = "...Status..."; + this.statusText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // WorkingDialog + // + this.AcceptButton = this.okButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(425, 120); + this.ControlBox = false; + this.Controls.Add(this.statusText); + this.Controls.Add(this.label1); + this.Controls.Add(this.okButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "WorkingDialog"; + this.Padding = new System.Windows.Forms.Padding(9); + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Loading"; + this.Load += new System.EventHandler(this.WorkingDialog_Load); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label statusText; + } +} diff --git a/DLSiteDumperCS/WorkingDialog.cs b/DLSiteDumperCS/WorkingDialog.cs new file mode 100644 index 0000000..4d7b641 --- /dev/null +++ b/DLSiteDumperCS/WorkingDialog.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace DLSiteDumperCS +{ + partial class WorkingDialog : Form + { + readonly MainForm main; + + public WorkingDialog( MainForm m ) + { + main = m; + InitializeComponent( ); + } + + #region Assembly Attribute Accessors + + public string AssemblyTitle + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + if( attributes.Length > 0 ) + { + AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + if( titleAttribute.Title != "" ) + { + return titleAttribute.Title; + } + } + return System.IO.Path.GetFileNameWithoutExtension( Assembly.GetExecutingAssembly( ).CodeBase ); + } + } + + public string AssemblyVersion + { + get + { + return Assembly.GetExecutingAssembly( ).GetName( ).Version.ToString( ); + } + } + + public string AssemblyDescription + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + if( attributes.Length == 0 ) + { + return ""; + } + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + + public string AssemblyProduct + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); + if( attributes.Length == 0 ) + { + return ""; + } + return ((AssemblyProductAttribute)attributes[0]).Product; + } + } + + public string AssemblyCopyright + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + if( attributes.Length == 0 ) + { + return ""; + } + return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + } + } + + public string AssemblyCompany + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + if( attributes.Length == 0 ) + { + return ""; + } + return ((AssemblyCompanyAttribute)attributes[0]).Company; + } + } + #endregion + + private void WorkingDialog_Load( object sender, EventArgs e ) + { + + } + + public void SetStatusText( string txt ) + { + statusText.Text = txt; + } + + private void okButton_Click( object sender, EventArgs e ) + { + main.NotifyAbort( ); + } + } +} diff --git a/DLSiteDumperCS/WorkingDialog.resx b/DLSiteDumperCS/WorkingDialog.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/DLSiteDumperCS/WorkingDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/fuckds.sln b/fuckds.sln deleted file mode 100644 index a9f5cf0..0000000 --- a/fuckds.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuckds", "fuckds\fuckds.vcxproj", "{76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Debug|x64.ActiveCfg = Debug|x64 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Debug|x64.Build.0 = Debug|x64 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Debug|x86.ActiveCfg = Debug|Win32 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Debug|x86.Build.0 = Debug|Win32 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Release|x64.ActiveCfg = Release|x64 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Release|x64.Build.0 = Release|x64 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Release|x86.ActiveCfg = Release|Win32 - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/fuckds/ReadMe.txt b/fuckds/ReadMe.txt deleted file mode 100644 index ca858a5..0000000 --- a/fuckds/ReadMe.txt +++ /dev/null @@ -1,40 +0,0 @@ -======================================================================== - CONSOLE APPLICATION : fuckds Project Overview -======================================================================== - -AppWizard has created this fuckds application for you. - -This file contains a summary of what you will find in each of the files that -make up your fuckds application. - - -fuckds.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -fuckds.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -fuckds.cpp - This is the main application source file. - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named fuckds.pch and a precompiled types file named StdAfx.obj. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" comments to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/fuckds/fuckds.cpp b/fuckds/fuckds.cpp deleted file mode 100644 index 23f16a5..0000000 --- a/fuckds/fuckds.cpp +++ /dev/null @@ -1,222 +0,0 @@ -// fuckds.cpp : Defines the entry point for the console application. -// - -#include "stdafx.h" -#include - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include - -#include -#include - -// Compact some stuff so it can all be sent by a pointer to get_process_window -struct process_window_helper -{ - // Set this before calling get_process_window as the process to match - DWORD pid; - // get_process_window will set this pointing to a visible window belonging to the process - HWND hwnd; -}; - -BOOL CALLBACK get_process_window(HWND hwnd, LPARAM lParam) -{ - // Find all windows belonging to the process - DWORD pid; - GetWindowThreadProcessId(hwnd, &pid); - if (((struct process_window_helper*)lParam)->pid == pid) { - // Any given process may have many invisible top level windows - // DMMViewer has about 4, but should only have one visible (the main window) - if (IsWindowVisible(hwnd)) { - ((struct process_window_helper*)lParam)->hwnd = hwnd; - return FALSE; - } - } - - return TRUE; -} - -int _tmain(int argc, const char* argv[]) -{ - static const int VIEWER_BUTTON_PARENT_CODE = 0xE805; - static const int VIEWER_BUTTON_FIRST_CODE = 0x8023; - static const int VIEWER_BUTTON_NEXT_CODE = 0x8020; - static const int VIEWER_BUTTON_ZOOM_CODE = 0x800A; - static const int VIEWER_AREA_PARENT_CODE = 0xE900; - static const int VIEWER_AREA_MAIN_CODE = 0xE900; - - if (argc < 2) - return -1; - - const DWORD viewer_process_id = atoi(argv[1]); - - printf("Try to open process... %d\n",viewer_process_id); - - // Open the process with permission to read memory and process info - HANDLE viewer_process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, viewer_process_id); - - printf("Process handle %d\n", viewer_process); - - if (!viewer_process) - return -1; - - struct process_window_helper pwh; - - pwh.pid = viewer_process_id; - pwh.hwnd = (HWND)0xdeaddead; - - printf("Try to find window...\n"); - - EnumWindows(&get_process_window, (LPARAM)&pwh); - - printf("Window hwnd: %d\n",pwh.hwnd); - - // Find all the subwindow by control ID - HWND viewer_window_main = pwh.hwnd; - HWND viewer_button_parent = GetDlgItem(viewer_window_main, VIEWER_BUTTON_PARENT_CODE); - HWND viewer_button_first = GetDlgItem(viewer_button_parent, VIEWER_BUTTON_FIRST_CODE); - HWND viewer_button_next = GetDlgItem(viewer_button_parent, VIEWER_BUTTON_NEXT_CODE); - HWND viewer_button_zoom = GetDlgItem(viewer_button_parent, VIEWER_BUTTON_ZOOM_CODE); - HWND viewer_area_parent = GetDlgItem(viewer_window_main, VIEWER_AREA_PARENT_CODE); - HWND viewer_area_main = GetDlgItem(viewer_area_parent, VIEWER_AREA_MAIN_CODE); - - // Store original window position and state - // Window will be shrunken to ensure window size is smaller than the image - // This is necessary so that the immage in memory will not be padded - WINDOWPLACEMENT original_window_placement; - original_window_placement.length = sizeof(original_window_placement); - GetWindowPlacement(viewer_window_main, &original_window_placement); - WINDOWPLACEMENT temp_window_placement; - temp_window_placement = original_window_placement; - temp_window_placement.showCmd = SW_SHOW; - SetWindowPlacement(viewer_window_main, &temp_window_placement); - - // Set zoom level to 100% - int original_zoom_selection = ComboBox_GetCurSel(viewer_button_zoom); - - ComboBox_SelectString(viewer_button_zoom, -1, "100%"); - - // Programatically selecting a ComboBox option will not send a selection change message to the parent, so do that manually - SendMessage(viewer_button_parent, WM_COMMAND, MAKEWPARAM(VIEWER_BUTTON_ZOOM_CODE, CBN_SELCHANGE), (LPARAM)viewer_button_zoom); - - RECT original_window_rect; - GetWindowRect(viewer_window_main, &original_window_rect); - - SetWindowPos(viewer_window_main, 0, 0, 0, 256, 256, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOACTIVATE); - - // Send a virtual click to the first page button - // SendMessage(viewer_button_first, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(1, 1)); - // SendMessage(viewer_button_first, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(1, 1)); - - // It seems it takes some time for messages to propagate to other buttons, so wait until the next button is enabled - // This will prevent the bug where if the Viewer was opened to the last page, it would only export the first image - if (GetWindowLong(viewer_button_next, GWL_STYLE) & WS_DISABLED) - { - Sleep(1000); - } - - std::vector image; - - std::set checksums; - - // Continue until the next button becomes disabled, indicating the last image - for (size_t pages = 0;; pages++) - { - // As a hack, the dimensions of the images are determined by - // looking at the size of the scroll area - // This requires that the image area be smaller than the image - SCROLLINFO sih, siv; - - sih.cbSize = sizeof(sih); - sih.fMask = SIF_ALL; - siv.cbSize = sizeof(siv); - siv.fMask = SIF_ALL; - - GetScrollInfo(viewer_area_main, SB_HORZ, &sih); - GetScrollInfo(viewer_area_main, SB_VERT, &siv); - - int w = sih.nMax - sih.nMin + 1; - int h = siv.nMax - siv.nMin + 1; - - image.resize((((w * 32 + 31) & ~31) >> 3) * h); - - BITMAPFILEHEADER bmf = { 0 }; - bmf.bfType = 0x4d42; - bmf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + image.size(); - bmf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - - BITMAPINFOHEADER bmi = { 0 }; - bmi.biSize = sizeof(BITMAPINFOHEADER); - bmi.biWidth = w; - bmi.biHeight = -h; - bmi.biPlanes = 1; - bmi.biBitCount = 32; - bmi.biSizeImage = image.size(); - - for (LPVOID address = 0;;) - { - MEMORY_BASIC_INFORMATION mbi; - - while (VirtualQueryEx(viewer_process, address, &mbi, sizeof(mbi))) { - if (mbi.State == MEM_COMMIT && mbi.Type == MEM_PRIVATE && mbi.Protect == PAGE_READWRITE && mbi.RegionSize >= image.size()) { - if (!ReadProcessMemory(viewer_process, mbi.BaseAddress, &image[0], image.size(), NULL)) { - printf("RPM failed\n"); - continue; - } - printf("RPM success\n"); - boost::crc_32_type crc32; - crc32.process_bytes(&image[0], image.size()); - if (!checksums.insert(crc32.checksum()).second) { - printf("Invalid checksum\n"); - continue; - } - printf("Check passed! \n"); - } - address = (char*)mbi.BaseAddress + mbi.RegionSize; - } - - char filename[FILENAME_MAX]; - - _snprintf(filename, FILENAME_MAX, "%03u_%p.bmp", pages, mbi.BaseAddress); - - FILE *fp = fopen(filename, "wb"); - - if (!fp) { - printf("Unable to open local file to write\n"); - continue; - } - - fwrite(&bmf, sizeof(bmf), 1, fp); - fwrite(&bmi, sizeof(bmi), 1, fp); - fwrite(&image[0], image.size(), 1, fp); - - fclose(fp); - - printf("Image dump ok, switch page."); - break; - } - - // Once image memory is ours, 'click' to the next image - SendMessage(viewer_button_next, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(1, 1)); - SendMessage(viewer_button_next, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(1, 1)); - - // If the next button is disabled, we reached the end; grab one last image and finish - if (GetWindowLong(viewer_button_next, GWL_STYLE) & WS_DISABLED) - break; - } - - // Restore window size and state - SetWindowPos(viewer_window_main, 0, 0, 0, original_window_rect.right - original_window_rect.left, original_window_rect.top - original_window_rect.bottom, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOACTIVATE); - SetWindowPlacement(viewer_window_main, &original_window_placement); - - // Restore zoom level - ComboBox_SetCurSel(viewer_button_zoom, original_zoom_selection); - SendMessage(viewer_button_parent, WM_COMMAND, MAKEWPARAM(VIEWER_BUTTON_ZOOM_CODE, CBN_SELCHANGE), (LPARAM)viewer_button_zoom); - - CloseHandle(viewer_process); - - return 0; -} \ No newline at end of file diff --git a/fuckds/fuckds.vcxproj b/fuckds/fuckds.vcxproj deleted file mode 100644 index a9b8d90..0000000 --- a/fuckds/fuckds.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {76055284-8986-4EF5-B6F0-ACF9B7AA4F6B} - Win32Proj - fuckds - 8.1 - - - - Application - true - v140 - MultiByte - - - Application - false - v140 - true - Unicode - - - Application - true - v140 - MultiByte - - - Application - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - T:\OldBackups\ProjectLibrary\boost_1_58_0;$(IncludePath) - - - true - T:\OldBackups\ProjectLibrary\boost_1_58_0;$(IncludePath) - - - false - T:\OldBackups\ProjectLibrary\boost_1_58_0;$(IncludePath) - - - false - T:\OldBackups\ProjectLibrary\boost_1_58_0;$(IncludePath) - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - true - - - - - Use - Level3 - Disabled - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - \ No newline at end of file diff --git a/fuckds/fuckds.vcxproj.filters b/fuckds/fuckds.vcxproj.filters deleted file mode 100644 index 6f0863f..0000000 --- a/fuckds/fuckds.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/fuckds/stdafx.cpp b/fuckds/stdafx.cpp deleted file mode 100644 index ef2a834..0000000 --- a/fuckds/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// fuckds.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/fuckds/stdafx.h b/fuckds/stdafx.h deleted file mode 100644 index b005a83..0000000 --- a/fuckds/stdafx.h +++ /dev/null @@ -1,15 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#include -#include - - - -// TODO: reference additional headers your program requires here diff --git a/fuckds/targetver.h b/fuckds/targetver.h deleted file mode 100644 index 87c0086..0000000 --- a/fuckds/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include