aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerghei Cebotari <serghei@cebotari.ru>2024-11-06 23:43:00 +0300
committerSerghei Cebotari <serghei@cebotari.ru>2024-11-06 23:43:00 +0300
commitdbaa8b111a5d869159db7e58b14c026806265874 (patch)
tree191b74ec9163cfdb693b1cc0e87081065a81bfa0
parenta065c4c6990e959742faa1bf8bb7ef960146978b (diff)
Add snipping tool
-rw-r--r--RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs106
-rw-r--r--RhSolutions.AddIn/Controllers/RibbonController.cs249
-rw-r--r--RhSolutions.AddIn/RhSolutions-AddIn.dna1
-rw-r--r--RhSolutions.AddIn/RhSolutions.AddIn.csproj1
-rw-r--r--RhSolutions.AddIn/Tools/OcrTool.cs22
-rw-r--r--RhSolutions.AddIn/Tools/Tool.cs32
-rw-r--r--RhSolutions.AddIn/Tools/ToolFactory.cs37
-rw-r--r--RhSolutions.sln6
-rw-r--r--SnippingTool/SnippingTool.Designer.cs38
-rw-r--r--SnippingTool/SnippingTool.cs86
-rw-r--r--SnippingTool/SnippingTool.csproj12
11 files changed, 380 insertions, 210 deletions
diff --git a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
index 983c0e6..1666df4 100644
--- a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
+++ b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
@@ -4,57 +4,57 @@ namespace RhSolutions.AddIn;
public sealed class RhSolutionsAddIn : IExcelAddIn
{
- public static Application Excel { get; private set; }
- public static ServiceProvider ServiceProvider { get; private set; }
- public static IAddInConfiguration Configuration { get; private set; }
-
- public void AutoOpen()
- {
- IServiceCollection Services = new ServiceCollection();
-
- Services.AddHttpClient()
- .AddMemoryCache()
- .AddSingleton((Application)ExcelDnaUtil.Application)
- .AddSingleton<IAddInConfiguration, AddInConfiguration>()
- .AddSingleton<IDatabaseClient, DatabaseClient>()
- .AddSingleton<ICurrencyClient, CurrencyClient>()
- .AddTransient<IFileDialog, FileDialog>();
-
- Services.AddSingleton<WriterFactory>();
- Services.AddTransient<NewPriceWriter>()
- .AddTransient<IWriter, NewPriceWriter>(s => s.GetService<NewPriceWriter>());
- Services.AddTransient<DxfWriter>()
- .AddTransient<IWriter, DxfWriter>(s => s.GetService<DxfWriter>());
- Services.AddTransient<CurrentPriceWriter>()
- .AddTransient<IWriter, CurrentPriceWriter>(s => s.GetService<CurrentPriceWriter>());
-
- Services.AddSingleton<ReaderFactory>();
- Services.AddTransient<ExcelReader>()
- .AddTransient<IReader, ExcelReader>(s => s.GetService<ExcelReader>());
- Services.AddTransient<GuessReader>()
- .AddTransient<IReader, GuessReader>(s => s.GetService<GuessReader>());
-
- Services.AddSingleton<FittingsCalculatorFactory>();
- Services.AddTransient<CouplingsCalculator>()
- .AddTransient<IFittingsCalculator, CouplingsCalculator>(s => s.GetService<CouplingsCalculator>());
- Services.AddTransient<SleevesCalculator>()
- .AddTransient<IFittingsCalculator, SleevesCalculator>(s => s.GetService<SleevesCalculator>());
-
- Services.AddSingleton<ToolFactory>();
-
- ServiceProvider = Services.BuildServiceProvider();
- Configuration = ServiceProvider.GetService<IAddInConfiguration>();
- Excel = ServiceProvider.GetService<Application>();
-
- EventsUtil.Initialize();
-
- ServicePointManager.SecurityProtocol =
- SecurityProtocolType.Tls12;
- ServicePointManager.DefaultConnectionLimit = 50;
- }
-
- public void AutoClose()
- {
- EventsUtil.Uninitialize();
- }
+ public static Application Excel { get; private set; }
+ public static ServiceProvider ServiceProvider { get; private set; }
+ public static IAddInConfiguration Configuration { get; private set; }
+
+ public void AutoOpen()
+ {
+ IServiceCollection Services = new ServiceCollection();
+
+ Services.AddHttpClient()
+ .AddMemoryCache()
+ .AddSingleton((Application)ExcelDnaUtil.Application)
+ .AddSingleton<IAddInConfiguration, AddInConfiguration>()
+ .AddSingleton<IDatabaseClient, DatabaseClient>()
+ .AddSingleton<ICurrencyClient, CurrencyClient>()
+ .AddTransient<IFileDialog, FileDialog>();
+
+ Services.AddSingleton<WriterFactory>();
+ Services.AddTransient<NewPriceWriter>()
+ .AddTransient<IWriter, NewPriceWriter>(s => s.GetService<NewPriceWriter>());
+ Services.AddTransient<DxfWriter>()
+ .AddTransient<IWriter, DxfWriter>(s => s.GetService<DxfWriter>());
+ Services.AddTransient<CurrentPriceWriter>()
+ .AddTransient<IWriter, CurrentPriceWriter>(s => s.GetService<CurrentPriceWriter>());
+
+ Services.AddSingleton<ReaderFactory>();
+ Services.AddTransient<ExcelReader>()
+ .AddTransient<IReader, ExcelReader>(s => s.GetService<ExcelReader>());
+ Services.AddTransient<GuessReader>()
+ .AddTransient<IReader, GuessReader>(s => s.GetService<GuessReader>());
+
+ Services.AddSingleton<FittingsCalculatorFactory>();
+ Services.AddTransient<CouplingsCalculator>()
+ .AddTransient<IFittingsCalculator, CouplingsCalculator>(s => s.GetService<CouplingsCalculator>());
+ Services.AddTransient<SleevesCalculator>()
+ .AddTransient<IFittingsCalculator, SleevesCalculator>(s => s.GetService<SleevesCalculator>());
+
+ Services.AddSingleton<ToolFactory>();
+
+ ServiceProvider = Services.BuildServiceProvider();
+ Configuration = ServiceProvider.GetService<IAddInConfiguration>();
+ Excel = ServiceProvider.GetService<Application>();
+
+ EventsUtil.Initialize();
+
+ ServicePointManager.SecurityProtocol =
+ SecurityProtocolType.Tls12;
+ ServicePointManager.DefaultConnectionLimit = 50;
+ }
+
+ public void AutoClose()
+ {
+ EventsUtil.Uninitialize();
+ }
}
diff --git a/RhSolutions.AddIn/Controllers/RibbonController.cs b/RhSolutions.AddIn/Controllers/RibbonController.cs
index aecdc02..9123940 100644
--- a/RhSolutions.AddIn/Controllers/RibbonController.cs
+++ b/RhSolutions.AddIn/Controllers/RibbonController.cs
@@ -9,127 +9,130 @@ namespace RhSolutions.Controllers;
[ComVisible(true)]
public class RibbonController : ExcelRibbon
{
- private static IRibbonUI ribbonUi;
- private static bool _workbookIsValid;
-
- public override string GetCustomUI(string RibbonID)
- {
- return @"
- <customUI onLoad='RibbonLoad' xmlns='http://schemas.microsoft.com/office/2006/01/customui' loadImage='LoadImage'>
- <ribbon>
- <tabs>
- <tab id='rau' label='RhSolutions'>
- <group id='priceList' label='Прайс-лист'>
- <button id='export' getEnabled='GetExportEnabled' label='Экспорт в новый файл' size='normal' image='RhSolutions' onAction='OnToolPressed'/>
- <button id='convert' getEnabled='GetConvertEnabled' label='Актуализировать' size='normal' imageMso='FileUpdate' onAction='OnToolPressed'/>
- <button id='merge' label='Объединить' size='normal' imageMso='Copy' onAction='OnToolPressed'/>
- <button id='guess' getEnabled='GetGuessEnabled' label='Найти и экспортировать' size='large' imageMso='ControlWizards' onAction='OnToolPressed'/>
- </group>
- <group id='fittingsCalc' label='Расчет фитингов'>
- <button id='fillsleeves' getEnabled='GetFittingsCalcEnabled' label='Гильзы' size='large' image='Sleeve' onAction='OnToolPressed'/>
- <button id='fillcouplings' getEnabled='GetFittingsCalcEnabled' label='Муфты' size='large' image='Coupling' onAction='OnToolPressed'/>
- </group>
- <group id='exportTab' label='Экспорт'>
- <button id='dxfexport' getEnabled='GetDxfEnabled' label='DXF' size='large' image='DXF' onAction='OnToolPressed'/>
- </group>
- <group id='settings' getLabel='GetVersionLabel'>
- <button id='setPriceList' getLabel='GetPriceListPathLabel' size='large' image='RhSolutions' onAction='OnSetPricePressed'/>
- </group>
- </tab>
- </tabs>
- </ribbon>
- </customUI>";
- }
-
- public void RibbonLoad(IRibbonUI sender)
- {
- ribbonUi = sender;
- }
-
- public static void RefreshControl(string id)
- {
- ribbonUi?.InvalidateControl(id);
- }
-
- public void OnSetPricePressed(IRibbonControl control)
- {
- IFileDialog dialog = RhSolutionsAddIn.ServiceProvider.GetService<IFileDialog>();
- string file = dialog.GetFile();
-
- if (!string.IsNullOrEmpty(file))
- {
- RhSolutionsAddIn.Configuration.SetPriceListPath(file);
- RhSolutionsAddIn.Configuration.SaveSettings();
- }
- }
-
- public void OnToolPressed(IRibbonControl control)
- {
- try
- {
- var toolFactory = RhSolutionsAddIn.ServiceProvider.GetService<ToolFactory>();
- using Tool tool = toolFactory.GetTool(control.Id);
- tool.Execute();
- }
-
- catch (Exception exception)
- {
- MessageBox.Show(exception.Message,
- "Ошибка",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information);
- RhSolutionsAddIn.Excel.StatusBar = false;
- return;
- }
- }
-
- public bool GetConvertEnabled(IRibbonControl control) => _workbookIsValid;
- public bool GetDxfEnabled(IRibbonControl control) => _workbookIsValid;
- public bool GetFittingsCalcEnabled(IRibbonControl control) => _workbookIsValid;
- public bool GetGuessEnabled(IRibbonControl control) => RhSolutionsAddIn.Excel.ActiveWorkbook != null && !_workbookIsValid;
-
- public bool GetExportEnabled(IRibbonControl control)
- {
- if (RhSolutionsAddIn.Excel.ActiveWorkbook == null)
- return false;
-
- else
- {
- Range selection = RhSolutionsAddIn.Excel.Selection;
- return selection.Columns.Count == 2;
- }
- }
-
- public string GetVersionLabel(IRibbonControl control)
- {
- string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
- return $"v{version}";
- }
-
- public string GetPriceListPathLabel(IRibbonControl control)
- {
- string name = RhSolutionsAddIn.Configuration.GetPriceListFileName();
- return string.IsNullOrEmpty(name) ? "Указать шаблонный файл" : name;
- }
-
- public static void UpdateWorkbookValidation()
- {
- if (RhSolutionsAddIn.Excel.ActiveWorkbook == null)
- _workbookIsValid = false;
-
- else
- {
- Worksheet worksheet = RhSolutionsAddIn.Excel.ActiveWorkbook.ActiveSheet;
- _workbookIsValid = worksheet.IsValidSource();
- }
- }
-
- public static void EnsurePriseListExists()
- {
- string pricelistPath = RhSolutionsAddIn.Configuration.GetPriceListPath();
- if (!File.Exists(pricelistPath))
- {
- RhSolutionsAddIn.Configuration.SetPriceListPath(string.Empty);
- }
- }
+ private static IRibbonUI ribbonUi;
+ private static bool _workbookIsValid;
+
+ public override string GetCustomUI(string RibbonID)
+ {
+ return @"
+ <customUI onLoad='RibbonLoad' xmlns='http://schemas.microsoft.com/office/2006/01/customui' loadImage='LoadImage'>
+ <ribbon>
+ <tabs>
+ <tab id='rau' label='RhSolutions'>
+ <group id='priceList' label='Прайс-лист'>
+ <button id='export' getEnabled='GetExportEnabled' label='Экспорт в новый файл' size='normal' image='RhSolutions' onAction='OnToolPressed'/>
+ <button id='convert' getEnabled='GetConvertEnabled' label='Актуализировать' size='normal' imageMso='FileUpdate' onAction='OnToolPressed'/>
+ <button id='merge' label='Объединить' size='normal' imageMso='Copy' onAction='OnToolPressed'/>
+ <button id='guess' getEnabled='GetGuessEnabled' label='Найти и экспортировать' size='large' imageMso='ControlWizards' onAction='OnToolPressed'/>
+ </group>
+ <group id='fittingsCalc' label='Расчет фитингов'>
+ <button id='fillsleeves' getEnabled='GetFittingsCalcEnabled' label='Гильзы' size='large' image='Sleeve' onAction='OnToolPressed'/>
+ <button id='fillcouplings' getEnabled='GetFittingsCalcEnabled' label='Муфты' size='large' image='Coupling' onAction='OnToolPressed'/>
+ </group>
+ <group id='exportTab' label='Экспорт'>
+ <button id='dxfexport' getEnabled='GetDxfEnabled' label='DXF' size='large' image='DXF' onAction='OnToolPressed'/>
+ </group>
+ <group id='importTab' label='OCR'>
+ <button id='ocr' label='Распознать таблицу' size='large' imageMso='TableInsert' onAction='OnToolPressed'/>
+ </group>
+ <group id='settings' getLabel='GetVersionLabel'>
+ <button id='setPriceList' getLabel='GetPriceListPathLabel' size='large' image='RhSolutions' onAction='OnSetPricePressed'/>
+ </group>
+ </tab>
+ </tabs>
+ </ribbon>
+ </customUI>";
+ }
+
+ public void RibbonLoad(IRibbonUI sender)
+ {
+ ribbonUi = sender;
+ }
+
+ public static void RefreshControl(string id)
+ {
+ ribbonUi?.InvalidateControl(id);
+ }
+
+ public void OnSetPricePressed(IRibbonControl control)
+ {
+ IFileDialog dialog = RhSolutionsAddIn.ServiceProvider.GetService<IFileDialog>();
+ string file = dialog.GetFile();
+
+ if (!string.IsNullOrEmpty(file))
+ {
+ RhSolutionsAddIn.Configuration.SetPriceListPath(file);
+ RhSolutionsAddIn.Configuration.SaveSettings();
+ }
+ }
+
+ public void OnToolPressed(IRibbonControl control)
+ {
+ try
+ {
+ var toolFactory = RhSolutionsAddIn.ServiceProvider.GetService<ToolFactory>();
+ using Tool tool = toolFactory.GetTool(control.Id);
+ tool.Execute();
+ }
+
+ catch (Exception exception)
+ {
+ MessageBox.Show(exception.Message,
+ "Ошибка",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Information);
+ RhSolutionsAddIn.Excel.StatusBar = false;
+ return;
+ }
+ }
+
+ public bool GetConvertEnabled(IRibbonControl control) => _workbookIsValid;
+ public bool GetDxfEnabled(IRibbonControl control) => _workbookIsValid;
+ public bool GetFittingsCalcEnabled(IRibbonControl control) => _workbookIsValid;
+ public bool GetGuessEnabled(IRibbonControl control) => RhSolutionsAddIn.Excel.ActiveWorkbook != null && !_workbookIsValid;
+
+ public bool GetExportEnabled(IRibbonControl control)
+ {
+ if (RhSolutionsAddIn.Excel.ActiveWorkbook == null)
+ return false;
+
+ else
+ {
+ Range selection = RhSolutionsAddIn.Excel.Selection;
+ return selection.Columns.Count == 2;
+ }
+ }
+
+ public string GetVersionLabel(IRibbonControl control)
+ {
+ string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ return $"v{version}";
+ }
+
+ public string GetPriceListPathLabel(IRibbonControl control)
+ {
+ string name = RhSolutionsAddIn.Configuration.GetPriceListFileName();
+ return string.IsNullOrEmpty(name) ? "Указать шаблонный файл" : name;
+ }
+
+ public static void UpdateWorkbookValidation()
+ {
+ if (RhSolutionsAddIn.Excel.ActiveWorkbook == null)
+ _workbookIsValid = false;
+
+ else
+ {
+ Worksheet worksheet = RhSolutionsAddIn.Excel.ActiveWorkbook.ActiveSheet;
+ _workbookIsValid = worksheet.IsValidSource();
+ }
+ }
+
+ public static void EnsurePriseListExists()
+ {
+ string pricelistPath = RhSolutionsAddIn.Configuration.GetPriceListPath();
+ if (!File.Exists(pricelistPath))
+ {
+ RhSolutionsAddIn.Configuration.SetPriceListPath(string.Empty);
+ }
+ }
}
diff --git a/RhSolutions.AddIn/RhSolutions-AddIn.dna b/RhSolutions.AddIn/RhSolutions-AddIn.dna
index a28cea0..1c5ee48 100644
--- a/RhSolutions.AddIn/RhSolutions-AddIn.dna
+++ b/RhSolutions.AddIn/RhSolutions-AddIn.dna
@@ -23,6 +23,7 @@
<Reference Path="System.Runtime.CompilerServices.Unsafe.dll" Pack="true" />
<Reference Path="System.Threading.Tasks.Extensions.dll" Pack="true" />
<Reference Path="System.ValueTuple.dll" Pack="true" />
+ <Reference Path="SnippingTool.dll" Pack="true" />
<Image Name='RhSolutions' Path='Images\RhSolutions.png' Pack='true' />
<Image Name='DXF' Path='Images\DXF.png' Pack='true' />
<Image Name='Sleeve' Path='Images\Sleeve.png' Pack='true' />
diff --git a/RhSolutions.AddIn/RhSolutions.AddIn.csproj b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
index 70431d4..9963e0c 100644
--- a/RhSolutions.AddIn/RhSolutions.AddIn.csproj
+++ b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
@@ -26,6 +26,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RhSolutions.ProductSku\RhSolutions.ProductSku.csproj" />
+ <ProjectReference Include="..\SnippingTool\SnippingTool.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Images\Coupling.png">
diff --git a/RhSolutions.AddIn/Tools/OcrTool.cs b/RhSolutions.AddIn/Tools/OcrTool.cs
new file mode 100644
index 0000000..4e0f828
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/OcrTool.cs
@@ -0,0 +1,22 @@
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+
+namespace RhSolutions.Tools;
+
+internal class OcrTool : Tool
+{
+ public OcrTool(ReaderFactory readerFactory, WriterFactory writerFactory) : base(readerFactory, writerFactory)
+ {
+ }
+
+ public override void Execute()
+ {
+ var bmp = SnippingTool.SnippingTool.Snip();
+ if (bmp != null)
+ {
+ // Do something with the bitmap
+ //...
+ }
+ }
+} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Tools/Tool.cs b/RhSolutions.AddIn/Tools/Tool.cs
index c438ff9..efb66f0 100644
--- a/RhSolutions.AddIn/Tools/Tool.cs
+++ b/RhSolutions.AddIn/Tools/Tool.cs
@@ -9,22 +9,22 @@ namespace RhSolutions.Tools;
#endif
internal abstract class Tool : IDisposable
{
- protected readonly ReaderFactory _readerFactory;
- protected readonly WriterFactory _writerFactory;
- protected IReader _reader;
- protected IWriter _writer;
+ protected readonly ReaderFactory _readerFactory;
+ protected readonly WriterFactory _writerFactory;
+ protected IReader _reader;
+ protected IWriter _writer;
- public Tool(ReaderFactory readerFactory, WriterFactory writerFactory)
- {
- _readerFactory = readerFactory;
- _writerFactory = writerFactory;
- }
+ public Tool(ReaderFactory readerFactory, WriterFactory writerFactory)
+ {
+ _readerFactory = readerFactory;
+ _writerFactory = writerFactory;
+ }
- public void Dispose()
- {
- _reader?.Dispose();
- _writer?.Dispose();
- }
+ public void Dispose()
+ {
+ _reader?.Dispose();
+ _writer?.Dispose();
+ }
- public abstract void Execute();
-} \ No newline at end of file
+ public abstract void Execute();
+}
diff --git a/RhSolutions.AddIn/Tools/ToolFactory.cs b/RhSolutions.AddIn/Tools/ToolFactory.cs
index 646fc15..e65ab0c 100644
--- a/RhSolutions.AddIn/Tools/ToolFactory.cs
+++ b/RhSolutions.AddIn/Tools/ToolFactory.cs
@@ -2,23 +2,24 @@
internal class ToolFactory
{
- static ReaderFactory readerFactory = RhSolutionsAddIn.ServiceProvider.GetService<ReaderFactory>();
- static WriterFactory writerFactory = RhSolutionsAddIn.ServiceProvider.GetService<WriterFactory>();
- static FittingsCalculatorFactory fittingsCalculatorFactory = RhSolutionsAddIn.ServiceProvider.GetService<FittingsCalculatorFactory>();
+ static ReaderFactory readerFactory = RhSolutionsAddIn.ServiceProvider.GetService<ReaderFactory>();
+ static WriterFactory writerFactory = RhSolutionsAddIn.ServiceProvider.GetService<WriterFactory>();
+ static FittingsCalculatorFactory fittingsCalculatorFactory = RhSolutionsAddIn.ServiceProvider.GetService<FittingsCalculatorFactory>();
- public Tool GetTool(string toolName)
- {
- Tool tool = toolName switch
- {
- "export" => new ExportTool(readerFactory, writerFactory),
- "convert" => new ConvertTool(readerFactory, writerFactory),
- "merge" => new MergeTool(readerFactory, writerFactory),
- "dxfexport" => new DxfTool(readerFactory, writerFactory),
- "guess" => new GuessTool(readerFactory, writerFactory),
- "fillsleeves" => new FittingsTool(readerFactory, writerFactory, fittingsCalculatorFactory, "Sleeves"),
- "fillcouplings" => new FittingsTool(readerFactory, writerFactory, fittingsCalculatorFactory, "Couplings"),
- _ => throw new Exception($"Неизвестный инструмент {toolName}"),
- };
- return tool;
- }
+ public Tool GetTool(string toolName)
+ {
+ Tool tool = toolName switch
+ {
+ "export" => new ExportTool(readerFactory, writerFactory),
+ "convert" => new ConvertTool(readerFactory, writerFactory),
+ "merge" => new MergeTool(readerFactory, writerFactory),
+ "dxfexport" => new DxfTool(readerFactory, writerFactory),
+ "guess" => new GuessTool(readerFactory, writerFactory),
+ "fillsleeves" => new FittingsTool(readerFactory, writerFactory, fittingsCalculatorFactory, "Sleeves"),
+ "fillcouplings" => new FittingsTool(readerFactory, writerFactory, fittingsCalculatorFactory, "Couplings"),
+ "ocr" => new OcrTool(readerFactory, writerFactory),
+ _ => throw new Exception($"Неизвестный инструмент {toolName}"),
+ };
+ return tool;
+ }
}
diff --git a/RhSolutions.sln b/RhSolutions.sln
index 610e085..a47ff74 100644
--- a/RhSolutions.sln
+++ b/RhSolutions.sln
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhSolutions.Tests", "RhSolu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhSolutions.ProductSku", "RhSolutions.ProductSku\RhSolutions.ProductSku.csproj", "{59CD05D0-71E0-4027-968A-8BE89A6FDCEF}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnippingTool", "SnippingTool\SnippingTool.csproj", "{DDB517C7-DF61-4C26-B691-956D0E5906C3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
{59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59CD05D0-71E0-4027-968A-8BE89A6FDCEF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DDB517C7-DF61-4C26-B691-956D0E5906C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DDB517C7-DF61-4C26-B691-956D0E5906C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DDB517C7-DF61-4C26-B691-956D0E5906C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DDB517C7-DF61-4C26-B691-956D0E5906C3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/SnippingTool/SnippingTool.Designer.cs b/SnippingTool/SnippingTool.Designer.cs
new file mode 100644
index 0000000..322a511
--- /dev/null
+++ b/SnippingTool/SnippingTool.Designer.cs
@@ -0,0 +1,38 @@
+namespace SnippingTool;
+
+partial class SnippingTool
+{
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Text = "Form1";
+ }
+
+ #endregion
+}
diff --git a/SnippingTool/SnippingTool.cs b/SnippingTool/SnippingTool.cs
new file mode 100644
index 0000000..bd08076
--- /dev/null
+++ b/SnippingTool/SnippingTool.cs
@@ -0,0 +1,86 @@
+namespace SnippingTool;
+
+public partial class SnippingTool : Form
+{
+ public static Image? Snip()
+ {
+ var rc = Screen.PrimaryScreen.Bounds;
+ using Bitmap bmp = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
+ using Graphics gr = Graphics.FromImage(bmp);
+ gr.CopyFromScreen(0, 0, 0, 0, bmp.Size);
+ using var snipper = new SnippingTool(bmp);
+
+ return snipper.ShowDialog() == DialogResult.OK ? snipper.Image : null;
+ }
+
+ public SnippingTool(Image screenShot)
+ {
+ InitializeComponent();
+ BackgroundImage = screenShot;
+ ShowInTaskbar = false;
+ FormBorderStyle = FormBorderStyle.None;
+ WindowState = FormWindowState.Maximized;
+ DoubleBuffered = true;
+ }
+ public Image? Image { get; set; }
+
+ private Rectangle rcSelect = new Rectangle();
+ private Point pntStart;
+
+ protected override void OnMouseDown(MouseEventArgs e)
+ {
+ if (e.Button != MouseButtons.Left)
+ {
+ return;
+ }
+ pntStart = e.Location;
+ rcSelect = new Rectangle(e.Location, new Size(0, 0));
+ Invalidate();
+ }
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ if (e.Button != MouseButtons.Left)
+ {
+ return;
+ }
+ int x1 = Math.Min(e.X, pntStart.X);
+ int y1 = Math.Min(e.Y, pntStart.Y);
+ int x2 = Math.Max(e.X, pntStart.X);
+ int y2 = Math.Max(e.Y, pntStart.Y);
+ rcSelect = new Rectangle(x1, y1, x2 - x1, y2 - y1);
+ Invalidate();
+ }
+ protected override void OnMouseUp(MouseEventArgs e)
+ {
+ if (rcSelect.Width <= 0 || rcSelect.Height <= 0)
+ {
+ return;
+ }
+ Image = new Bitmap(rcSelect.Width, rcSelect.Height);
+ using Graphics gr = Graphics.FromImage(Image);
+ gr.DrawImage(BackgroundImage, new Rectangle(0, 0, Image.Width, Image.Height),
+ rcSelect, GraphicsUnit.Pixel);
+ DialogResult = DialogResult.OK;
+ }
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ using Brush br = new SolidBrush(Color.FromArgb(120, Color.White));
+ int x1 = rcSelect.X; int x2 = rcSelect.X + rcSelect.Width;
+ int y1 = rcSelect.Y; int y2 = rcSelect.Y + rcSelect.Height;
+ e.Graphics.FillRectangle(br, new Rectangle(0, 0, x1, Height));
+ e.Graphics.FillRectangle(br, new Rectangle(x2, 0, Width - x2, Height));
+ e.Graphics.FillRectangle(br, new Rectangle(x1, 0, x2 - x1, y1));
+ e.Graphics.FillRectangle(br, new Rectangle(x1, y2, x2 - x1, Height - y2));
+
+ using Pen pen = new Pen(Color.Red, 3);
+ e.Graphics.DrawRectangle(pen, rcSelect);
+ }
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+ {
+ if (keyData == Keys.Escape)
+ {
+ DialogResult = DialogResult.Cancel;
+ }
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+} \ No newline at end of file
diff --git a/SnippingTool/SnippingTool.csproj b/SnippingTool/SnippingTool.csproj
new file mode 100644
index 0000000..a16e30c
--- /dev/null
+++ b/SnippingTool/SnippingTool.csproj
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <LangVersion>10</LangVersion>
+ <TargetFrameworks>net472;net6.0-windows</TargetFrameworks>
+ <Nullable>enable</Nullable>
+ <UseWindowsForms>true</UseWindowsForms>
+ <ImplicitUsings>enable</ImplicitUsings>
+ </PropertyGroup>
+
+</Project> \ No newline at end of file