├── .gitignore ├── LICENSE.txt ├── README.md ├── SimpleScreenshotCapture.sln ├── docs └── capture-screenshot-1c.png ├── nuget.config └── src ├── AboutDialog.cs ├── AboutDialog.designer.cs ├── AboutDialog.resx ├── App.config ├── DesktopLayout.cs ├── GroupBox.cs ├── Line.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── NativeMethods.cs ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx ├── Resources ├── Camera-Photo.png ├── Copy.png ├── Save.png ├── Timer.png └── fill.png ├── ScreenshotCapture.cs ├── SimpleScreenshotCapture.csproj ├── ToolStripColorPickerDropDown.cs ├── ToolStripColorPickerDropDown.resx ├── ToolStripColorPickerSplitButton.cs ├── app.manifest └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | .vs/ 4 | packages/ 5 | 6 | *.suo 7 | *.user 8 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2019 Cyotek Ltd. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Capturing screenshots using C# and p/invoke 2 | 3 | ![The sample application][screenshot] 4 | 5 | This repository contains a sample application showing the basics 6 | of capturing screenshots in your C# applications via the use of 7 | platform invoke. 8 | 9 | For more information, please see the following article on the 10 | Cyotek blog: 11 | 12 | * [Capturing screenshots using C# and p/invoke][bloglink] 13 | 14 | [screenshot]: docs/capture-screenshot-1c.png 15 | [bloglink]: https://devblog.cyotek.com/post/capturing-screenshots-using-csharp-and-p-invoke 16 | -------------------------------------------------------------------------------- /SimpleScreenshotCapture.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleScreenshotCapture", "src\SimpleScreenshotCapture.csproj", "{EC728998-A741-4388-99E3-29C5F013E011}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {EC728998-A741-4388-99E3-29C5F013E011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {EC728998-A741-4388-99E3-29C5F013E011}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {EC728998-A741-4388-99E3-29C5F013E011}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {EC728998-A741-4388-99E3-29C5F013E011}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /docs/capture-screenshot-1c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/docs/capture-screenshot-1c.png -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/AboutDialog.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.Diagnostics; 10 | using System.Drawing; 11 | using System.Windows.Forms; 12 | 13 | namespace Cyotek.Demo.SimpleScreenshotCapture 14 | { 15 | internal partial class AboutDialog : Form 16 | { 17 | #region Constructors 18 | 19 | public AboutDialog() 20 | { 21 | this.InitializeComponent(); 22 | } 23 | 24 | #endregion 25 | 26 | #region Methods 27 | 28 | protected override void OnLoad(EventArgs e) 29 | { 30 | FileVersionInfo versionInfo; 31 | Font font; 32 | 33 | versionInfo = FileVersionInfo.GetVersionInfo(typeof(MainForm).Assembly.Location); 34 | nameLabel.Text = versionInfo.ProductName; 35 | copyrightLabel.Text = versionInfo.LegalCopyright; 36 | 37 | font = SystemFonts.MessageBoxFont; 38 | this.Font = font; 39 | nameLabel.Font = new Font(font, FontStyle.Bold); 40 | 41 | base.OnLoad(e); 42 | } 43 | 44 | private void closeButton_Click(object sender, EventArgs e) 45 | { 46 | this.Close(); 47 | } 48 | 49 | private void webLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 50 | { 51 | try 52 | { 53 | Process.Start("http://cyotek.com"); 54 | } 55 | catch (Exception ex) 56 | { 57 | MessageBox.Show(ex.GetBaseException().Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); 58 | } 59 | } 60 | 61 | #endregion 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/AboutDialog.designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Demo.SimpleScreenshotCapture 2 | { 3 | partial class AboutDialog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.nameLabel = new System.Windows.Forms.Label(); 32 | this.copyrightLabel = new System.Windows.Forms.Label(); 33 | this.webLinkLabel = new System.Windows.Forms.LinkLabel(); 34 | this.closeButton = new System.Windows.Forms.Button(); 35 | this.SuspendLayout(); 36 | // 37 | // nameLabel 38 | // 39 | this.nameLabel.AutoSize = true; 40 | this.nameLabel.Location = new System.Drawing.Point(12, 9); 41 | this.nameLabel.Name = "nameLabel"; 42 | this.nameLabel.Size = new System.Drawing.Size(54, 13); 43 | this.nameLabel.TabIndex = 1; 44 | this.nameLabel.Text = "AppName"; 45 | // 46 | // copyrightLabel 47 | // 48 | this.copyrightLabel.AutoSize = true; 49 | this.copyrightLabel.Location = new System.Drawing.Point(12, 22); 50 | this.copyrightLabel.Name = "copyrightLabel"; 51 | this.copyrightLabel.Size = new System.Drawing.Size(51, 13); 52 | this.copyrightLabel.TabIndex = 2; 53 | this.copyrightLabel.Text = "Copyright"; 54 | // 55 | // webLinkLabel 56 | // 57 | this.webLinkLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 58 | this.webLinkLabel.AutoSize = true; 59 | this.webLinkLabel.Location = new System.Drawing.Point(12, 251); 60 | this.webLinkLabel.Name = "webLinkLabel"; 61 | this.webLinkLabel.Size = new System.Drawing.Size(120, 13); 62 | this.webLinkLabel.TabIndex = 3; 63 | this.webLinkLabel.TabStop = true; 64 | this.webLinkLabel.Text = "http://www.cyotek.com"; 65 | this.webLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.webLinkLabel_LinkClicked); 66 | // 67 | // closeButton 68 | // 69 | this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 70 | this.closeButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; 71 | this.closeButton.Location = new System.Drawing.Point(336, 246); 72 | this.closeButton.Name = "closeButton"; 73 | this.closeButton.Size = new System.Drawing.Size(75, 23); 74 | this.closeButton.TabIndex = 0; 75 | this.closeButton.Text = "Close"; 76 | this.closeButton.UseVisualStyleBackColor = true; 77 | this.closeButton.Click += new System.EventHandler(this.closeButton_Click); 78 | // 79 | // AboutDialog 80 | // 81 | this.AcceptButton = this.closeButton; 82 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 83 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 84 | this.CancelButton = this.closeButton; 85 | this.ClientSize = new System.Drawing.Size(423, 281); 86 | this.Controls.Add(this.closeButton); 87 | this.Controls.Add(this.webLinkLabel); 88 | this.Controls.Add(this.copyrightLabel); 89 | this.Controls.Add(this.nameLabel); 90 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 91 | this.MaximizeBox = false; 92 | this.MinimizeBox = false; 93 | this.Name = "AboutDialog"; 94 | this.ShowIcon = false; 95 | this.ShowInTaskbar = false; 96 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 97 | this.Text = "About"; 98 | this.ResumeLayout(false); 99 | this.PerformLayout(); 100 | 101 | } 102 | 103 | #endregion 104 | 105 | private System.Windows.Forms.Label nameLabel; 106 | private System.Windows.Forms.Label copyrightLabel; 107 | private System.Windows.Forms.LinkLabel webLinkLabel; 108 | private System.Windows.Forms.Button closeButton; 109 | } 110 | } -------------------------------------------------------------------------------- /src/AboutDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/DesktopLayout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | // Capturing screenshots using C# and p/invoke 6 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 7 | // Copyright © 2017-2019 Cyotek Ltd. All Rights Reserved. 8 | 9 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 10 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 11 | 12 | namespace Cyotek.Windows.Forms 13 | { 14 | internal sealed class DesktopLayout 15 | { 16 | #region Private Fields 17 | 18 | private Rectangle _bounds; 19 | 20 | private int _count; 21 | 22 | private Rectangle[] _displays; 23 | 24 | private bool _workingAreaOnly; 25 | 26 | #endregion Private Fields 27 | 28 | #region Public Constructors 29 | 30 | public DesktopLayout() 31 | { 32 | this.Initialize(); 33 | } 34 | 35 | #endregion Public Constructors 36 | 37 | #region Public Properties 38 | 39 | public Rectangle Bounds 40 | { get { return _bounds; } } 41 | 42 | public int Count 43 | { get { return _count; } } 44 | 45 | public int Height 46 | { get { return _bounds.Height; } } 47 | 48 | public int Width 49 | { get { return _bounds.Width; } } 50 | 51 | public bool WorkingAreaOnly 52 | { 53 | get { return _workingAreaOnly; } 54 | set 55 | { 56 | if (_workingAreaOnly != value) 57 | { 58 | _workingAreaOnly = value; 59 | 60 | this.Initialize(); 61 | } 62 | } 63 | } 64 | 65 | #endregion Public Properties 66 | 67 | #region Public Methods 68 | 69 | public Rectangle GetDisplayBounds(int index) 70 | { 71 | return _displays[index]; 72 | } 73 | 74 | public Rectangle GetNormalizedDisplayBounds(int index) 75 | { 76 | return this.GetNormalizedDisplayBounds(_displays[index]); 77 | } 78 | 79 | public Rectangle GetNormalizedDisplayBounds(Rectangle bounds) 80 | { 81 | return new Rectangle(bounds.X - _bounds.X, bounds.Y - _bounds.Y, bounds.Width, bounds.Height); 82 | } 83 | 84 | #endregion Public Methods 85 | 86 | #region Private Methods 87 | 88 | private void Initialize() 89 | { 90 | Screen[] screens; 91 | int minX; 92 | int minY; 93 | int maxX; 94 | int maxY; 95 | 96 | screens = Screen.AllScreens; 97 | minX = 0; 98 | minY = 0; 99 | maxX = 0; 100 | maxY = 0; 101 | 102 | _count = screens.Length; 103 | _displays = new Rectangle[_count]; 104 | 105 | for (int i = 0; i < _count; i++) 106 | { 107 | Screen screen; 108 | Rectangle bounds; 109 | 110 | screen = screens[i]; 111 | bounds = _workingAreaOnly ? screen.WorkingArea : screen.Bounds; 112 | 113 | _displays[i] = bounds; 114 | 115 | minX = Math.Min(minX, bounds.X); 116 | minY = Math.Min(minY, bounds.Y); 117 | maxX = Math.Max(maxX, bounds.Right); 118 | maxY = Math.Max(maxY, bounds.Bottom); 119 | } 120 | 121 | _bounds = new Rectangle(minX, minY, maxX - minX, maxY - minY); 122 | } 123 | 124 | #endregion Private Methods 125 | } 126 | } -------------------------------------------------------------------------------- /src/GroupBox.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/GroupBox.cs -------------------------------------------------------------------------------- /src/Line.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.ComponentModel; 10 | using System.Drawing; 11 | using System.Windows.Forms; 12 | 13 | namespace Cyotek.Windows.Forms 14 | { 15 | #if PUBLICLIB 16 | [Designer(typeof(Design.LineDesigner))] 17 | public class Line : Control 18 | #else 19 | internal class Line : Control 20 | #endif 21 | { 22 | #region Constants 23 | 24 | private static readonly object _eventFlatStyleChanged = new object(); 25 | 26 | private static readonly object _eventLineColorChanged = new object(); 27 | 28 | private static readonly object _eventOrientationChanged = new object(); 29 | 30 | #endregion 31 | 32 | #region Fields 33 | 34 | private FlatStyle _flatStyle = FlatStyle.Standard; 35 | 36 | private Color _lineColor; 37 | 38 | private Orientation _orientation; 39 | 40 | #endregion 41 | 42 | #region Constructors 43 | 44 | public Line() 45 | { 46 | this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); 47 | this.SetStyle(ControlStyles.Selectable, false); 48 | this.LineColor = SystemColors.ControlDark; 49 | base.TabStop = false; 50 | base.TabIndex = 0; 51 | } 52 | 53 | #endregion 54 | 55 | #region Events 56 | 57 | [Category("Property Changed")] 58 | public event EventHandler FlatStyleChanged 59 | { 60 | add { this.Events.AddHandler(_eventFlatStyleChanged, value); } 61 | remove { this.Events.RemoveHandler(_eventFlatStyleChanged, value); } 62 | } 63 | 64 | [Category("Property Changed")] 65 | public event EventHandler LineColorChanged 66 | { 67 | add { this.Events.AddHandler(_eventLineColorChanged, value); } 68 | remove { this.Events.RemoveHandler(_eventLineColorChanged, value); } 69 | } 70 | 71 | [Category("Property Changed")] 72 | public event EventHandler OrientationChanged 73 | { 74 | add { this.Events.AddHandler(_eventOrientationChanged, value); } 75 | remove { this.Events.RemoveHandler(_eventOrientationChanged, value); } 76 | } 77 | 78 | #endregion 79 | 80 | #region Properties 81 | 82 | [Category("Appearance")] 83 | [DefaultValue(typeof(FlatStyle), "Standard")] 84 | public FlatStyle FlatStyle 85 | { 86 | get { return _flatStyle; } 87 | set 88 | { 89 | if (_flatStyle != value) 90 | { 91 | _flatStyle = value; 92 | 93 | this.OnFlatStyleChanged(EventArgs.Empty); 94 | } 95 | } 96 | } 97 | 98 | [Category("Appearance")] 99 | [DefaultValue(typeof(Color), "ControlDark")] 100 | public Color LineColor 101 | { 102 | get { return _lineColor; } 103 | set 104 | { 105 | if (this.LineColor != value) 106 | { 107 | _lineColor = value; 108 | 109 | this.OnLineColorChanged(EventArgs.Empty); 110 | } 111 | } 112 | } 113 | 114 | [Category("Appearance")] 115 | [DefaultValue(typeof(Orientation), "Horizontal")] 116 | public Orientation Orientation 117 | { 118 | get { return _orientation; } 119 | set 120 | { 121 | if (this.Orientation != value) 122 | { 123 | _orientation = value; 124 | 125 | this.OnOrientationChanged(EventArgs.Empty); 126 | } 127 | } 128 | } 129 | 130 | [DefaultValue(false)] 131 | [Browsable(false)] 132 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 133 | public new int TabIndex 134 | { 135 | get { return base.TabIndex; } 136 | set { base.TabIndex = value; } 137 | } 138 | 139 | [DefaultValue(false)] 140 | [Browsable(false)] 141 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 142 | public new bool TabStop 143 | { 144 | get { return base.TabStop; } 145 | set { base.TabStop = value; } 146 | } 147 | 148 | protected override Size DefaultSize 149 | { 150 | get { return new Size(100, 2); } 151 | } 152 | 153 | #endregion 154 | 155 | #region Methods 156 | 157 | /// 158 | /// Raises the event. 159 | /// 160 | /// The instance containing the event data. 161 | protected virtual void OnFlatStyleChanged(EventArgs e) 162 | { 163 | EventHandler handler; 164 | 165 | this.Invalidate(); 166 | 167 | handler = (EventHandler)this.Events[_eventFlatStyleChanged]; 168 | 169 | handler?.Invoke(this, e); 170 | } 171 | 172 | /// 173 | /// Raises the event. 174 | /// 175 | /// The instance containing the event data. 176 | protected virtual void OnLineColorChanged(EventArgs e) 177 | { 178 | EventHandler handler; 179 | 180 | this.Invalidate(); 181 | 182 | handler = (EventHandler)this.Events[_eventLineColorChanged]; 183 | 184 | handler?.Invoke(this, e); 185 | } 186 | 187 | /// 188 | /// Raises the event. 189 | /// 190 | /// The instance containing the event data. 191 | protected virtual void OnOrientationChanged(EventArgs e) 192 | { 193 | EventHandler handler; 194 | 195 | this.Invalidate(); 196 | 197 | handler = (EventHandler)this.Events[_eventOrientationChanged]; 198 | 199 | handler?.Invoke(this, e); 200 | } 201 | 202 | protected override void OnPaint(PaintEventArgs pe) 203 | { 204 | int x1; 205 | int y1; 206 | int x2; 207 | int y2; 208 | int xOffset; 209 | int yOffset; 210 | 211 | switch (this.Orientation) 212 | { 213 | case Orientation.Horizontal: 214 | x1 = 0; 215 | y1 = this.Height / 2 - 1; 216 | x2 = this.Width; 217 | y2 = y1; 218 | xOffset = 0; 219 | yOffset = 1; 220 | break; 221 | default: 222 | x1 = this.Width / 2 - 1; 223 | y1 = 0; 224 | x2 = x1; 225 | y2 = this.Height; 226 | xOffset = 1; 227 | yOffset = 0; 228 | break; 229 | } 230 | 231 | switch (this.FlatStyle) 232 | { 233 | case FlatStyle.System: 234 | using (Pen pen = new Pen(this.LineColor)) 235 | { 236 | pe.Graphics.DrawLine(pen, x1, y1, x2, y2); 237 | } 238 | break; 239 | default: 240 | pe.Graphics.DrawLine(SystemPens.ControlDark, x1, y1, x2, y2); 241 | pe.Graphics.DrawLine(SystemPens.ControlLightLight, x1 + xOffset, y1 + yOffset, x2 + xOffset, y2 + yOffset); 242 | break; 243 | } 244 | } 245 | 246 | protected override void OnSystemColorsChanged(EventArgs e) 247 | { 248 | base.OnSystemColorsChanged(e); 249 | 250 | this.Invalidate(); 251 | } 252 | 253 | #endregion 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Demo.SimpleScreenshotCapture 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | this.menuStrip = new System.Windows.Forms.MenuStrip(); 33 | this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 34 | this.captureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator(); 36 | this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); 38 | this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 39 | this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 40 | this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 42 | this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 43 | this.previewGroupBox = new Cyotek.Windows.Forms.GroupBox(); 44 | this.previewImageBox = new Cyotek.Windows.Forms.ImageBox(); 45 | this.setupGroupBox = new Cyotek.Windows.Forms.GroupBox(); 46 | this.desktopScreensCheckedListBox = new System.Windows.Forms.CheckedListBox(); 47 | this.line1 = new Cyotek.Windows.Forms.Line(); 48 | this.workingAreaCheckBox = new System.Windows.Forms.CheckBox(); 49 | this.line = new Cyotek.Windows.Forms.Line(); 50 | this.desktopRadioButton = new System.Windows.Forms.RadioButton(); 51 | this.monitorComboBox = new System.Windows.Forms.ComboBox(); 52 | this.monitorRadioButton = new System.Windows.Forms.RadioButton(); 53 | this.currentMonitorRadioButton = new System.Windows.Forms.RadioButton(); 54 | this.currentWindowRadioButton = new System.Windows.Forms.RadioButton(); 55 | this.label1 = new System.Windows.Forms.Label(); 56 | this.splitContainer = new System.Windows.Forms.SplitContainer(); 57 | this.toolStrip = new System.Windows.Forms.ToolStrip(); 58 | this.saveToolStripButton = new System.Windows.Forms.ToolStripButton(); 59 | this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); 60 | this.copyToolStripButton = new System.Windows.Forms.ToolStripButton(); 61 | this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); 62 | this.captureToolStripButton = new System.Windows.Forms.ToolStripButton(); 63 | this.delayCaptureToolStripButton = new System.Windows.Forms.ToolStripButton(); 64 | this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); 65 | this.fillToolStripColorPickerSplitButton = new Cyotek.Windows.Forms.ToolStripControllerHosts.ToolStripColorPickerSplitButton(); 66 | this.delayCaptureTimer = new System.Windows.Forms.Timer(this.components); 67 | this.statusStrip = new System.Windows.Forms.StatusStrip(); 68 | this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); 69 | this.timerToolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); 70 | this.menuStrip.SuspendLayout(); 71 | this.previewGroupBox.SuspendLayout(); 72 | this.setupGroupBox.SuspendLayout(); 73 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); 74 | this.splitContainer.Panel1.SuspendLayout(); 75 | this.splitContainer.Panel2.SuspendLayout(); 76 | this.splitContainer.SuspendLayout(); 77 | this.toolStrip.SuspendLayout(); 78 | this.statusStrip.SuspendLayout(); 79 | this.SuspendLayout(); 80 | // 81 | // menuStrip 82 | // 83 | this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 84 | this.fileToolStripMenuItem, 85 | this.editToolStripMenuItem, 86 | this.helpToolStripMenuItem}); 87 | this.menuStrip.Location = new System.Drawing.Point(0, 0); 88 | this.menuStrip.Name = "menuStrip"; 89 | this.menuStrip.Size = new System.Drawing.Size(867, 24); 90 | this.menuStrip.TabIndex = 0; 91 | // 92 | // fileToolStripMenuItem 93 | // 94 | this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 95 | this.captureToolStripMenuItem, 96 | this.toolStripSeparator, 97 | this.saveToolStripMenuItem, 98 | this.toolStripSeparator1, 99 | this.exitToolStripMenuItem}); 100 | this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; 101 | this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); 102 | this.fileToolStripMenuItem.Text = "&File"; 103 | // 104 | // captureToolStripMenuItem 105 | // 106 | this.captureToolStripMenuItem.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Capture; 107 | this.captureToolStripMenuItem.Name = "captureToolStripMenuItem"; 108 | this.captureToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F9; 109 | this.captureToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 110 | this.captureToolStripMenuItem.Text = "&Capture"; 111 | this.captureToolStripMenuItem.Click += new System.EventHandler(this.captureToolStripMenuItem_Click); 112 | // 113 | // toolStripSeparator 114 | // 115 | this.toolStripSeparator.Name = "toolStripSeparator"; 116 | this.toolStripSeparator.Size = new System.Drawing.Size(144, 6); 117 | // 118 | // saveToolStripMenuItem 119 | // 120 | this.saveToolStripMenuItem.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Save; 121 | this.saveToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; 122 | this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; 123 | this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); 124 | this.saveToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 125 | this.saveToolStripMenuItem.Text = "&Save..."; 126 | this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); 127 | // 128 | // toolStripSeparator1 129 | // 130 | this.toolStripSeparator1.Name = "toolStripSeparator1"; 131 | this.toolStripSeparator1.Size = new System.Drawing.Size(144, 6); 132 | // 133 | // exitToolStripMenuItem 134 | // 135 | this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; 136 | this.exitToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 137 | this.exitToolStripMenuItem.Text = "E&xit"; 138 | this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); 139 | // 140 | // editToolStripMenuItem 141 | // 142 | this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 143 | this.copyToolStripMenuItem}); 144 | this.editToolStripMenuItem.Name = "editToolStripMenuItem"; 145 | this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20); 146 | this.editToolStripMenuItem.Text = "&Edit"; 147 | // 148 | // copyToolStripMenuItem 149 | // 150 | this.copyToolStripMenuItem.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Copy; 151 | this.copyToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta; 152 | this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; 153 | this.copyToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); 154 | this.copyToolStripMenuItem.Size = new System.Drawing.Size(144, 22); 155 | this.copyToolStripMenuItem.Text = "&Copy"; 156 | this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); 157 | // 158 | // helpToolStripMenuItem 159 | // 160 | this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 161 | this.aboutToolStripMenuItem}); 162 | this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; 163 | this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); 164 | this.helpToolStripMenuItem.Text = "&Help"; 165 | // 166 | // aboutToolStripMenuItem 167 | // 168 | this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; 169 | this.aboutToolStripMenuItem.Size = new System.Drawing.Size(107, 22); 170 | this.aboutToolStripMenuItem.Text = "&About"; 171 | this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); 172 | // 173 | // previewGroupBox 174 | // 175 | this.previewGroupBox.Controls.Add(this.previewImageBox); 176 | this.previewGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; 177 | this.previewGroupBox.Location = new System.Drawing.Point(0, 0); 178 | this.previewGroupBox.Name = "previewGroupBox"; 179 | this.previewGroupBox.Size = new System.Drawing.Size(558, 316); 180 | this.previewGroupBox.TabIndex = 0; 181 | this.previewGroupBox.TabStop = false; 182 | this.previewGroupBox.Text = "Preview"; 183 | // 184 | // previewImageBox 185 | // 186 | this.previewImageBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 187 | | System.Windows.Forms.AnchorStyles.Left) 188 | | System.Windows.Forms.AnchorStyles.Right))); 189 | this.previewImageBox.Location = new System.Drawing.Point(6, 19); 190 | this.previewImageBox.Name = "previewImageBox"; 191 | this.previewImageBox.Size = new System.Drawing.Size(546, 291); 192 | this.previewImageBox.TabIndex = 0; 193 | this.previewImageBox.TabStop = false; 194 | this.previewImageBox.Zoomed += new System.EventHandler(this.previewImageBox_Zoomed); 195 | // 196 | // setupGroupBox 197 | // 198 | this.setupGroupBox.Controls.Add(this.desktopScreensCheckedListBox); 199 | this.setupGroupBox.Controls.Add(this.line1); 200 | this.setupGroupBox.Controls.Add(this.workingAreaCheckBox); 201 | this.setupGroupBox.Controls.Add(this.line); 202 | this.setupGroupBox.Controls.Add(this.desktopRadioButton); 203 | this.setupGroupBox.Controls.Add(this.monitorComboBox); 204 | this.setupGroupBox.Controls.Add(this.monitorRadioButton); 205 | this.setupGroupBox.Controls.Add(this.currentMonitorRadioButton); 206 | this.setupGroupBox.Controls.Add(this.currentWindowRadioButton); 207 | this.setupGroupBox.Controls.Add(this.label1); 208 | this.setupGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; 209 | this.setupGroupBox.Location = new System.Drawing.Point(0, 0); 210 | this.setupGroupBox.Name = "setupGroupBox"; 211 | this.setupGroupBox.Size = new System.Drawing.Size(281, 316); 212 | this.setupGroupBox.TabIndex = 0; 213 | this.setupGroupBox.TabStop = false; 214 | this.setupGroupBox.Text = "Capture Setup"; 215 | // 216 | // desktopScreensCheckedListBox 217 | // 218 | this.desktopScreensCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 219 | | System.Windows.Forms.AnchorStyles.Left) 220 | | System.Windows.Forms.AnchorStyles.Right))); 221 | this.desktopScreensCheckedListBox.FormattingEnabled = true; 222 | this.desktopScreensCheckedListBox.IntegralHeight = false; 223 | this.desktopScreensCheckedListBox.Location = new System.Drawing.Point(6, 206); 224 | this.desktopScreensCheckedListBox.Name = "desktopScreensCheckedListBox"; 225 | this.desktopScreensCheckedListBox.Size = new System.Drawing.Size(269, 104); 226 | this.desktopScreensCheckedListBox.TabIndex = 7; 227 | // 228 | // line1 229 | // 230 | this.line1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 231 | | System.Windows.Forms.AnchorStyles.Right))); 232 | this.line1.Location = new System.Drawing.Point(6, 190); 233 | this.line1.Name = "line1"; 234 | this.line1.Size = new System.Drawing.Size(269, 10); 235 | this.line1.Text = "label2"; 236 | // 237 | // workingAreaCheckBox 238 | // 239 | this.workingAreaCheckBox.AutoSize = true; 240 | this.workingAreaCheckBox.Location = new System.Drawing.Point(6, 167); 241 | this.workingAreaCheckBox.Name = "workingAreaCheckBox"; 242 | this.workingAreaCheckBox.Size = new System.Drawing.Size(115, 17); 243 | this.workingAreaCheckBox.TabIndex = 6; 244 | this.workingAreaCheckBox.Text = "&Working Area Only"; 245 | this.workingAreaCheckBox.UseVisualStyleBackColor = true; 246 | // 247 | // line 248 | // 249 | this.line.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 250 | | System.Windows.Forms.AnchorStyles.Right))); 251 | this.line.Location = new System.Drawing.Point(6, 151); 252 | this.line.Name = "line"; 253 | this.line.Size = new System.Drawing.Size(269, 10); 254 | this.line.Text = "label2"; 255 | // 256 | // desktopRadioButton 257 | // 258 | this.desktopRadioButton.AutoSize = true; 259 | this.desktopRadioButton.Location = new System.Drawing.Point(6, 128); 260 | this.desktopRadioButton.Name = "desktopRadioButton"; 261 | this.desktopRadioButton.Size = new System.Drawing.Size(95, 17); 262 | this.desktopRadioButton.TabIndex = 5; 263 | this.desktopRadioButton.Text = "Entire &Desktop"; 264 | this.desktopRadioButton.UseVisualStyleBackColor = true; 265 | // 266 | // monitorComboBox 267 | // 268 | this.monitorComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 269 | this.monitorComboBox.FormattingEnabled = true; 270 | this.monitorComboBox.Location = new System.Drawing.Point(22, 101); 271 | this.monitorComboBox.Name = "monitorComboBox"; 272 | this.monitorComboBox.Size = new System.Drawing.Size(121, 21); 273 | this.monitorComboBox.TabIndex = 4; 274 | this.monitorComboBox.SelectedIndexChanged += new System.EventHandler(this.monitorComboBox_SelectedIndexChanged); 275 | // 276 | // monitorRadioButton 277 | // 278 | this.monitorRadioButton.AutoSize = true; 279 | this.monitorRadioButton.Location = new System.Drawing.Point(6, 78); 280 | this.monitorRadioButton.Name = "monitorRadioButton"; 281 | this.monitorRadioButton.Size = new System.Drawing.Size(98, 17); 282 | this.monitorRadioButton.TabIndex = 3; 283 | this.monitorRadioButton.Text = "Custom M&onitor"; 284 | this.monitorRadioButton.UseVisualStyleBackColor = true; 285 | // 286 | // currentMonitorRadioButton 287 | // 288 | this.currentMonitorRadioButton.AutoSize = true; 289 | this.currentMonitorRadioButton.Location = new System.Drawing.Point(6, 55); 290 | this.currentMonitorRadioButton.Name = "currentMonitorRadioButton"; 291 | this.currentMonitorRadioButton.Size = new System.Drawing.Size(97, 17); 292 | this.currentMonitorRadioButton.TabIndex = 2; 293 | this.currentMonitorRadioButton.Text = "Current &Monitor"; 294 | this.currentMonitorRadioButton.UseVisualStyleBackColor = true; 295 | // 296 | // currentWindowRadioButton 297 | // 298 | this.currentWindowRadioButton.AutoSize = true; 299 | this.currentWindowRadioButton.Checked = true; 300 | this.currentWindowRadioButton.Location = new System.Drawing.Point(6, 32); 301 | this.currentWindowRadioButton.Name = "currentWindowRadioButton"; 302 | this.currentWindowRadioButton.Size = new System.Drawing.Size(101, 17); 303 | this.currentWindowRadioButton.TabIndex = 1; 304 | this.currentWindowRadioButton.TabStop = true; 305 | this.currentWindowRadioButton.Text = "Current &Window"; 306 | this.currentWindowRadioButton.UseVisualStyleBackColor = true; 307 | // 308 | // label1 309 | // 310 | this.label1.AutoSize = true; 311 | this.label1.Location = new System.Drawing.Point(3, 16); 312 | this.label1.Name = "label1"; 313 | this.label1.Size = new System.Drawing.Size(160, 13); 314 | this.label1.TabIndex = 0; 315 | this.label1.Text = "What would you like to capture?"; 316 | // 317 | // splitContainer 318 | // 319 | this.splitContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 320 | | System.Windows.Forms.AnchorStyles.Left) 321 | | System.Windows.Forms.AnchorStyles.Right))); 322 | this.splitContainer.Location = new System.Drawing.Point(12, 52); 323 | this.splitContainer.Name = "splitContainer"; 324 | // 325 | // splitContainer.Panel1 326 | // 327 | this.splitContainer.Panel1.Controls.Add(this.setupGroupBox); 328 | // 329 | // splitContainer.Panel2 330 | // 331 | this.splitContainer.Panel2.Controls.Add(this.previewGroupBox); 332 | this.splitContainer.Size = new System.Drawing.Size(843, 316); 333 | this.splitContainer.SplitterDistance = 281; 334 | this.splitContainer.TabIndex = 2; 335 | // 336 | // toolStrip 337 | // 338 | this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 339 | this.saveToolStripButton, 340 | this.toolStripSeparator6, 341 | this.copyToolStripButton, 342 | this.toolStripSeparator7, 343 | this.captureToolStripButton, 344 | this.delayCaptureToolStripButton, 345 | this.toolStripSeparator2, 346 | this.fillToolStripColorPickerSplitButton}); 347 | this.toolStrip.Location = new System.Drawing.Point(0, 24); 348 | this.toolStrip.Name = "toolStrip"; 349 | this.toolStrip.Size = new System.Drawing.Size(867, 25); 350 | this.toolStrip.TabIndex = 1; 351 | // 352 | // saveToolStripButton 353 | // 354 | this.saveToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 355 | this.saveToolStripButton.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Save; 356 | this.saveToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; 357 | this.saveToolStripButton.Name = "saveToolStripButton"; 358 | this.saveToolStripButton.Size = new System.Drawing.Size(23, 22); 359 | this.saveToolStripButton.Text = "&Save"; 360 | this.saveToolStripButton.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); 361 | // 362 | // toolStripSeparator6 363 | // 364 | this.toolStripSeparator6.Name = "toolStripSeparator6"; 365 | this.toolStripSeparator6.Size = new System.Drawing.Size(6, 25); 366 | // 367 | // copyToolStripButton 368 | // 369 | this.copyToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 370 | this.copyToolStripButton.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Copy; 371 | this.copyToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; 372 | this.copyToolStripButton.Name = "copyToolStripButton"; 373 | this.copyToolStripButton.Size = new System.Drawing.Size(23, 22); 374 | this.copyToolStripButton.Text = "&Copy"; 375 | this.copyToolStripButton.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); 376 | // 377 | // toolStripSeparator7 378 | // 379 | this.toolStripSeparator7.Name = "toolStripSeparator7"; 380 | this.toolStripSeparator7.Size = new System.Drawing.Size(6, 25); 381 | // 382 | // captureToolStripButton 383 | // 384 | this.captureToolStripButton.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Capture; 385 | this.captureToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; 386 | this.captureToolStripButton.Name = "captureToolStripButton"; 387 | this.captureToolStripButton.Size = new System.Drawing.Size(69, 22); 388 | this.captureToolStripButton.Text = "&Capture"; 389 | this.captureToolStripButton.Click += new System.EventHandler(this.captureToolStripMenuItem_Click); 390 | // 391 | // delayCaptureToolStripButton 392 | // 393 | this.delayCaptureToolStripButton.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Timer; 394 | this.delayCaptureToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; 395 | this.delayCaptureToolStripButton.Name = "delayCaptureToolStripButton"; 396 | this.delayCaptureToolStripButton.Size = new System.Drawing.Size(101, 22); 397 | this.delayCaptureToolStripButton.Text = "&Delay Capture"; 398 | this.delayCaptureToolStripButton.Click += new System.EventHandler(this.delayCaptureToolStripButton_Click); 399 | // 400 | // toolStripSeparator2 401 | // 402 | this.toolStripSeparator2.Name = "toolStripSeparator2"; 403 | this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); 404 | // 405 | // fillToolStripColorPickerSplitButton 406 | // 407 | this.fillToolStripColorPickerSplitButton.Color = System.Drawing.Color.White; 408 | this.fillToolStripColorPickerSplitButton.Image = global::Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources.Fill; 409 | this.fillToolStripColorPickerSplitButton.Name = "fillToolStripColorPickerSplitButton"; 410 | this.fillToolStripColorPickerSplitButton.Size = new System.Drawing.Size(32, 22); 411 | // 412 | // delayCaptureTimer 413 | // 414 | this.delayCaptureTimer.Interval = 1000; 415 | this.delayCaptureTimer.Tick += new System.EventHandler(this.delayCaptureTimer_Tick); 416 | // 417 | // statusStrip 418 | // 419 | this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 420 | this.toolStripStatusLabel1, 421 | this.timerToolStripStatusLabel}); 422 | this.statusStrip.Location = new System.Drawing.Point(0, 371); 423 | this.statusStrip.Name = "statusStrip"; 424 | this.statusStrip.Size = new System.Drawing.Size(867, 22); 425 | this.statusStrip.TabIndex = 3; 426 | // 427 | // toolStripStatusLabel1 428 | // 429 | this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; 430 | this.toolStripStatusLabel1.Size = new System.Drawing.Size(852, 17); 431 | this.toolStripStatusLabel1.Spring = true; 432 | this.toolStripStatusLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 433 | // 434 | // timerToolStripStatusLabel 435 | // 436 | this.timerToolStripStatusLabel.Name = "timerToolStripStatusLabel"; 437 | this.timerToolStripStatusLabel.Size = new System.Drawing.Size(0, 17); 438 | // 439 | // MainForm 440 | // 441 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 442 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 443 | this.ClientSize = new System.Drawing.Size(867, 393); 444 | this.Controls.Add(this.statusStrip); 445 | this.Controls.Add(this.toolStrip); 446 | this.Controls.Add(this.splitContainer); 447 | this.Controls.Add(this.menuStrip); 448 | this.MainMenuStrip = this.menuStrip; 449 | this.Name = "MainForm"; 450 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 451 | this.Text = "Simple Screenshot Capture"; 452 | this.menuStrip.ResumeLayout(false); 453 | this.menuStrip.PerformLayout(); 454 | this.previewGroupBox.ResumeLayout(false); 455 | this.setupGroupBox.ResumeLayout(false); 456 | this.setupGroupBox.PerformLayout(); 457 | this.splitContainer.Panel1.ResumeLayout(false); 458 | this.splitContainer.Panel2.ResumeLayout(false); 459 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); 460 | this.splitContainer.ResumeLayout(false); 461 | this.toolStrip.ResumeLayout(false); 462 | this.toolStrip.PerformLayout(); 463 | this.statusStrip.ResumeLayout(false); 464 | this.statusStrip.PerformLayout(); 465 | this.ResumeLayout(false); 466 | this.PerformLayout(); 467 | 468 | } 469 | 470 | #endregion 471 | private Cyotek.Windows.Forms.ImageBox previewImageBox; 472 | private Cyotek.Windows.Forms.GroupBox setupGroupBox; 473 | private System.Windows.Forms.RadioButton desktopRadioButton; 474 | private System.Windows.Forms.ComboBox monitorComboBox; 475 | private System.Windows.Forms.RadioButton monitorRadioButton; 476 | private System.Windows.Forms.RadioButton currentMonitorRadioButton; 477 | private System.Windows.Forms.RadioButton currentWindowRadioButton; 478 | private System.Windows.Forms.Label label1; 479 | private Cyotek.Windows.Forms.GroupBox previewGroupBox; 480 | private Cyotek.Windows.Forms.Line line; 481 | private System.Windows.Forms.CheckBox workingAreaCheckBox; 482 | private System.Windows.Forms.MenuStrip menuStrip; 483 | private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; 484 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator; 485 | private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; 486 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; 487 | private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; 488 | private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem; 489 | private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem; 490 | private System.Windows.Forms.SplitContainer splitContainer; 491 | private System.Windows.Forms.ToolStrip toolStrip; 492 | private System.Windows.Forms.ToolStripButton saveToolStripButton; 493 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; 494 | private System.Windows.Forms.ToolStripButton copyToolStripButton; 495 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; 496 | private System.Windows.Forms.ToolStripButton captureToolStripButton; 497 | private System.Windows.Forms.ToolStripMenuItem captureToolStripMenuItem; 498 | private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; 499 | private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; 500 | private System.Windows.Forms.ToolStripButton delayCaptureToolStripButton; 501 | private System.Windows.Forms.Timer delayCaptureTimer; 502 | private System.Windows.Forms.StatusStrip statusStrip; 503 | private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; 504 | private System.Windows.Forms.ToolStripStatusLabel timerToolStripStatusLabel; 505 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; 506 | private Cyotek.Windows.Forms.ToolStripControllerHosts.ToolStripColorPickerSplitButton fillToolStripColorPickerSplitButton; 507 | private System.Windows.Forms.CheckedListBox desktopScreensCheckedListBox; 508 | private Windows.Forms.Line line1; 509 | } 510 | } 511 | 512 | -------------------------------------------------------------------------------- /src/MainForm.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017-2019 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.Drawing; 10 | using System.Drawing.Drawing2D; 11 | using System.Drawing.Imaging; 12 | using System.Media; 13 | using System.Runtime.InteropServices; 14 | using System.Windows.Forms; 15 | using Cyotek.Windows.Forms; 16 | 17 | namespace Cyotek.Demo.SimpleScreenshotCapture 18 | { 19 | internal partial class MainForm : Form 20 | { 21 | #region Private Fields 22 | 23 | private Bitmap _preview; 24 | 25 | private int _timer; 26 | 27 | #endregion Private Fields 28 | 29 | #region Public Constructors 30 | 31 | public MainForm() 32 | { 33 | this.InitializeComponent(); 34 | } 35 | 36 | #endregion Public Constructors 37 | 38 | #region Protected Methods 39 | 40 | protected override void OnShown(EventArgs e) 41 | { 42 | this.InitializeMonitorList(); 43 | 44 | currentWindowRadioButton.Checked = true; 45 | 46 | base.OnShown(e); 47 | } 48 | 49 | #endregion Protected Methods 50 | 51 | #region Private Methods 52 | 53 | private void aboutToolStripMenuItem_Click(object sender, EventArgs e) 54 | { 55 | using (AboutDialog dialog = new AboutDialog()) 56 | { 57 | dialog.ShowDialog(this); 58 | } 59 | } 60 | 61 | private void CaptureImage() 62 | { 63 | Bitmap result; 64 | ScreenshotCapture capture; 65 | bool onlyCaptureWorkingArea; 66 | 67 | capture = new ScreenshotCapture(); 68 | 69 | onlyCaptureWorkingArea = workingAreaCheckBox.Checked; 70 | 71 | if (currentWindowRadioButton.Checked) 72 | { 73 | result = capture.CaptureActiveWindow(); 74 | } 75 | else if (currentMonitorRadioButton.Checked) 76 | { 77 | result = capture.CaptureMonitor(Screen.FromControl(this), onlyCaptureWorkingArea); 78 | } 79 | else if (monitorRadioButton.Checked) 80 | { 81 | result = capture.CaptureMonitor(monitorComboBox.SelectedIndex, onlyCaptureWorkingArea); 82 | } 83 | else 84 | { 85 | result = capture.CaptureDesktop(onlyCaptureWorkingArea, fillToolStripColorPickerSplitButton.Color, i => desktopScreensCheckedListBox.GetItemChecked(i)); 86 | } 87 | 88 | this.UpdatePreview(result); 89 | } 90 | 91 | private void captureToolStripMenuItem_Click(object sender, EventArgs e) 92 | { 93 | this.CaptureImage(); 94 | } 95 | 96 | private void copyToolStripMenuItem_Click(object sender, EventArgs e) 97 | { 98 | if (_preview == null) 99 | { 100 | SystemSounds.Beep.Play(); 101 | } 102 | else 103 | { 104 | try 105 | { 106 | Clipboard.SetImage(_preview); 107 | } 108 | catch (ExternalException ex) 109 | { 110 | MessageBox.Show("Failed to copy image. " + ex.GetBaseException().Message, "Copy", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 111 | } 112 | } 113 | } 114 | 115 | private void delayCaptureTimer_Tick(object sender, EventArgs e) 116 | { 117 | _timer--; 118 | 119 | this.UpdateTimer(); 120 | 121 | if (_timer < 0) 122 | { 123 | delayCaptureTimer.Stop(); 124 | 125 | this.CaptureImage(); 126 | } 127 | } 128 | 129 | private void delayCaptureToolStripButton_Click(object sender, EventArgs e) 130 | { 131 | this.DelayedCapture(3); 132 | } 133 | 134 | private void DelayedCapture(int seconds) 135 | { 136 | _timer = seconds; 137 | 138 | delayCaptureTimer.Stop(); 139 | delayCaptureTimer.Start(); 140 | 141 | this.UpdateTimer(); 142 | } 143 | 144 | private void exitToolStripMenuItem_Click(object sender, EventArgs e) 145 | { 146 | this.Close(); 147 | } 148 | 149 | private void InitializeMonitorList() 150 | { 151 | Screen[] screens; 152 | 153 | screens = Screen.AllScreens; 154 | 155 | for (int i = 0; i < screens.Length; i++) 156 | { 157 | string name; 158 | 159 | name = screens[i].DeviceName; 160 | 161 | monitorComboBox.Items.Add(name); 162 | desktopScreensCheckedListBox.Items.Add(name, true); 163 | } 164 | 165 | monitorComboBox.SelectedIndex = 0; 166 | } 167 | 168 | private void monitorComboBox_SelectedIndexChanged(object sender, EventArgs e) 169 | { 170 | monitorRadioButton.Checked = true; 171 | } 172 | 173 | private void previewImageBox_Zoomed(object sender, ImageBoxZoomEventArgs e) 174 | { 175 | previewImageBox.InterpolationMode = previewImageBox.Zoom < 100 ? InterpolationMode.HighQualityBicubic : InterpolationMode.NearestNeighbor; 176 | } 177 | 178 | private void SaveImage(string fileName) 179 | { 180 | try 181 | { 182 | _preview.Save(fileName, ImageFormat.Png); 183 | } 184 | catch (ExternalException ex) 185 | { 186 | MessageBox.Show("Failed to save image. " + ex.GetBaseException().Message, "Save", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 187 | } 188 | } 189 | 190 | private void saveToolStripMenuItem_Click(object sender, EventArgs e) 191 | { 192 | if (_preview == null) 193 | { 194 | MessageBox.Show("Nothing to save.", "Save", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 195 | } 196 | else 197 | { 198 | using (SaveFileDialog dialog = new SaveFileDialog 199 | { 200 | Title = "Save Image As", 201 | Filter = "PNG Files (*.png)|*.png", 202 | DefaultExt = "png" 203 | }) 204 | { 205 | if (dialog.ShowDialog(this) == DialogResult.OK) 206 | { 207 | this.SaveImage(dialog.FileName); 208 | } 209 | } 210 | } 211 | } 212 | 213 | private void UpdatePreview(Bitmap capture) 214 | { 215 | if (_preview != null) 216 | { 217 | previewImageBox.Image = null; 218 | _preview.Dispose(); 219 | _preview = null; 220 | } 221 | 222 | _preview = capture; 223 | 224 | previewImageBox.Image = capture; 225 | previewImageBox.ZoomToFit(); 226 | } 227 | 228 | private void UpdateTimer() 229 | { 230 | timerToolStripStatusLabel.Text = _timer >= 0 ? _timer + "s" : string.Empty; 231 | } 232 | 233 | #endregion Private Methods 234 | } 235 | } -------------------------------------------------------------------------------- /src/MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 137, 17 125 | 126 | 127 | 240, 17 128 | 129 | 130 | 403, 17 131 | 132 | -------------------------------------------------------------------------------- /src/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.Runtime.InteropServices; 10 | 11 | // ReSharper disable FieldCanBeMadeReadOnly.Global 12 | // ReSharper disable InconsistentNaming 13 | 14 | namespace Cyotek.Demo.SimpleScreenshotCapture 15 | { 16 | internal static class NativeMethods 17 | { 18 | #region Externals 19 | 20 | [DllImport("gdi32.dll")] 21 | public static extern bool BitBlt(IntPtr hdcDest, int nxDest, int nyDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, RasterOperations dwRop); 22 | 23 | [DllImport("gdi32.dll")] 24 | public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); 25 | 26 | [DllImport("gdi32.dll")] 27 | public static extern IntPtr CreateCompatibleDC(IntPtr hdc); 28 | 29 | [DllImport("gdi32.dll")] 30 | public static extern IntPtr DeleteDC(IntPtr hdc); 31 | 32 | [DllImport("gdi32.dll")] 33 | public static extern IntPtr DeleteObject(IntPtr hObject); 34 | 35 | [DllImport("dwmapi.dll")] 36 | public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out RECT pvAttribute, int cbAttribute); 37 | 38 | [DllImport("user32.dll")] 39 | public static extern IntPtr GetDesktopWindow(); 40 | 41 | [DllImport("user32.dll")] 42 | public static extern IntPtr GetForegroundWindow(); 43 | 44 | [DllImport("user32.dll")] 45 | public static extern IntPtr GetWindowDC(IntPtr hWnd); 46 | 47 | [DllImport("user32.dll", SetLastError = true)] 48 | public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); 49 | 50 | [DllImport("user32.dll")] 51 | public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc); 52 | 53 | [DllImport("gdi32.dll")] 54 | public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); 55 | 56 | #endregion 57 | 58 | #region RasterOperations enum 59 | 60 | [Flags] 61 | public enum RasterOperations 62 | { 63 | SRCCOPY = 0x00CC0020, 64 | 65 | SRCPAINT = 0x00EE0086, 66 | 67 | SRCAND = 0x008800C6, 68 | 69 | SRCINVERT = 0x00660046, 70 | 71 | SRCERASE = 0x00440328, 72 | 73 | NOTSRCCOPY = 0x00330008, 74 | 75 | NOTSRCERASE = 0x001100A6, 76 | 77 | MERGECOPY = 0x00C000CA, 78 | 79 | MERGEPAINT = 0x00BB0226, 80 | 81 | PATCOPY = 0x00F00021, 82 | 83 | PATPAINT = 0x00FB0A09, 84 | 85 | PATINVERT = 0x005A0049, 86 | 87 | DSTINVERT = 0x00550009, 88 | 89 | BLACKNESS = 0x00000042, 90 | 91 | WHITENESS = 0x00FF0062, 92 | 93 | CAPTUREBLT = 0x40000000 //only if WinVer >= 5.0.0 (see wingdi.h) 94 | } 95 | 96 | #endregion 97 | 98 | #region Constants 99 | 100 | public const int DWMWA_EXTENDED_FRAME_BOUNDS = 9; 101 | 102 | #endregion 103 | 104 | #region Nested type: RECT 105 | 106 | [StructLayout(LayoutKind.Sequential)] 107 | public struct RECT 108 | { 109 | public int left; 110 | 111 | public int top; 112 | 113 | public int right; 114 | 115 | public int bottom; 116 | } 117 | 118 | #endregion 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/Program.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.Windows.Forms; 10 | 11 | namespace Cyotek.Demo.SimpleScreenshotCapture 12 | { 13 | internal static class Program 14 | { 15 | #region Static Methods 16 | 17 | /// 18 | /// The main entry point for the application. 19 | /// 20 | [STAThread] 21 | static void Main() 22 | { 23 | Application.EnableVisualStyles(); 24 | Application.SetCompatibleTextRenderingDefault(false); 25 | Application.Run(new MainForm()); 26 | } 27 | 28 | #endregion 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017-2019 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.Reflection; 10 | using System.Runtime.InteropServices; 11 | 12 | [assembly: AssemblyTitle("Simple Screenshot Capture")] 13 | [assembly: AssemblyDescription("")] 14 | [assembly: AssemblyConfiguration("")] 15 | [assembly: AssemblyCompany("Cyotek Ltd")] 16 | [assembly: AssemblyProduct("Simple Screenshot Capture")] 17 | [assembly: AssemblyCopyright("Copyright © 2017-2019 Cyotek Ltd. All Rights Reserved.")] 18 | [assembly: AssemblyTrademark("")] 19 | [assembly: AssemblyCulture("")] 20 | [assembly: ComVisible(false)] 21 | [assembly: CLSCompliant(true)] 22 | [assembly: Guid("ec728998-a741-4388-99e3-29c5f013e011")] 23 | [assembly: AssemblyVersion("2.0.0.0")] 24 | [assembly: AssemblyFileVersion("2.0.0.0")] 25 | -------------------------------------------------------------------------------- /src/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Cyotek.Demo.SimpleScreenshotCapture.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Cyotek.Demo.SimpleScreenshotCapture.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Capture { 67 | get { 68 | object obj = ResourceManager.GetObject("Capture", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap Copy { 77 | get { 78 | object obj = ResourceManager.GetObject("Copy", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap Fill { 87 | get { 88 | object obj = ResourceManager.GetObject("Fill", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap Save { 97 | get { 98 | object obj = ResourceManager.GetObject("Save", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap Timer { 107 | get { 108 | object obj = ResourceManager.GetObject("Timer", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\Copy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\Save.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\Timer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\Camera-Photo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resources\fill.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | -------------------------------------------------------------------------------- /src/Resources/Camera-Photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/Resources/Camera-Photo.png -------------------------------------------------------------------------------- /src/Resources/Copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/Resources/Copy.png -------------------------------------------------------------------------------- /src/Resources/Save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/Resources/Save.png -------------------------------------------------------------------------------- /src/Resources/Timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/Resources/Timer.png -------------------------------------------------------------------------------- /src/Resources/fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/Resources/fill.png -------------------------------------------------------------------------------- /src/ScreenshotCapture.cs: -------------------------------------------------------------------------------- 1 | // Capturing screenshots using C# and p/invoke 2 | // http://www.cyotek.com/blog/capturing-screenshots-using-csharp-and-p-invoke 3 | // Copyright © 2017-2019 Cyotek Ltd. All Rights Reserved. 4 | 5 | // This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | // To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/. 7 | 8 | using System; 9 | using System.ComponentModel; 10 | using System.Drawing; 11 | using System.Drawing.Imaging; 12 | using System.Runtime.InteropServices; 13 | using System.Windows.Forms; 14 | using Cyotek.Windows.Forms; 15 | 16 | namespace Cyotek.Demo.SimpleScreenshotCapture 17 | { 18 | internal sealed class ScreenshotCapture 19 | { 20 | #region Public Methods 21 | 22 | public Bitmap CaptureActiveWindow() 23 | { 24 | return this.CaptureWindow(NativeMethods.GetForegroundWindow()); 25 | } 26 | 27 | public Bitmap CaptureDesktop() 28 | { 29 | return this.CaptureDesktop(false); 30 | } 31 | 32 | public Bitmap CaptureDesktop(bool workingAreaOnly) 33 | { 34 | return this.CaptureDesktop(workingAreaOnly, Color.Transparent); 35 | } 36 | 37 | public Bitmap CaptureDesktop(Color invalidColor) 38 | { 39 | return this.CaptureDesktop(false, invalidColor); 40 | } 41 | 42 | public Bitmap CaptureDesktop(bool workingAreaOnly, Color invalidColor) 43 | { 44 | return CaptureDesktop(workingAreaOnly, invalidColor, index => true); 45 | } 46 | 47 | public Bitmap CaptureDesktop(Predicate includeScreen) 48 | { 49 | return CaptureDesktop(false, Color.Transparent, includeScreen); 50 | } 51 | 52 | public Bitmap CaptureDesktop(bool workingAreaOnly, Color invalidColor, Predicate includeScreen) 53 | { 54 | DesktopLayout layout; 55 | Bitmap bitmap; 56 | 57 | layout = new DesktopLayout 58 | { 59 | WorkingAreaOnly = workingAreaOnly 60 | }; 61 | 62 | bitmap = new Bitmap(layout.Width, layout.Height, PixelFormat.Format32bppArgb); 63 | 64 | using (Graphics g = Graphics.FromImage(bitmap)) 65 | { 66 | g.Clear(invalidColor); 67 | 68 | for (int i = 0; i < layout.Count; i++) 69 | { 70 | if (includeScreen(i)) 71 | { 72 | Rectangle bounds; 73 | 74 | bounds = layout.GetDisplayBounds(i); 75 | 76 | using (Bitmap displayImage = CaptureRegion(bounds)) 77 | { 78 | g.DrawImageUnscaled(displayImage, layout.GetNormalizedDisplayBounds(bounds)); 79 | } 80 | } 81 | } 82 | } 83 | 84 | return bitmap; 85 | } 86 | 87 | public Bitmap CaptureMonitor(Screen monitor) 88 | { 89 | return this.CaptureMonitor(monitor, false); 90 | } 91 | 92 | public Bitmap CaptureMonitor(Screen monitor, bool workingAreaOnly) 93 | { 94 | Rectangle region; 95 | 96 | region = workingAreaOnly ? monitor.WorkingArea : monitor.Bounds; 97 | 98 | return this.CaptureRegion(region); 99 | } 100 | 101 | public Bitmap CaptureMonitor(int index) 102 | { 103 | return this.CaptureMonitor(index, false); 104 | } 105 | 106 | public Bitmap CaptureMonitor(int index, bool workingAreaOnly) 107 | { 108 | return this.CaptureMonitor(Screen.AllScreens[index], workingAreaOnly); 109 | } 110 | 111 | public Bitmap CaptureRegion(Rectangle region) 112 | { 113 | IntPtr desktophWnd; 114 | IntPtr desktopDc; 115 | IntPtr memoryDc; 116 | IntPtr bitmap; 117 | IntPtr oldBitmap; 118 | bool success; 119 | Bitmap result; 120 | 121 | desktophWnd = NativeMethods.GetDesktopWindow(); 122 | desktopDc = NativeMethods.GetWindowDC(desktophWnd); 123 | memoryDc = NativeMethods.CreateCompatibleDC(desktopDc); 124 | bitmap = NativeMethods.CreateCompatibleBitmap(desktopDc, region.Width, region.Height); 125 | oldBitmap = NativeMethods.SelectObject(memoryDc, bitmap); 126 | 127 | success = NativeMethods.BitBlt(memoryDc, 0, 0, region.Width, region.Height, desktopDc, region.Left, region.Top, NativeMethods.RasterOperations.SRCCOPY | NativeMethods.RasterOperations.CAPTUREBLT); 128 | 129 | try 130 | { 131 | if (!success) 132 | { 133 | throw new Win32Exception(); 134 | } 135 | 136 | result = Image.FromHbitmap(bitmap); 137 | } 138 | finally 139 | { 140 | NativeMethods.SelectObject(memoryDc, oldBitmap); 141 | NativeMethods.DeleteObject(bitmap); 142 | NativeMethods.DeleteDC(memoryDc); 143 | NativeMethods.ReleaseDC(desktophWnd, desktopDc); 144 | } 145 | 146 | return result; 147 | } 148 | 149 | public Bitmap CaptureWindow(IntPtr hWnd) 150 | { 151 | NativeMethods.RECT region; 152 | 153 | if (Environment.OSVersion.Version.Major < 6) 154 | { 155 | NativeMethods.GetWindowRect(hWnd, out region); 156 | } 157 | else 158 | { 159 | if (NativeMethods.DwmGetWindowAttribute(hWnd, NativeMethods.DWMWA_EXTENDED_FRAME_BOUNDS, out region, Marshal.SizeOf(typeof(NativeMethods.RECT))) != 0) 160 | { 161 | NativeMethods.GetWindowRect(hWnd, out region); 162 | } 163 | } 164 | 165 | return this.CaptureRegion(Rectangle.FromLTRB(region.left, region.top, region.right, region.bottom)); 166 | } 167 | 168 | public Bitmap CaptureWindow(Form form) 169 | { 170 | return this.CaptureWindow(form.Handle); 171 | } 172 | 173 | #endregion Public Methods 174 | } 175 | } -------------------------------------------------------------------------------- /src/SimpleScreenshotCapture.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EC728998-A741-4388-99E3-29C5F013E011} 8 | WinExe 9 | Properties 10 | Cyotek.Demo.SimpleScreenshotCapture 11 | ssc 12 | v4.6 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | app.manifest 38 | 39 | 40 | 41 | ..\packages\Cyotek.Windows.Forms.ColorPicker.1.7.2\lib\net35\Cyotek.Windows.Forms.ColorPicker.dll 42 | 43 | 44 | ..\packages\CyotekImageBox.1.2.1\lib\net20\Cyotek.Windows.Forms.ImageBox.dll 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Form 61 | 62 | 63 | AboutDialog.cs 64 | 65 | 66 | 67 | Component 68 | 69 | 70 | Component 71 | 72 | 73 | Form 74 | 75 | 76 | MainForm.cs 77 | 78 | 79 | 80 | 81 | 82 | 83 | Component 84 | 85 | 86 | Component 87 | 88 | 89 | AboutDialog.cs 90 | 91 | 92 | MainForm.cs 93 | 94 | 95 | ResXFileCodeGenerator 96 | Resources.Designer.cs 97 | Designer 98 | 99 | 100 | True 101 | Resources.resx 102 | True 103 | 104 | 105 | ToolStripColorPickerDropDown.cs 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 136 | -------------------------------------------------------------------------------- /src/ToolStripColorPickerDropDown.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyotek/SimpleScreenshotCapture/c5a0170adbfadf1437d798d0f9417870d0c82003/src/ToolStripColorPickerDropDown.cs -------------------------------------------------------------------------------- /src/ToolStripColorPickerDropDown.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | False 122 | 123 | -------------------------------------------------------------------------------- /src/ToolStripColorPickerSplitButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | using System.Windows.Forms.Design; 6 | 7 | // Cyotek Color Picker controls library 8 | // Copyright © 2013-2017 Cyotek Ltd. 9 | // http://cyotek.com/blog/tag/colorpicker 10 | 11 | // Licensed under the MIT License. See license.txt for the full text. 12 | 13 | // If you use this code in your applications, donations or attribution are welcome 14 | 15 | namespace Cyotek.Windows.Forms.ToolStripControllerHosts 16 | { 17 | [DefaultProperty("Color")] 18 | [DefaultEvent("ColorChanged")] 19 | [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)] 20 | public class ToolStripColorPickerSplitButton : ToolStripSplitButton 21 | { 22 | #region Constants 23 | 24 | private static readonly object _eventColorChanged = new object(); 25 | 26 | #endregion 27 | 28 | #region Fields 29 | 30 | private Color _color; 31 | 32 | private ToolStripColorPickerDropDown _dropDown; 33 | 34 | #endregion 35 | 36 | #region Constructors 37 | 38 | public ToolStripColorPickerSplitButton() 39 | { 40 | this.Color = Color.Black; 41 | } 42 | 43 | #endregion 44 | 45 | #region Events 46 | 47 | [Category("Property Changed")] 48 | public event EventHandler ColorChanged 49 | { 50 | add { this.Events.AddHandler(_eventColorChanged, value); } 51 | remove { this.Events.RemoveHandler(_eventColorChanged, value); } 52 | } 53 | 54 | #endregion 55 | 56 | #region Properties 57 | 58 | [Category("Data")] 59 | [DefaultValue(typeof(Color), "Black")] 60 | public virtual Color Color 61 | { 62 | get { return _color; } 63 | set 64 | { 65 | if (this.Color != value) 66 | { 67 | _color = value; 68 | 69 | this.OnColorChanged(EventArgs.Empty); 70 | } 71 | } 72 | } 73 | 74 | [Browsable(false)] 75 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 76 | public new ToolStripDropDown DropDown 77 | { 78 | get { return base.DropDown; } 79 | set { base.DropDown = value; } 80 | } 81 | 82 | [Browsable(false)] 83 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 84 | public ColorGrid Host 85 | { 86 | get 87 | { 88 | this.EnsureDropDownIsCreated(); 89 | 90 | return _dropDown.Host; 91 | } 92 | } 93 | 94 | #endregion 95 | 96 | #region Methods 97 | 98 | protected override ToolStripDropDown CreateDefaultDropDown() 99 | { 100 | this.EnsureDropDownIsCreated(); 101 | 102 | return _dropDown; 103 | } 104 | 105 | /// 106 | /// Releases the unmanaged resources used by the and optionally releases the managed resources. 107 | /// 108 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources. 109 | protected override void Dispose(bool disposing) 110 | { 111 | if (disposing) 112 | { 113 | if (_dropDown != null) 114 | { 115 | this.DropDown = null; 116 | _dropDown.Dispose(); 117 | _dropDown.ColorChanged -= this.DropDownColorChangedHandler; 118 | _dropDown = null; 119 | } 120 | } 121 | 122 | base.Dispose(disposing); 123 | } 124 | 125 | /// 126 | /// Raises the event. 127 | /// 128 | /// An that contains the event data. 129 | protected override void OnButtonClick(EventArgs e) 130 | { 131 | base.OnButtonClick(e); 132 | 133 | using (ColorPickerDialog dialog = new ColorPickerDialog()) 134 | { 135 | dialog.Color = this.Color; 136 | 137 | if (dialog.ShowDialog(this.GetCurrentParent()) == DialogResult.OK) 138 | { 139 | this.Color = dialog.Color; 140 | } 141 | } 142 | } 143 | 144 | /// 145 | /// Raises the event. 146 | /// 147 | /// The instance containing the event data. 148 | protected virtual void OnColorChanged(EventArgs e) 149 | { 150 | EventHandler handler; 151 | 152 | this.Invalidate(); 153 | 154 | if (_dropDown != null) 155 | { 156 | _dropDown.Color = this.Color; 157 | } 158 | 159 | handler = (EventHandler)this.Events[_eventColorChanged]; 160 | 161 | handler?.Invoke(this, e); 162 | } 163 | 164 | /// 165 | /// Raised in response to the method. 166 | /// 167 | /// An that contains the event data. 168 | protected override void OnDropDownShow(EventArgs e) 169 | { 170 | this.EnsureDropDownIsCreated(); 171 | base.OnDropDownShow(e); 172 | } 173 | 174 | /// A that contains the event data. 175 | protected override void OnPaint(PaintEventArgs e) 176 | { 177 | Rectangle underline; 178 | 179 | base.OnPaint(e); 180 | 181 | underline = this.GetUnderlineRectangle(e.Graphics); 182 | 183 | using (Brush brush = new SolidBrush(this.Color)) 184 | { 185 | e.Graphics.FillRectangle(brush, underline); 186 | } 187 | } 188 | 189 | private void DropDownColorChangedHandler(object sender, EventArgs e) 190 | { 191 | this.Color = _dropDown.Color; 192 | } 193 | 194 | private void EnsureDropDownIsCreated() 195 | { 196 | if (_dropDown == null) 197 | { 198 | _dropDown = new ToolStripColorPickerDropDown(); 199 | _dropDown.ColorChanged += this.DropDownColorChangedHandler; 200 | } 201 | } 202 | 203 | private Rectangle GetUnderlineRectangle(Graphics g) 204 | { 205 | int x; 206 | int y; 207 | int w; 208 | int h; 209 | 210 | // TODO: These are approximate values and may not work with different font sizes or image sizes etc 211 | 212 | h = 4; // static height! 213 | x = this.ContentRectangle.Left; 214 | y = this.ContentRectangle.Bottom - (h + 1); 215 | 216 | if (this.DisplayStyle == ToolStripItemDisplayStyle.ImageAndText && this.Image != null && !string.IsNullOrEmpty(this.Text)) 217 | { 218 | int innerHeight; 219 | 220 | innerHeight = this.Image.Height - h; 221 | 222 | // got both an image and some text to deal with 223 | w = this.Image.Width; 224 | y = this.ButtonBounds.Top + innerHeight + (this.ButtonBounds.Height - this.Image.Height) / 2; 225 | 226 | switch (this.TextImageRelation) 227 | { 228 | case TextImageRelation.TextBeforeImage: 229 | x = this.ButtonBounds.Right - (w + this.ButtonBounds.Left + 2); 230 | break; 231 | case TextImageRelation.ImageAboveText: 232 | x = this.ButtonBounds.Left + (this.ButtonBounds.Width - this.Image.Width) / 2; 233 | y = this.ButtonBounds.Top + innerHeight + 2; 234 | break; 235 | case TextImageRelation.TextAboveImage: 236 | x = this.ButtonBounds.Left + (this.ButtonBounds.Width - this.Image.Width) / 2; 237 | y = this.ContentRectangle.Bottom - h; 238 | break; 239 | case TextImageRelation.Overlay: 240 | x = this.ButtonBounds.Left + (this.ButtonBounds.Width - this.Image.Width) / 2; 241 | y = this.ButtonBounds.Top + innerHeight + (this.ButtonBounds.Height - this.Image.Height) / 2; 242 | break; 243 | } 244 | } 245 | else if (this.DisplayStyle == ToolStripItemDisplayStyle.Image && this.Image != null) 246 | { 247 | // just the image 248 | w = this.Image.Width; 249 | } 250 | else if (this.DisplayStyle == ToolStripItemDisplayStyle.Text && !string.IsNullOrEmpty(this.Text)) 251 | { 252 | // just the text 253 | w = TextRenderer.MeasureText(g, this.Text, this.Font).Width; 254 | } 255 | else 256 | { 257 | // who knows, use what we have 258 | // TODO: ButtonBounds (and SplitterBounds for that matter) seem to return the wrong 259 | // values when painting first occurs, so the line is too narrow until after you 260 | // hover the mouse over the button 261 | w = this.ButtonBounds.Width - this.ContentRectangle.Left * 2; 262 | } 263 | 264 | return new Rectangle(x, y, w, h); 265 | } 266 | 267 | #endregion 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | true/PM 7 | 8 | 9 | 10 | 11 | 12 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | --------------------------------------------------------------------------------