From 4a8f77da0decf240157a672c74ab76b5a9b231cc Mon Sep 17 00:00:00 2001 From: -- <--> Date: Thu, 29 Nov 2018 01:53:56 -0500 Subject: [PATCH 1/3] Added ability to capture the game window directly for ease of adding logo and screenshot --- FlashpointCC/CurationForm.Designer.cs | 121 ++++++++++++++++---------- FlashpointCC/CurationForm.cs | 98 ++++++++++++++++++++- FlashpointCC/CurationForm.resx | 8 +- FlashpointCC/FlashpointCC.csproj | 1 + FlashpointCC/ScreenCapture.cs | 99 +++++++++++++++++++++ 5 files changed, 273 insertions(+), 54 deletions(-) create mode 100644 FlashpointCC/ScreenCapture.cs diff --git a/FlashpointCC/CurationForm.Designer.cs b/FlashpointCC/CurationForm.Designer.cs index 3b22c72..5e79f5c 100644 --- a/FlashpointCC/CurationForm.Designer.cs +++ b/FlashpointCC/CurationForm.Designer.cs @@ -60,15 +60,17 @@ private void InitializeComponent() this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); this.label11 = new System.Windows.Forms.Label(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.label14 = new System.Windows.Forms.Label(); + this.treeViewIcons = new System.Windows.Forms.ImageList(this.components); this.label12 = new System.Windows.Forms.Label(); this.label13 = new System.Windows.Forms.Label(); this.saveFileDialog = new System.Windows.Forms.SaveFileDialog(); - this.treeView = new System.Windows.Forms.TreeView(); - this.treeViewIcons = new System.Windows.Forms.ImageList(this.components); this.extremeCheckBox = new System.Windows.Forms.CheckBox(); this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.flagAsExecutableToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.label14 = new System.Windows.Forms.Label(); + this.treeView = new System.Windows.Forms.TreeView(); + this.captureLogoButton = new System.Windows.Forms.Button(); + this.captureScreenshotButton = new System.Windows.Forms.Button(); this.tableLayoutPanel1.SuspendLayout(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); @@ -323,7 +325,7 @@ private void InitializeComponent() this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; this.logoPictureBox.Location = new System.Drawing.Point(3, 16); this.logoPictureBox.Name = "logoPictureBox"; - this.logoPictureBox.Size = new System.Drawing.Size(201, 165); + this.logoPictureBox.Size = new System.Drawing.Size(201, 141); this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.logoPictureBox.TabIndex = 2; this.logoPictureBox.TabStop = false; @@ -333,7 +335,7 @@ private void InitializeComponent() this.screenshotPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; this.screenshotPictureBox.Location = new System.Drawing.Point(210, 16); this.screenshotPictureBox.Name = "screenshotPictureBox"; - this.screenshotPictureBox.Size = new System.Drawing.Size(201, 165); + this.screenshotPictureBox.Size = new System.Drawing.Size(201, 141); this.screenshotPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.screenshotPictureBox.TabIndex = 3; this.screenshotPictureBox.TabStop = false; @@ -364,33 +366,33 @@ private void InitializeComponent() this.imagePanel.Controls.Add(this.tableLayoutPanel3); this.imagePanel.Location = new System.Drawing.Point(12, 235); this.imagePanel.Name = "imagePanel"; - this.imagePanel.Size = new System.Drawing.Size(629, 203); + this.imagePanel.Size = new System.Drawing.Size(629, 225); this.imagePanel.TabIndex = 6; // // tableLayoutPanel3 // this.tableLayoutPanel3.ColumnCount = 1; this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Controls.Add(this.label11, 0, 1); + this.tableLayoutPanel3.Controls.Add(this.label11, 0, 2); this.tableLayoutPanel3.Controls.Add(this.tableLayoutPanel2, 0, 0); - this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 6); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; - this.tableLayoutPanel3.RowCount = 2; + this.tableLayoutPanel3.RowCount = 3; this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.Size = new System.Drawing.Size(629, 203); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(629, 216); this.tableLayoutPanel3.TabIndex = 8; // // label11 // - this.label11.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.label11.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); this.label11.AutoSize = true; - this.label11.Location = new System.Drawing.Point(250, 190); + this.label11.Location = new System.Drawing.Point(188, 196); this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(129, 13); + this.label11.Size = new System.Drawing.Size(252, 20); this.label11.TabIndex = 0; - this.label11.Text = "Drag and drop to change."; + this.label11.Text = "Drag and drop files to add logo, image, and content."; // // tableLayoutPanel2 // @@ -404,15 +406,37 @@ private void InitializeComponent() this.tableLayoutPanel2.Controls.Add(this.screenshotPictureBox, 1, 1); this.tableLayoutPanel2.Controls.Add(this.label12, 0, 0); this.tableLayoutPanel2.Controls.Add(this.label13, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.captureLogoButton, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.captureScreenshotButton, 1, 2); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 3); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; - this.tableLayoutPanel2.RowCount = 2; + this.tableLayoutPanel2.RowCount = 3; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(623, 184); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(623, 190); this.tableLayoutPanel2.TabIndex = 3; // + // label14 + // + this.label14.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(496, 0); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(44, 13); + this.label14.TabIndex = 8; + this.label14.Text = "Content"; + // + // treeViewIcons + // + this.treeViewIcons.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("treeViewIcons.ImageStream"))); + this.treeViewIcons.TransparentColor = System.Drawing.Color.Transparent; + this.treeViewIcons.Images.SetKeyName(0, "fileIcon.png"); + this.treeViewIcons.Images.SetKeyName(1, "folderIcon.png"); + this.treeViewIcons.Images.SetKeyName(2, "folderOpenIcon.png"); + this.treeViewIcons.Images.SetKeyName(3, "joystick.png"); + // // label12 // this.label12.Anchor = System.Windows.Forms.AnchorStyles.Top; @@ -439,26 +463,6 @@ private void InitializeComponent() this.saveFileDialog.Filter = "ZIP Archives (*.zip)|*.zip"; this.saveFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.saveFileDialog_FileOk); // - // treeView - // - this.treeView.Dock = System.Windows.Forms.DockStyle.Fill; - this.treeView.ImageIndex = 0; - this.treeView.ImageList = this.treeViewIcons; - this.treeView.Location = new System.Drawing.Point(417, 16); - this.treeView.Name = "treeView"; - this.treeView.SelectedImageIndex = 0; - this.treeView.Size = new System.Drawing.Size(203, 165); - this.treeView.TabIndex = 7; - // - // treeViewIcons - // - this.treeViewIcons.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("treeViewIcons.ImageStream"))); - this.treeViewIcons.TransparentColor = System.Drawing.Color.Transparent; - this.treeViewIcons.Images.SetKeyName(0, "fileIcon.png"); - this.treeViewIcons.Images.SetKeyName(1, "folderIcon.png"); - this.treeViewIcons.Images.SetKeyName(2, "folderOpenIcon.png"); - this.treeViewIcons.Images.SetKeyName(3, "joystick.png"); - // // extremeCheckBox // this.extremeCheckBox.AutoSize = true; @@ -483,15 +487,38 @@ private void InitializeComponent() this.flagAsExecutableToolStripMenuItem.Text = "Flag as Executable"; this.flagAsExecutableToolStripMenuItem.Click += new System.EventHandler(this.flagAsExecutableToolStripMenuItem_Click); // - // label14 + // treeView // - this.label14.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(496, 0); - this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(44, 13); - this.label14.TabIndex = 8; - this.label14.Text = "Content"; + this.treeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.treeView.ImageIndex = 0; + this.treeView.ImageList = this.treeViewIcons; + this.treeView.Location = new System.Drawing.Point(417, 16); + this.treeView.Name = "treeView"; + this.treeView.SelectedImageIndex = 0; + this.treeView.Size = new System.Drawing.Size(203, 141); + this.treeView.TabIndex = 7; + // + // captureLogoButton + // + this.captureLogoButton.Anchor = System.Windows.Forms.AnchorStyles.None; + this.captureLogoButton.Location = new System.Drawing.Point(66, 163); + this.captureLogoButton.Name = "captureLogoButton"; + this.captureLogoButton.Size = new System.Drawing.Size(75, 23); + this.captureLogoButton.TabIndex = 9; + this.captureLogoButton.Text = "Capture"; + this.captureLogoButton.UseVisualStyleBackColor = true; + this.captureLogoButton.Click += new System.EventHandler(this.captureLogoButton_Click); + // + // captureScreenshotButton + // + this.captureScreenshotButton.Anchor = System.Windows.Forms.AnchorStyles.None; + this.captureScreenshotButton.Location = new System.Drawing.Point(273, 163); + this.captureScreenshotButton.Name = "captureScreenshotButton"; + this.captureScreenshotButton.Size = new System.Drawing.Size(75, 23); + this.captureScreenshotButton.TabIndex = 10; + this.captureScreenshotButton.Text = "Capture"; + this.captureScreenshotButton.UseVisualStyleBackColor = true; + this.captureScreenshotButton.Click += new System.EventHandler(this.captureScreenshotButton_Click); // // CurationForm // @@ -554,7 +581,6 @@ private void InitializeComponent() private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; private System.Windows.Forms.Label label11; private System.Windows.Forms.SaveFileDialog saveFileDialog; - private System.Windows.Forms.TreeView treeView; private System.Windows.Forms.CheckBox extremeCheckBox; private System.Windows.Forms.Label label12; private System.Windows.Forms.Label label13; @@ -564,5 +590,8 @@ private void InitializeComponent() private System.Windows.Forms.ComboBox platformComboBox; private System.Windows.Forms.ComboBox statusComboBox; private System.Windows.Forms.Label label14; + private System.Windows.Forms.TreeView treeView; + private System.Windows.Forms.Button captureLogoButton; + private System.Windows.Forms.Button captureScreenshotButton; } } \ No newline at end of file diff --git a/FlashpointCC/CurationForm.cs b/FlashpointCC/CurationForm.cs index 16c1bc1..d7c1566 100644 --- a/FlashpointCC/CurationForm.cs +++ b/FlashpointCC/CurationForm.cs @@ -5,11 +5,13 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.IO.Compression; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -25,6 +27,21 @@ public partial class CurationForm : Form private TreeNode executable; private string flashpointPath; + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern int GetClientRect(System.IntPtr hWnd, ref Rectangle lpRECT); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] + private static extern bool IsIconic(IntPtr hwnd); + + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool IsWindowVisible(IntPtr hWnd); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern int SetForegroundWindow(int hwnd); + + public static Bitmap logo; + public static Bitmap gamescreen; + public CurationForm(string flashpointPath) { this.flashpointPath = flashpointPath; @@ -176,6 +193,22 @@ public static string GetLaunchCommand(string commandLine, TreeNode executable, s return commandLine; } + public bool IsValidImage(string path) + { + string[] extensions = { "png", "jpg", "jpeg", "gif", "bmp" }; + + if (extensions.Contains(Path.GetExtension(path).ToLowerInvariant().Replace(".", ""))) + { + return true; + } + + else + { + MessageBox.Show("Please use a valid image format (PNG, JPG, JPEG, GIF, BMP)", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return false; + } + } + private void ScreenshotPictureBox_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; @@ -190,8 +223,11 @@ private void ScreenshotPictureBox_DragDrop(object sender, DragEventArgs e) { foreach (string pic in ((string[])e.Data.GetData(DataFormats.FileDrop))) { - Image img = Image.FromFile(pic); - screenshotPictureBox.Image = img; + if (IsValidImage(pic)) + { + Image img = Image.FromFile(pic); + screenshotPictureBox.Image = img; + } } } @@ -199,8 +235,11 @@ private void LogoPictureBox_DragDrop(object sender, DragEventArgs e) { foreach (string pic in ((string[])e.Data.GetData(DataFormats.FileDrop))) { - Image img = Image.FromFile(pic); - logoPictureBox.Image = img; + if (IsValidImage(pic)) + { + Image img = Image.FromFile(pic); + logoPictureBox.Image = img; + } } } @@ -357,5 +396,56 @@ private void curateButton_Click(object sender, EventArgs e) screenshotPictureBox.Image.Save(ssPath, ImageFormat.Png); MessageBox.Show("Added to Flashpoint!", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information); } + + public Bitmap CaptureGameWindow() + { + Platform platform = (Platform)platformComboBox.SelectedItem; + Process[] players = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(platform.ApplicationPath)); + + if (players.Length == 0) + { + MessageBox.Show("No game window detected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return null; + } + + IntPtr player = players[0].MainWindowHandle; + + Rectangle pic = new Rectangle(); + GetClientRect(player, ref pic); + + ScreenShot.ScreenCapture screenshot = new ScreenShot.ScreenCapture(); + Bitmap image = (Bitmap)screenshot.CaptureWindow(player); + + int border = (image.Width - pic.Width) / 2; + int top = image.Height - pic.Height - border; + + Rectangle crop = new Rectangle(border, top, pic.Width, pic.Height); + + if (IsIconic(player) | crop.IsEmpty | crop.Width == 0 | crop.Height == 0) + { + MessageBox.Show("Please make sure the game is not minimized", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + SetForegroundWindow((int)player); + SendKeys.SendWait("~"); + return null; + } + + else + { + Bitmap cropped = image.Clone(crop, image.PixelFormat); + return cropped; + } + } + + private void captureLogoButton_Click(object sender, EventArgs e) + { + logo = CaptureGameWindow(); + logoPictureBox.Image = logo; + } + + private void captureScreenshotButton_Click(object sender, EventArgs e) + { + gamescreen = CaptureGameWindow(); + screenshotPictureBox.Image = gamescreen; + } } } diff --git a/FlashpointCC/CurationForm.resx b/FlashpointCC/CurationForm.resx index 410ab57..591c874 100644 --- a/FlashpointCC/CurationForm.resx +++ b/FlashpointCC/CurationForm.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 17, 17 - 146, 17 @@ -128,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAE - CgAAAk1TRnQBSQFMAgEBBAEAAVABAAFQAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CgAAAk1TRnQBSQFMAgEBBAEAAVgBAAFYAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -173,6 +170,9 @@ AQEB+AEfAcABBwEAAR8BAAEDAfgBHwHAAQ8BAAEfAQABPwH4AR8E/wGAAT8B/AE/Cw== + + 17, 17 + 273, 17 diff --git a/FlashpointCC/FlashpointCC.csproj b/FlashpointCC/FlashpointCC.csproj index efc184c..2b42f67 100644 --- a/FlashpointCC/FlashpointCC.csproj +++ b/FlashpointCC/FlashpointCC.csproj @@ -58,6 +58,7 @@ + Form diff --git a/FlashpointCC/ScreenCapture.cs b/FlashpointCC/ScreenCapture.cs new file mode 100644 index 0000000..1ed0c09 --- /dev/null +++ b/FlashpointCC/ScreenCapture.cs @@ -0,0 +1,99 @@ +using Microsoft.VisualBasic; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Drawing.Imaging; + + +namespace ScreenShot +{ + /// Provides functions to capture the entire screen, or a particular window, and save it to a file. + public class ScreenCapture + { + /// Creates an Image object containing a screen shot of a specific window + public Image CaptureWindow(IntPtr handle) + { + int SRCCOPY = 0xcc0020; + // get te hDC of the target window + IntPtr hdcSrc = User32.GetWindowDC(handle); + // get the size + User32.RECT windowRect = new User32.RECT(); + User32.GetWindowRect(handle, ref windowRect); + int width = windowRect.right - windowRect.left; + int height = windowRect.bottom - windowRect.top; + // create a device context we can copy to + IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc); + // create a bitmap we can copy it to, + // using GetDeviceCaps to get the width/height + IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height); + // select the bitmap object + IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap); + // bitblt over + GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY); + // restore selection + GDI32.SelectObject(hdcDest, hOld); + // clean up + GDI32.DeleteDC(hdcDest); + User32.ReleaseDC(handle, hdcSrc); + + // get a .NET image object for it + Image img = Image.FromHbitmap(hBitmap); + // free up the Bitmap object + GDI32.DeleteObject(hBitmap); + + return img; + } + //CaptureWindow + + /// Helper class containing Gdi32 API functions + private class GDI32 + { + public int SRCCOPY = 0xcc0020; + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 BitBlt(IntPtr hDestDC, Int32 x, Int32 y, Int32 nWidth, Int32 nHeight, IntPtr hSrcDC, Int32 xSrc, Int32 ySrc, Int32 dwRop); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, Int32 nWidth, Int32 nHeight); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CreateCompatibleDC(IntPtr hdc); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 DeleteDC(IntPtr hdc); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 DeleteObject(IntPtr hObject); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); + // BitBlt dwRop parameter + + } + //GDI32 + /// Helper class containing User32 API functions + public class User32 + { + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int left; + public int top; + public int right; + public int bottom; + } + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr GetDesktopWindow(); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr GetWindowDC(IntPtr hwnd); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 GetWindowRect(IntPtr hwnd, ref RECT lpRect); + //RECT + + + } + //User32 + } + //ScreenCapture +} +//ScreenShot From 1d54068be4a37493c2ad27f189d0c42ff8f86c80 Mon Sep 17 00:00:00 2001 From: Seirade <45798662+Seirade@users.noreply.github.com> Date: Wed, 27 Feb 2019 22:21:40 -0500 Subject: [PATCH 2/3] Additions to the GUI - Added Label for instructions on how to add Logo and Screenshot - Added Capture, Browse, and X buttons for Logo and Screenshot - Added Swap button for switching Logo and Screenshot images - Added placeholder Crop button for Logo - Changed PictureBoxes to have dotted outline for a more modern feel - Fixed some rendering issues with PictureBox outlines --- FlashpointCC/CurationForm.Designer.cs | 29 ++-- FlashpointCC/CurationForm.cs | 219 +++++++++++++++++++++++++- FlashpointCC/CurationForm.resx | 2 +- FlashpointCC/FlashpointCC.csproj | 1 + FlashpointCC/ScreenCapture.cs | 99 ++++++++++++ 5 files changed, 327 insertions(+), 23 deletions(-) create mode 100644 FlashpointCC/ScreenCapture.cs diff --git a/FlashpointCC/CurationForm.Designer.cs b/FlashpointCC/CurationForm.Designer.cs index bb06771..021721f 100644 --- a/FlashpointCC/CurationForm.Designer.cs +++ b/FlashpointCC/CurationForm.Designer.cs @@ -76,12 +76,12 @@ private void InitializeComponent() this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.importCurationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.addToFlashpointToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.selectFlashpointPathToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.openCurationFileDialog = new System.Windows.Forms.OpenFileDialog(); this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); - this.selectFlashpointPathToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip.SuspendLayout(); this.groupBox1.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); @@ -581,7 +581,7 @@ private void InitializeComponent() // this.newToolStripMenuItem.Name = "newToolStripMenuItem"; this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); - this.newToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.newToolStripMenuItem.Size = new System.Drawing.Size(199, 22); this.newToolStripMenuItem.Text = "&New"; this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); // @@ -589,28 +589,35 @@ private void InitializeComponent() // this.importCurationToolStripMenuItem.Name = "importCurationToolStripMenuItem"; this.importCurationToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.I))); - this.importCurationToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.importCurationToolStripMenuItem.Size = new System.Drawing.Size(199, 22); this.importCurationToolStripMenuItem.Text = "&Import Curation"; this.importCurationToolStripMenuItem.Click += new System.EventHandler(this.importCurationToolStripMenuItem_Click); // // addToFlashpointToolStripMenuItem // this.addToFlashpointToolStripMenuItem.Name = "addToFlashpointToolStripMenuItem"; - this.addToFlashpointToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.addToFlashpointToolStripMenuItem.Size = new System.Drawing.Size(199, 22); this.addToFlashpointToolStripMenuItem.Text = "&Add to Flashpoint"; this.addToFlashpointToolStripMenuItem.Visible = false; this.addToFlashpointToolStripMenuItem.Click += new System.EventHandler(this.addToFlashpointToolStripMenuItem_Click); // + // selectFlashpointPathToolStripMenuItem + // + this.selectFlashpointPathToolStripMenuItem.Name = "selectFlashpointPathToolStripMenuItem"; + this.selectFlashpointPathToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.selectFlashpointPathToolStripMenuItem.Text = "Select Flashpoint Path..."; + this.selectFlashpointPathToolStripMenuItem.Click += new System.EventHandler(this.selectFlashpointPathToolStripMenuItem_Click); + // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(193, 6); + this.toolStripSeparator1.Size = new System.Drawing.Size(196, 6); // // preferencesToolStripMenuItem // this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; this.preferencesToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); - this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(199, 22); this.preferencesToolStripMenuItem.Text = "&Preferences"; this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); // @@ -618,7 +625,7 @@ private void InitializeComponent() // this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); - this.exitToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(199, 22); this.exitToolStripMenuItem.Text = "E&xit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); // @@ -627,13 +634,6 @@ private void InitializeComponent() this.openCurationFileDialog.DefaultExt = "zip"; this.openCurationFileDialog.Filter = "ZIP Archives (*.zip)|*.zip"; // - // selectFlashpointPathToolStripMenuItem - // - this.selectFlashpointPathToolStripMenuItem.Name = "selectFlashpointPathToolStripMenuItem"; - this.selectFlashpointPathToolStripMenuItem.Size = new System.Drawing.Size(199, 22); - this.selectFlashpointPathToolStripMenuItem.Text = "Select Flashpoint Path..."; - this.selectFlashpointPathToolStripMenuItem.Click += new System.EventHandler(this.selectFlashpointPathToolStripMenuItem_Click); - // // CurationForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -647,6 +647,7 @@ private void InitializeComponent() this.MaximizeBox = false; this.Name = "CurationForm"; this.Text = "FlashpointCC"; + this.Move += new System.EventHandler(this.CurationForm_Move); this.contextMenuStrip.ResumeLayout(false); this.groupBox1.ResumeLayout(false); this.tableLayoutPanel1.ResumeLayout(false); diff --git a/FlashpointCC/CurationForm.cs b/FlashpointCC/CurationForm.cs index c4451ee..04334e4 100644 --- a/FlashpointCC/CurationForm.cs +++ b/FlashpointCC/CurationForm.cs @@ -5,12 +5,14 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -26,6 +28,17 @@ public partial class CurationForm : Form private Curation curation; private TreeNode executable; private string flashpointPath; + + public delegate void SetImage(Image image); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern int GetClientRect(System.IntPtr hWnd, ref Rectangle lpRECT); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] + private static extern bool IsIconic(IntPtr hwnd); + + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern int SetForegroundWindow(int hwnd); public CurationForm() { @@ -44,15 +57,96 @@ public CurationForm() screenshotPictureBox.DragDrop += ScreenshotPictureBox_DragDrop; profileComboBox.Items.AddRange(ProfileEditorForm.LoadProfiles()); genreComboBox.Items.AddRange(Curation.Genres); - genreComboBox.SelectedIndex = 0; playModeComboBox.Items.AddRange(Curation.Modes); - playModeComboBox.SelectedIndex = 0; statusComboBox.Items.AddRange(Curation.Statuses); - statusComboBox.SelectedIndex = 0; treeView.MouseDown += TreeView_MouseDown; treeView.AfterExpand += TreeView_AfterExpand; treeView.AfterCollapse += TreeView_AfterCollapse; Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); + + SetImage SetL = SetLogo; + SetImage SetSS = SetScreenshot; + + //Create instructions and Browse/Capture/Remove/Crop buttons for logo PictureBox + Label logoinstructions = new Label(); + logoinstructions.TextAlign = ContentAlignment.MiddleCenter; + logoinstructions.AutoSize = true; + logoinstructions.Text = "Drag and drop an image here, or..."; + logoPictureBox.Controls.Add(logoinstructions); + logoinstructions.Location = new Point((logoPictureBox.Width / 2) - (logoinstructions.Width / 2), (logoPictureBox.Height / 2) - (logoinstructions.Height / 2) - 15); + + Button logocapturebutton = new Button(); + logocapturebutton.Text = "Capture"; + logoPictureBox.Controls.Add(logocapturebutton); + logocapturebutton.Click += (sender, e) => { CaptureWindow(SetL); }; + logocapturebutton.Location = new Point((logoPictureBox.Width / 2) - logocapturebutton.Width - 5, (logoPictureBox.Height / 2) - (logocapturebutton.Height / 2) + 10); + + Button logobrowsebutton = new Button(); + logobrowsebutton.Text = "Browse..."; + logoPictureBox.Controls.Add(logobrowsebutton); + logobrowsebutton.Click += (sender, e) => { BrowseForImage(SetL); }; + logobrowsebutton.Location = new Point((logoPictureBox.Width / 2) + 5, (logoPictureBox.Height / 2) - (logobrowsebutton.Height / 2) + 10); + + Button logoremovebutton = new Button(); + logoremovebutton.Text = "X"; + logoremovebutton.Name = "logoremovebutton"; + logoremovebutton.Visible = false; + logoremovebutton.Width = 26; + logoremovebutton.BackColor = Color.PaleVioletRed; + logoremovebutton.ForeColor = Color.White; + logoremovebutton.Font = new Font(logoremovebutton.Font, FontStyle.Bold); + logoPictureBox.Controls.Add(logoremovebutton); + logoremovebutton.Click += (sender, e) => { SetLogo(null); }; + logoremovebutton.Location = new Point(logoPictureBox.Width - logoremovebutton.Width - 5, 5); + + //Button logocropbutton = new Button(); + //logocropbutton.Text = "Crop"; + //logocropbutton.Name = "logocropbutton"; + //logocropbutton.Visible = false; + //logoPictureBox.Controls.Add(logocropbutton); + //logocropbutton.Location = new Point((logoPictureBox.Width / 2) - (logocropbutton.Width / 2), logoPictureBox.Height - logocropbutton.Height - 8); + + //Create instructions and Browse/Capture/Remove buttons for screenshot PictureBox + Label screenshotinstructions = new Label(); + screenshotinstructions.TextAlign = ContentAlignment.MiddleCenter; + screenshotinstructions.AutoSize = true; + screenshotinstructions.Text = "Drag and drop an image here, or..."; + screenshotPictureBox.Controls.Add(screenshotinstructions); + screenshotinstructions.Location = new Point((screenshotPictureBox.Width / 2) - (screenshotinstructions.Width / 2), (screenshotPictureBox.Height / 2) - (screenshotinstructions.Height / 2) - 15); + + Button screenshotcapturebutton = new Button(); + screenshotcapturebutton.Text = "Capture"; + screenshotPictureBox.Controls.Add(screenshotcapturebutton); + screenshotcapturebutton.Click += (sender, e) => { CaptureWindow(SetSS); }; + screenshotcapturebutton.Location = new Point((screenshotPictureBox.Width / 2) - screenshotcapturebutton.Width - 5, (screenshotPictureBox.Height / 2) - (screenshotcapturebutton.Height / 2) + 10); + + Button screenshotbrowsebutton = new Button(); + screenshotbrowsebutton.Text = "Browse..."; + screenshotPictureBox.Controls.Add(screenshotbrowsebutton); + screenshotbrowsebutton.Click += (sender, e) => { BrowseForImage(SetSS); }; + screenshotbrowsebutton.Location = new Point((screenshotPictureBox.Width / 2) + 5, (screenshotPictureBox.Height / 2) - (screenshotbrowsebutton.Height / 2) + 10); + + Button screenshotremovebutton = new Button(); + screenshotremovebutton.Text = "X"; + screenshotremovebutton.Name = "screenshotremovebutton"; + screenshotremovebutton.Visible = false; + screenshotremovebutton.Width = 26; + screenshotremovebutton.BackColor = Color.PaleVioletRed; + screenshotremovebutton.ForeColor = Color.White; + screenshotremovebutton.Font = new Font(screenshotremovebutton.Font, FontStyle.Bold); + screenshotPictureBox.Controls.Add(screenshotremovebutton); + screenshotremovebutton.Click += (sender, e) => { SetScreenshot(null); }; + screenshotremovebutton.Location = new Point(screenshotPictureBox.Width - screenshotremovebutton.Width - 5, 5); + + //Create swap button + Button swapbutton = new Button(); + swapbutton.Text = "<- Swap ->"; + swapbutton.Visible = false; + swapbutton.Name = "swapbutton"; + this.Controls.Add(swapbutton); + swapbutton.Click += (sender, e) => { SwapPictures(); }; + swapbutton.Location = new Point(tableLayoutPanel2.Location.X + (tableLayoutPanel2.Width/2) - (swapbutton.Width/2), tableLayoutPanel2.Location.Y + tableLayoutPanel2.Height - 10); + swapbutton.BringToFront(); } private void ProfileEditor_ProfileChange(Profile profile) @@ -124,22 +218,120 @@ private void TreeView_DragDrop(object sender, DragEventArgs e) private void ScreenshotPictureBox_Paint(object sender, PaintEventArgs e) { - ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, Color.Gray, ButtonBorderStyle.Solid); + Pen pen = new Pen(Color.FromArgb(255, 170, 170, 170), 2.0F); + pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; + e.Graphics.DrawRectangle(pen, e.ClipRectangle.X + 1, e.ClipRectangle.Y + 1, e.ClipRectangle.Width - 2, e.ClipRectangle.Height - 2); + pen.Dispose(); } private void LogoPictureBox_Paint(object sender, PaintEventArgs e) { - ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, Color.Gray, ButtonBorderStyle.Solid); + Pen pen = new Pen(Color.FromArgb(255, 170, 170, 170), 2.0F); + pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; + e.Graphics.DrawRectangle(pen, e.ClipRectangle.X + 1, e.ClipRectangle.Y + 1, e.ClipRectangle.Width - 2, e.ClipRectangle.Height - 2); + pen.Dispose(); } public void SetLogo(Image image) { logoPictureBox.Image = image; + this.Controls.Find("swapbutton", false)[0].Visible = (logoPictureBox.Image == null && screenshotPictureBox.Image == null) ? false : true; + + foreach (Control child in logoPictureBox.Controls) + { + child.Visible = (image == null) ? true : false; + if (child.Name == "logocropbutton" | child.Name == "logoremovebutton") + { + child.Visible = (image == null) ? false : true; + } + } + + this.Refresh(); } public void SetScreenshot(Image image) { screenshotPictureBox.Image = image; + this.Controls.Find("swapbutton", false)[0].Visible = (logoPictureBox.Image == null && screenshotPictureBox.Image == null) ? false : true; + + foreach (Control child in screenshotPictureBox.Controls) + { + child.Visible = (image == null) ? true : false; + if (child.Name == "screenshotremovebutton") + { + child.Visible = (image == null) ? false : true; + } + } + + this.Refresh(); + } + + public void CaptureWindow(SetImage pass) + { + Profile profile = (Profile)profileComboBox.SelectedItem; + + if(profile == null) + { + MessageBox.Show("Please select a Profile", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + Process[] players = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(profile.ApplicationPath)); + + if(players.Length == 0) + { + MessageBox.Show("No game window detected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + IntPtr player = players[0].MainWindowHandle; + + Rectangle pic = new Rectangle(); + GetClientRect(player, ref pic); + + ScreenShot.ScreenCapture screenshot = new ScreenShot.ScreenCapture(); + Bitmap image = (Bitmap)screenshot.CaptureWindow(player); + + int border = (image.Width - pic.Width) / 2; + int top = image.Height - pic.Height - border; + + Rectangle crop = new Rectangle(border, top, pic.Width, pic.Height); + + if(IsIconic(player) | crop.IsEmpty | crop.Width == 0 | crop.Height == 0) + { + MessageBox.Show("Please make sure the game is not minimized", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + SetForegroundWindow((int)player); + SendKeys.SendWait("~"); + return; + } + + else + { + Bitmap cropped = image.Clone(crop, image.PixelFormat); + pass(cropped); + } + } + + public void BrowseForImage(SetImage pass) + { + OpenFileDialog browse = new OpenFileDialog(); + browse.FilterIndex = 2; + browse.Filter = "BMP Image (*.bmp)|*.bmp|PNG Image (*.png)|*.png|JPEG Image (*.jpg, *.jpeg)|*.jpg; *.jpeg|GIF Image (*.gif)|*.gif"; + browse.CheckFileExists = true; + browse.CheckPathExists = true; + browse.ValidateNames = true; + DialogResult result = browse.ShowDialog(); + if(result == DialogResult.OK) + { + pass(LoadImage(browse.FileName)); + } + } + + public void SwapPictures() + { + Image temp = logoPictureBox.Image; + SetLogo(screenshotPictureBox.Image); + SetScreenshot(temp); } public void SetContent(IContentSource content) @@ -193,12 +385,18 @@ private void LogoPictureBox_DragEnter(object sender, DragEventArgs e) e.Effect = DragDropEffects.Copy; } + public Image LoadImage(string path) + { + return Image.FromFile(path); + } + private void ScreenshotPictureBox_DragDrop(object sender, DragEventArgs e) { foreach (string pic in ((string[])e.Data.GetData(DataFormats.FileDrop))) { - Image img = Image.FromFile(pic); + Image img = LoadImage(pic); screenshotPictureBox.Image = img; + SetScreenshot(img); } } @@ -206,8 +404,8 @@ private void LogoPictureBox_DragDrop(object sender, DragEventArgs e) { foreach (string pic in ((string[])e.Data.GetData(DataFormats.FileDrop))) { - Image img = Image.FromFile(pic); - logoPictureBox.Image = img; + Image img = LoadImage(pic); + SetLogo(img); } } @@ -441,5 +639,10 @@ private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); } + + private void CurationForm_Move(object sender, EventArgs e) + { + this.Refresh(); + } } } diff --git a/FlashpointCC/CurationForm.resx b/FlashpointCC/CurationForm.resx index 5899b23..e181852 100644 --- a/FlashpointCC/CurationForm.resx +++ b/FlashpointCC/CurationForm.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAE - CgAAAk1TRnQBSQFMAgEBBAEAAegBAAHoAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CgAAAk1TRnQBSQFMAgEBBAEAAfgBAAH4AQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/FlashpointCC/FlashpointCC.csproj b/FlashpointCC/FlashpointCC.csproj index efd06e5..8216392 100644 --- a/FlashpointCC/FlashpointCC.csproj +++ b/FlashpointCC/FlashpointCC.csproj @@ -68,6 +68,7 @@ ProfileEditorForm.cs + diff --git a/FlashpointCC/ScreenCapture.cs b/FlashpointCC/ScreenCapture.cs new file mode 100644 index 0000000..1ed0c09 --- /dev/null +++ b/FlashpointCC/ScreenCapture.cs @@ -0,0 +1,99 @@ +using Microsoft.VisualBasic; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Drawing.Imaging; + + +namespace ScreenShot +{ + /// Provides functions to capture the entire screen, or a particular window, and save it to a file. + public class ScreenCapture + { + /// Creates an Image object containing a screen shot of a specific window + public Image CaptureWindow(IntPtr handle) + { + int SRCCOPY = 0xcc0020; + // get te hDC of the target window + IntPtr hdcSrc = User32.GetWindowDC(handle); + // get the size + User32.RECT windowRect = new User32.RECT(); + User32.GetWindowRect(handle, ref windowRect); + int width = windowRect.right - windowRect.left; + int height = windowRect.bottom - windowRect.top; + // create a device context we can copy to + IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc); + // create a bitmap we can copy it to, + // using GetDeviceCaps to get the width/height + IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height); + // select the bitmap object + IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap); + // bitblt over + GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY); + // restore selection + GDI32.SelectObject(hdcDest, hOld); + // clean up + GDI32.DeleteDC(hdcDest); + User32.ReleaseDC(handle, hdcSrc); + + // get a .NET image object for it + Image img = Image.FromHbitmap(hBitmap); + // free up the Bitmap object + GDI32.DeleteObject(hBitmap); + + return img; + } + //CaptureWindow + + /// Helper class containing Gdi32 API functions + private class GDI32 + { + public int SRCCOPY = 0xcc0020; + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 BitBlt(IntPtr hDestDC, Int32 x, Int32 y, Int32 nWidth, Int32 nHeight, IntPtr hSrcDC, Int32 xSrc, Int32 ySrc, Int32 dwRop); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, Int32 nWidth, Int32 nHeight); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CreateCompatibleDC(IntPtr hdc); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 DeleteDC(IntPtr hdc); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 DeleteObject(IntPtr hObject); + [DllImport("gdi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); + // BitBlt dwRop parameter + + } + //GDI32 + /// Helper class containing User32 API functions + public class User32 + { + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int left; + public int top; + public int right; + public int bottom; + } + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr GetDesktopWindow(); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr GetWindowDC(IntPtr hwnd); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); + [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + public static extern Int32 GetWindowRect(IntPtr hwnd, ref RECT lpRect); + //RECT + + + } + //User32 + } + //ScreenCapture +} +//ScreenShot From 2ef59192e3b7543b8e6ad53e858bdb1d4f2bb522 Mon Sep 17 00:00:00 2001 From: Seirade <45798662+Seirade@users.noreply.github.com> Date: Thu, 28 Feb 2019 02:49:14 -0500 Subject: [PATCH 3/3] Tweaks - Reordered Curation class fields - Added Extreme to Curation class - Added missing values to Modes and Statuses in Curation class - Fixed Genre dropdown from opening in the up direction - Fixed small issue with image formats when saving a curation using captured images - Changed behavior of New Curation menu item --- FlashpointCC/Curation.cs | 43 +++++++++---- FlashpointCC/CurationForm.Designer.cs | 4 +- FlashpointCC/CurationForm.cs | 28 +++++++-- FlashpointCC/CurationForm.resx | 88 +++++++++++++-------------- 4 files changed, 102 insertions(+), 61 deletions(-) diff --git a/FlashpointCC/Curation.cs b/FlashpointCC/Curation.cs index 0ee0551..c1aa365 100644 --- a/FlashpointCC/Curation.cs +++ b/FlashpointCC/Curation.cs @@ -10,16 +10,41 @@ namespace FlashpointCurator { public class Curation { - public static string[] Modes { get { return new string[] { "Single Player", "Multiplayer" }; } } + public static string[] Modes { get + { + return new string[] + { + "Single Player", + "Multiplayer", + "Cooperative" + }; + } } - public static string[] Statuses { get { - return new string[] { - "Playable", "Playable (Hacked)", "Playable (Web Browser)", "Playable (Web Browser) (Hacked)", "Playable (Partial)" }; } } + public static string[] Statuses { get + { + return new string[] + { + "Playable", + "Playable (Partial)", + "Playable (Hacked)", + "Playable (Web Browser)", + "Playable (Web Browser) (Hacked)", + "Not Working" + }; + } } public static string[] Genres { get; set; } public string Title { get; set; } + public string Series { get; set; } + + public string Platform { get; set; } + + public string Developer { get; set; } + + public string Publisher { get; set; } + [MetaIgnore] public DateTime? ReleaseDate { get; set; } @@ -45,21 +70,15 @@ public string ReleaseDateString public string Genre { get; set; } - public string Developer { get; set; } - - public string Series { get; set; } - [MetaElement(ElementName = "Play Mode")] public string PlayMode { get; set; } + public string Extreme { get; set; } + public string Status { get; set; } public string Source { get; set; } - public string Platform { get; set; } - - public string Publisher { get; set; } - [MetaElement(ElementName = "Launch Command")] public string LaunchCommand { get; set; } diff --git a/FlashpointCC/CurationForm.Designer.cs b/FlashpointCC/CurationForm.Designer.cs index 021721f..a0172da 100644 --- a/FlashpointCC/CurationForm.Designer.cs +++ b/FlashpointCC/CurationForm.Designer.cs @@ -208,7 +208,9 @@ private void InitializeComponent() // this.genreComboBox.Dock = System.Windows.Forms.DockStyle.Fill; this.genreComboBox.FormattingEnabled = true; + this.genreComboBox.IntegralHeight = false; this.genreComboBox.Location = new System.Drawing.Point(3, 3); + this.genreComboBox.MaxDropDownItems = 17; this.genreComboBox.Name = "genreComboBox"; this.genreComboBox.Size = new System.Drawing.Size(189, 21); this.genreComboBox.TabIndex = 19; @@ -691,7 +693,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox titleTextBox; private System.Windows.Forms.DateTimePicker dateTimePicker; private System.Windows.Forms.TextBox developerTextBox; - private System.Windows.Forms.ComboBox genreComboBox; private System.Windows.Forms.TextBox seriesTextBox; private System.Windows.Forms.ComboBox playModeComboBox; private System.Windows.Forms.CheckBox extremeCheckBox; @@ -725,5 +726,6 @@ private void InitializeComponent() private System.Windows.Forms.OpenFileDialog openCurationFileDialog; private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog; private System.Windows.Forms.ToolStripMenuItem selectFlashpointPathToolStripMenuItem; + private System.Windows.Forms.ComboBox genreComboBox; } } \ No newline at end of file diff --git a/FlashpointCC/CurationForm.cs b/FlashpointCC/CurationForm.cs index 04334e4..c2ebf9b 100644 --- a/FlashpointCC/CurationForm.cs +++ b/FlashpointCC/CurationForm.cs @@ -358,6 +358,7 @@ public void LoadCuration(Curation curation) genreComboBox.SelectedIndex = Math.Max(0, genreComboBox.FindString(curation.Genre)); developerTextBox.Text = curation.Developer; seriesTextBox.Text = curation.Series; + extremeCheckBox.Checked = (curation.Extreme == "Yes"); playModeComboBox.SelectedIndex = Math.Max(0, playModeComboBox.FindString(curation.PlayMode)); statusComboBox.SelectedIndex = Math.Max(0, statusComboBox.FindString(curation.Status)); sourceTextBox.Text = curation.Source; @@ -448,6 +449,7 @@ private void saveFileDialog_FileOk(object sender, CancelEventArgs e) PlayMode = playModeComboBox.SelectedItem.ToString(), Status = statusComboBox.SelectedItem.ToString(), Source = sourceTextBox.Text, + Extreme = extremeCheckBox.Checked ? "Yes" : "No", Platform = profile.Platform, Publisher = publisherTextBox.Text, LaunchCommand = commandLine, @@ -472,12 +474,12 @@ private void saveFileDialog_FileOk(object sender, CancelEventArgs e) var logoEntry = zip.CreateEntry(name + "/logo.png"); using (var entryStream = logoEntry.Open()) { - logoPictureBox.Image.Save(entryStream, logoPictureBox.Image.RawFormat); + logoPictureBox.Image.Save(entryStream, ImageFormat.Png); } var ssEntry = zip.CreateEntry(name + "/ss.png"); using (var entryStream = ssEntry.Open()) { - screenshotPictureBox.Image.Save(entryStream, screenshotPictureBox.Image.RawFormat); + screenshotPictureBox.Image.Save(entryStream, ImageFormat.Png); } source.CopyToZip(zip, name); } @@ -510,8 +512,26 @@ private void flagAsExecutableToolStripMenuItem_Click(object sender, EventArgs e) private void newToolStripMenuItem_Click(object sender, EventArgs e) { - new CurationForm().Show(); - Dispose(false); + if(MessageBox.Show("Are you sure you wish to reset all fields?", "New", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) + { + SetLogo(null); + SetScreenshot(null); + titleTextBox.Text = ""; + seriesTextBox.Text = ""; + profileComboBox.Text = ""; + developerTextBox.Text = ""; + publisherTextBox.Text = ""; + sourceTextBox.Text = ""; + dateTimePicker.Value = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day); + dateTimePicker.Checked = false; + genreComboBox.Text = "Genre"; + playModeComboBox.Text = "Playmode"; + statusComboBox.Text = "Status"; + extremeCheckBox.Checked = false; + notesTextBox.Text = ""; + authorNotesTextBox.Text = ""; + treeView.Nodes.Clear(); + } } private void importCurationToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/FlashpointCC/CurationForm.resx b/FlashpointCC/CurationForm.resx index e181852..51e757c 100644 --- a/FlashpointCC/CurationForm.resx +++ b/FlashpointCC/CurationForm.resx @@ -124,50 +124,50 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAE - CgAAAk1TRnQBSQFMAgEBBAEAAfgBAAH4AQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo - AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA - AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 - AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA - AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm - AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM - AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA - ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz - AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ - AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM - AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA - AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA - AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ - AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ - AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA - AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm - ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ - Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz - AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA - AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM - AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM - ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM - Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA - AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM - AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ - AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz - AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm - AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw - AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD//8A/wD/AP8ANgAB9AIJ - AfIGAAHzAgkB9AMADPQiAAHzDrMB8wIAAfQKFAH0AgAP9AEADvQB/wEAAQkO1AEJAgAB9AEUCPQBFAH0 - AgAB9A15AfQBAAH0ApkKeQEaAfQBAAHdDtQB3QIAAfQBFAj0ARQB9AIAAfQNeQH0AQAB9AF5ARoKeQGZ - AfQBAAHzDrMB8wIAAfQBFAj0ARQB9AIAAfQNeQH0AQAB9AF5AfMLeQEbAfQCAAGTARYB8gHzBG0B8wcA - AfQBFAj0ARQB9AIAAfQNeQH0AQAB9AF5AfQBmQp5ARoB9AYAAfICbQHyCAAB9AEUCPQBFAH0AgAB9A15 - AfQBAAH0AXkB9AEaCnkBmQH0BwAC8gkAAfQBFAj0ARQB9AIAAfQNeQH0AQAB9AF5C/QBeQL0BwAC8gkA - AfQBFAj0ARQB9AIAAfQNeQH0AQAB9AF5C/QBeQL0BgAB/wK8Af8IAAH0ARQF9AQUAfQCAAH0DXkB9AEA - AfQBeQv0AXkB9AYAAf8BbwJGAW8B/wcAAfQBFAX0AxQB7wH0AgAB9A15AfQBAAH0AXkG9AEaBHkBmQH0 - BgABkwRGAZMHAAH0ARQF9AIUAe8C9AIAAfQBeQb0ARsBmQX0AQAB9AF5BvQBmQEaBfQGAAFvAUcCFwFG - AW8HAAH0BxQB7wL0AwAB8wh5ARoB9AUAAfMBmQZ5AZkE9AH/BwABkwMXAUYBkwcACvQEAAr0Af8FAAr0 - CwAB/wFvAkYBFwH0JgAB/wf0Af8MAAH/AfIBGgH/BgABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEA - AQEGAAEBFgAD/4EABv8BhwHhAcABAwT/AgABwAEDAQABAQEAAQECAAHAAQMBAAEBAQABAQIAAcABAwEA - AQEBAAEBAgABwAEDAQABAQIAAcABHwHAAQMBAAEBAgAB/AE/AcABAwEAAQECAAH+AX8BwAEDAQABAQIA - Af4BfwHAAQMBAAEBAgAB/AE/AcABAwEAAQEBAAEBAfgBHwHAAQMBAAEBAQABAQH4AR8BwAEDAQABAQEA - AQEB+AEfAcABBwEAAR8BAAEDAfgBHwHAAQ8BAAEfAQABPwH4AR8E/wGAAT8B/AE/Cw== + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAC + CgAAAk1TRnQBSQFMAgEBBAIAAQEBAAEBARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA + AUADAAEgAwABAQEAAQgGAAEIGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA + AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA + AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm + AwABmQMAAcwCAAEzAwACMwIAATMBZgIAATMBmQIAATMBzAIAATMB/wIAAWYDAAFmATMCAAJmAgABZgGZ + AgABZgHMAgABZgH/AgABmQMAAZkBMwIAAZkBZgIAApkCAAGZAcwCAAGZAf8CAAHMAwABzAEzAgABzAFm + AgABzAGZAgACzAIAAcwB/wIAAf8BZgIAAf8BmQIAAf8BzAEAATMB/wIAAf8BAAEzAQABMwEAAWYBAAEz + AQABmQEAATMBAAHMAQABMwEAAf8BAAH/ATMCAAMzAQACMwFmAQACMwGZAQACMwHMAQACMwH/AQABMwFm + AgABMwFmATMBAAEzAmYBAAEzAWYBmQEAATMBZgHMAQABMwFmAf8BAAEzAZkCAAEzAZkBMwEAATMBmQFm + AQABMwKZAQABMwGZAcwBAAEzAZkB/wEAATMBzAIAATMBzAEzAQABMwHMAWYBAAEzAcwBmQEAATMCzAEA + ATMBzAH/AQABMwH/ATMBAAEzAf8BZgEAATMB/wGZAQABMwH/AcwBAAEzAv8BAAFmAwABZgEAATMBAAFm + AQABZgEAAWYBAAGZAQABZgEAAcwBAAFmAQAB/wEAAWYBMwIAAWYCMwEAAWYBMwFmAQABZgEzAZkBAAFm + ATMBzAEAAWYBMwH/AQACZgIAAmYBMwEAA2YBAAJmAZkBAAJmAcwBAAFmAZkCAAFmAZkBMwEAAWYBmQFm + AQABZgKZAQABZgGZAcwBAAFmAZkB/wEAAWYBzAIAAWYBzAEzAQABZgHMAZkBAAFmAswBAAFmAcwB/wEA + AWYB/wIAAWYB/wEzAQABZgH/AZkBAAFmAf8BzAEAAcwBAAH/AQAB/wEAAcwBAAKZAgABmQEzAZkBAAGZ + AQABmQEAAZkBAAHMAQABmQMAAZkCMwEAAZkBAAFmAQABmQEzAcwBAAGZAQAB/wEAAZkBZgIAAZkBZgEz + AQABmQEzAWYBAAGZAWYBmQEAAZkBZgHMAQABmQEzAf8BAAKZATMBAAKZAWYBAAOZAQACmQHMAQACmQH/ + AQABmQHMAgABmQHMATMBAAFmAcwBZgEAAZkBzAGZAQABmQLMAQABmQHMAf8BAAGZAf8CAAGZAf8BMwEA + AZkBzAFmAQABmQH/AZkBAAGZAf8BzAEAAZkC/wEAAcwDAAGZAQABMwEAAcwBAAFmAQABzAEAAZkBAAHM + AQABzAEAAZkBMwIAAcwCMwEAAcwBMwFmAQABzAEzAZkBAAHMATMBzAEAAcwBMwH/AQABzAFmAgABzAFm + ATMBAAGZAmYBAAHMAWYBmQEAAcwBZgHMAQABmQFmAf8BAAHMAZkCAAHMAZkBMwEAAcwBmQFmAQABzAKZ + AQABzAGZAcwBAAHMAZkB/wEAAswCAALMATMBAALMAWYBAALMAZkBAAPMAQACzAH/AQABzAH/AgABzAH/ + ATMBAAGZAf8BZgEAAcwB/wGZAQABzAH/AcwBAAHMAv8BAAHMAQABMwEAAf8BAAFmAQAB/wEAAZkBAAHM + ATMCAAH/AjMBAAH/ATMBZgEAAf8BMwGZAQAB/wEzAcwBAAH/ATMB/wEAAf8BZgIAAf8BZgEzAQABzAJm + AQAB/wFmAZkBAAH/AWYBzAEAAcwBZgH/AQAB/wGZAgAB/wGZATMBAAH/AZkBZgEAAf8CmQEAAf8BmQHM + AQAB/wGZAf8BAAH/AcwCAAH/AcwBMwEAAf8BzAFmAQAB/wHMAZkBAAH/AswBAAH/AcwB/wEAAv8BMwEA + AcwB/wFmAQAC/wGZAQAC/wHMAQACZgH/AQABZgH/AWYBAAFmAv8BAAH/AmYBAAH/AWYB/wEAAv8BZgEA + ASEBAAGlAQADXwEAA3cBAAOGAQADlgEAA8sBAAOyAQAD1wEAA90BAAPjAQAD6gEAA/EBAAP4AQAB8AH7 + Af8BAAGkAqABAAOAAwAB/wIAAf8DAAL/AQAB/wMAAf8BAAH/AQAC/wIAA///AP8A/wD/ADYAAfQCCQHy + BgAB8wIJAfQDAAz0IgAB8w6zAfMCAAH0ChQB9AIAD/QBAA70Af8BAAEJDtQBCQIAAfQBFAj0ARQB9AIA + AfQNeQH0AQAB9AKZCnkBGgH0AQAB3Q7UAd0CAAH0ARQI9AEUAfQCAAH0DXkB9AEAAfQBeQEaCnkBmQH0 + AQAB8w6zAfMCAAH0ARQI9AEUAfQCAAH0DXkB9AEAAfQBeQHzC3kBGwH0AgABkwEWAfIB8wRtAfMHAAH0 + ARQI9AEUAfQCAAH0DXkB9AEAAfQBeQH0AZkKeQEaAfQGAAHyAm0B8ggAAfQBFAj0ARQB9AIAAfQNeQH0 + AQAB9AF5AfQBGgp5AZkB9AcAAvIJAAH0ARQI9AEUAfQCAAH0DXkB9AEAAfQBeQv0AXkC9AcAAvIJAAH0 + ARQI9AEUAfQCAAH0DXkB9AEAAfQBeQv0AXkC9AYAAf8CvAH/CAAB9AEUBfQEFAH0AgAB9A15AfQBAAH0 + AXkL9AF5AfQGAAH/AW8CRgFvAf8HAAH0ARQF9AMUAe8B9AIAAfQNeQH0AQAB9AF5BvQBGgR5AZkB9AYA + AZMERgGTBwAB9AEUBfQCFAHvAvQCAAH0AXkG9AEbAZkF9AEAAfQBeQb0AZkBGgX0BgABbwFHAhcBRgFv + BwAB9AcUAe8C9AMAAfMIeQEaAfQFAAHzAZkGeQGZBPQB/wcAAZMDFwFGAZMHAAr0BAAK9AH/BQAK9AsA + Af8BbwJGARcB9CYAAf8H9AH/DAAB/wHyARoB/wYAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEB + BgABARYAA/+BAAb/AYcB4QHAAQME/wIAAcABAwEAAQEBAAEBAgABwAEDAQABAQEAAQECAAHAAQMBAAEB + AQABAQIAAcABAwEAAQECAAHAAR8BwAEDAQABAQIAAfwBPwHAAQMBAAEBAgAB/gF/AcABAwEAAQECAAH+ + AX8BwAEDAQABAQIAAfwBPwHAAQMBAAEBAQABAQH4AR8BwAEDAQABAQEAAQEB+AEfAcABAwEAAQEBAAEB + AfgBHwHAAQcBAAEfAQABAwH4AR8BwAEPAQABHwEAAT8B+AEfBP8BgAE/AfwBPws=