├── wfc.png
├── nugetNetCoreRelease.ps1
├── example1.png
├── SampleProject
├── SampleFormApplication
│ ├── App.config
│ ├── Properties
│ │ ├── Settings.settings
│ │ ├── Settings.Designer.cs
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── Program.cs
│ ├── SampleFormApplication.csproj
│ ├── Form1.resx
│ ├── Form1.cs
│ └── Form1.Designer.cs
└── SampleFormApplicationCore
│ └── SampleFormApplicationCore.csproj
├── src
└── WindowsForms.Console
│ ├── _Globals.cs
│ ├── QueueTaskObject.cs
│ ├── Enums
│ └── ConsoleState.cs
│ ├── QueueTask.cs
│ ├── WindowsForms.Console.csproj
│ ├── Extensions
│ └── FConsoleExtensions.cs
│ └── FConsole.cs
├── LICENSE
├── WindowsFormBuild.ps1
├── SECURITY.md
├── .gitattributes
├── README.md
├── WindowsForms.Console.sln
├── appveyor.yml
├── WindowsForms.Console.nuspec
└── .gitignore
/wfc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msx752/WindowsForms.Console/HEAD/wfc.png
--------------------------------------------------------------------------------
/nugetNetCoreRelease.ps1:
--------------------------------------------------------------------------------
1 | dotnet build -c Release -p:PackageVersion=2.0.10
2 | pause
--------------------------------------------------------------------------------
/example1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/msx752/WindowsForms.Console/HEAD/example1.png
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/WindowsForms.Console/_Globals.cs:
--------------------------------------------------------------------------------
1 | global using System;
2 | global using System.Collections.Concurrent;
3 | global using System.Collections.Generic;
4 | global using System.Diagnostics;
5 | global using System.Drawing;
6 | global using System.Linq;
7 | global using System.Runtime.InteropServices;
8 | global using System.Threading;
9 | global using System.Threading.Tasks;
10 | global using System.Windows.Forms;
11 | global using WindowsForms.Console.Enums;
--------------------------------------------------------------------------------
/src/WindowsForms.Console/QueueTaskObject.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsForms.Console;
2 |
3 | internal readonly struct QueueTaskObject
4 | {
5 | public QueueTaskObject(string message, Color? color, bool showTimeTag)
6 | {
7 | Message = message;
8 | Color = color;
9 | ShowTimeTag = showTimeTag;
10 | }
11 |
12 | public Color? Color { get; }
13 | public string Message { get; }
14 | public bool ShowTimeTag { get; }
15 | }
16 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace SampleFormApplication
5 | {
6 | internal static class Program
7 | {
8 | ///
9 | /// The main entry point for the application.
10 | ///
11 | [STAThread]
12 | private static void Main()
13 | {
14 | Application.EnableVisualStyles();
15 | Application.SetCompatibleTextRenderingDefault(false);
16 | Application.Run(new Form1());
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/WindowsForms.Console/Enums/ConsoleState.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsForms.Console.Enums;
2 |
3 | ///
4 | /// Represents the various states that the FConsole can be in.
5 | ///
6 | public enum ConsoleState
7 | {
8 | ///
9 | /// The console is waiting for the user to input a full line of text.
10 | ///
11 | ReadLine = 0,
12 |
13 | ///
14 | /// The console is waiting for a single key press from the user.
15 | ///
16 | ReadKey = 1,
17 |
18 | ///
19 | /// The console is in the process of closing and is no longer accepting input.
20 | ///
21 | Closing = 2,
22 |
23 | ///
24 | /// The console is actively writing output to the display.
25 | ///
26 | Writing = 3
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Mustafa Salih ASLIM
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Properties/Settings.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 SampleFormApplication.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/WindowsFormBuild.ps1:
--------------------------------------------------------------------------------
1 |
2 | if($($env:APPVEYOR)){
3 | $msbuild = "C:\Program Files (x86)\MSBuild\15.0\Bin\amd64\MSBuild.exe"
4 | }else{
5 |
6 | $msbuild = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
7 | }
8 |
9 | .\nuget restore WindowsForms.Console.sln;
10 |
11 | & $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.5 /p:OutputPath="bin\v4.5";
12 | & $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.5.1 /p:OutputPath="bin\v4.5.1";
13 | & $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.5.2 /p:OutputPath="bin\v4.5.2";
14 | & $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.6 /p:OutputPath="bin\v4.6";
15 | & $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.6.1 /p:OutputPath="bin\v4.6.1";
16 | & $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.6.2 /p:OutputPath="bin\v4.6.2";
17 | #& $msbuild WindowsForms.Console.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.7 /p:OutputPath="bin\v4.7";
18 |
19 | .\nuget pack WindowsForm.Console.nuspec;
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("SampleFormApplication")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("SampleFormApplication")]
12 | [assembly: AssemblyCopyright("Copyright © 2017")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("d6755ede-9f23-4986-9ad5-a817fbc0a556")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Below are the .NET versions currently supported with security updates. To ensure your applications remain secure and up-to-date, please use a supported version:
6 |
7 | | Version | Supported |
8 | | ---------------- | ------------------ |
9 | | WPF | :x: |
10 | | < net48 | :x: |
11 | | net48 | :white_check_mark: |
12 | | netcoreapp3.0 | :white_check_mark: |
13 | | netcoreapp3.1 | :white_check_mark: |
14 | | net5.0-windows | :white_check_mark: |
15 | | net6.0-windows | :white_check_mark: |
16 | | net7.0-windows | :white_check_mark: |
17 | | net8.0-windows | :white_check_mark: |
18 | | net9.0-windows | :white_check_mark: |
19 |
20 | ## Reporting a Vulnerability
21 |
22 | If you discover a security vulnerability in our project, please report it using the following process:
23 |
24 | Open an Issue: Go to our issue tracker and create a new issue. Include as much detail as possible, such as steps to reproduce the vulnerability and its potential impact.
25 |
26 | Acknowledgment: We will acknowledge your report by commenting on the issue.
27 |
28 | Assessment: Our security team will assess the vulnerability and determine its severity. We may request additional information from you during this process.
29 |
30 | Updates: You will receive updates on the status of your report through the issue tracker.
31 |
32 | Resolution: If the vulnerability is confirmed, we will work on a fix and provide an estimated timeline for the release of a security update. If the vulnerability is not confirmed, we will explain our reasoning in the issue comments.
33 |
34 | Disclosure: Once a fix is implemented and released, we will publicly disclose the vulnerability details and credit you for your responsible reporting.
35 |
36 | Thank you for helping us maintain a secure project. Your diligence in reporting vulnerabilities plays a crucial role in protecting our community.
37 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplicationCore/SampleFormApplicationCore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net9.0-windows
6 | true
7 | SampleFormApplication
8 |
9 |
10 |
11 | x64
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Form
38 |
39 |
40 | Form1.cs
41 |
42 |
43 |
44 |
45 |
46 | Form1.cs
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | SettingsSingleFileGenerator
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/WindowsForms.Console/QueueTask.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsForms.Console;
2 |
3 | internal class QueueTask : IDisposable
4 | {
5 | private readonly Task _backgroundTask;
6 | private readonly CancellationTokenSource _cancellationTokenSource;
7 | private readonly FConsole _fConsole;
8 | private bool _disposed;
9 | private readonly ConcurrentQueue _tasks;
10 |
11 | public QueueTask(FConsole fConsole)
12 | {
13 | _cancellationTokenSource = new CancellationTokenSource();
14 | _tasks = new ConcurrentQueue();
15 | _fConsole = fConsole;
16 |
17 | _backgroundTask = Task.Factory.StartNew(ProcessQueue, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
18 | }
19 |
20 | public void Enqueue(QueueTaskObject task)
21 | {
22 | _tasks.Enqueue(task);
23 | }
24 |
25 | public void Dispose()
26 | {
27 | Dispose(true);
28 | GC.SuppressFinalize(this);
29 | }
30 |
31 | protected virtual void Dispose(bool disposing)
32 | {
33 | if (!_disposed)
34 | {
35 | if (disposing)
36 | {
37 | _cancellationTokenSource.Cancel();
38 | _backgroundTask.Dispose();
39 | #if !NET48
40 | _tasks.Clear();
41 | #endif
42 | }
43 |
44 | _disposed = true;
45 | }
46 | }
47 |
48 | private async Task ProcessQueue()
49 | {
50 | var spinWait = new SpinWait();
51 |
52 | try
53 | {
54 | while (!_disposed)
55 | {
56 | if (_tasks.TryDequeue(out QueueTaskObject task))
57 | {
58 | if (_fConsole.OriginalWrite(task.Message, task.Color, task.ShowTimeTag))
59 | {
60 | // Successfully processed the task
61 | }
62 | }
63 | else
64 | {
65 | // If queue is empty, yield the CPU but avoid context switches when possible
66 | spinWait.SpinOnce();
67 | await Task.Yield();
68 | }
69 | }
70 | }
71 | catch (OperationCanceledException)
72 | {
73 | // Task was cancelled
74 | }
75 | catch (Exception ex)
76 | {
77 | // Log or handle other exceptions
78 | // Consider logging ex.Message or using a logging framework
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.nuget.org/packages/WindowsForms.Console)
2 | [](https://www.nuget.org/packages/WindowsForms.Console)
3 | [](https://ci.appveyor.com/project/msx752/windowsform-console)
4 |
5 | # WindowsForms.Console
6 | Component of WindowsForm
7 |
8 | # Usage
9 | - import nuget package to the project
10 |
11 | ```
12 | Install-Package WindowsForms.Console
13 | ```
14 | - add 'FConsole' component to FormControl ([you can see how to](https://stackoverflow.com/questions/2101171/how-to-add-user-control-in-the-toolbox-for-c-net-for-winforms-by-importing-the))
15 |
16 | - look at sample project [(for more example)](https://github.com/msx752/WindowsForms.Console/tree/master/SampleProject/SampleFormApplicationCore)
17 |
18 | ## Example Usage
19 |
20 | All examples assume you have added the FConsole control to your form (named `fconsole1`). Both direct usage and extension methods are shown. For input, async/await is recommended.
21 |
22 | ```csharp
23 | // Write a line to the console
24 | fconsole1.WriteLine("Hello, World!");
25 | this.WriteLine("Hello, World!"); // Extension method (inside a Form)
26 |
27 | // Write a line with a specific color
28 | fconsole1.WriteLine("Success!", Color.Green);
29 | this.WriteLine("Success!", Color.Green); // Extension method
30 |
31 | // Write text without a newline
32 | fconsole1.Write("Processing...");
33 | this.Write("Processing..."); // Extension method
34 |
35 | // Write colored text without a newline
36 | fconsole1.Write("Warning!", Color.Orange);
37 | this.Write("Warning!", Color.Orange); // Extension method
38 |
39 | // Read a line from the console (asynchronous)
40 | string input = await fconsole1.ReadLine();
41 | string input2 = await this.ReadLine(); // Extension method
42 |
43 | // Read a single key from the console (asynchronous)
44 | char key = await fconsole1.ReadKey();
45 | char key2 = await this.ReadKey(); // Extension method
46 | ```
47 |
48 | > **Note:** `ReadLine` and `ReadKey` are asynchronous and should be awaited inside an async method for best UI responsiveness. Synchronous blocking is possible but not recommended on the UI thread.
49 |
50 | 
51 |
52 | # Supported Platforms
53 | [moved to security.md](https://github.com/msx752/WindowsForms.Console/blob/master/SECURITY.md)
54 |
55 | # Dependencies
56 | - System.Windows.Form
57 | - System
58 | # FrameworkReferences for the .NetCore and upper
59 | - Microsoft.WindowsDesktop.App.WindowsForm
60 |
61 | # Example Project
62 | - component is used in [MSniper Project](https://github.com/msx752/MSniper)
63 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/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 SampleFormApplication.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", "17.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("SampleFormApplication.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 |
--------------------------------------------------------------------------------
/WindowsForms.Console.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29418.71
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsForms.Console", "src\WindowsForms.Console\WindowsForms.Console.csproj", "{6298AB3A-B82C-4148-ADAF-ADE5F7B7A663}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D8D8CE0A-3704-47DB-95C4-19AD19D48D1D}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleProject", "SampleProject", "{8629138E-53EB-4727-945E-5023D3A3D3D2}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleFormApplication", "SampleProject\SampleFormApplication\SampleFormApplication.csproj", "{D6755EDE-9F23-4986-9AD5-A817FBC0A556}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC85158C-7E14-44E2-BB49-CCB70B7DAFFE}"
15 | ProjectSection(SolutionItems) = preProject
16 | .gitattributes = .gitattributes
17 | README.md = README.md
18 | EndProjectSection
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleFormApplicationCore", "SampleProject\SampleFormApplicationCore\SampleFormApplicationCore.csproj", "{A3A2EB2F-5460-4F3D-BAAB-09DCF283FDF5}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Release|Any CPU = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {6298AB3A-B82C-4148-ADAF-ADE5F7B7A663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {6298AB3A-B82C-4148-ADAF-ADE5F7B7A663}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {6298AB3A-B82C-4148-ADAF-ADE5F7B7A663}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {6298AB3A-B82C-4148-ADAF-ADE5F7B7A663}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {D6755EDE-9F23-4986-9AD5-A817FBC0A556}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {D6755EDE-9F23-4986-9AD5-A817FBC0A556}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {D6755EDE-9F23-4986-9AD5-A817FBC0A556}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {D6755EDE-9F23-4986-9AD5-A817FBC0A556}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {A3A2EB2F-5460-4F3D-BAAB-09DCF283FDF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {A3A2EB2F-5460-4F3D-BAAB-09DCF283FDF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {A3A2EB2F-5460-4F3D-BAAB-09DCF283FDF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {A3A2EB2F-5460-4F3D-BAAB-09DCF283FDF5}.Release|Any CPU.Build.0 = Release|Any CPU
40 | EndGlobalSection
41 | GlobalSection(SolutionProperties) = preSolution
42 | HideSolutionNode = FALSE
43 | EndGlobalSection
44 | GlobalSection(NestedProjects) = preSolution
45 | {6298AB3A-B82C-4148-ADAF-ADE5F7B7A663} = {D8D8CE0A-3704-47DB-95C4-19AD19D48D1D}
46 | {D6755EDE-9F23-4986-9AD5-A817FBC0A556} = {8629138E-53EB-4727-945E-5023D3A3D3D2}
47 | {A3A2EB2F-5460-4F3D-BAAB-09DCF283FDF5} = {8629138E-53EB-4727-945E-5023D3A3D3D2}
48 | EndGlobalSection
49 | GlobalSection(ExtensibilityGlobals) = postSolution
50 | SolutionGuid = {363D53B2-6B7C-4590-BC88-555C0FBE0162}
51 | EndGlobalSection
52 | EndGlobal
53 |
--------------------------------------------------------------------------------
/src/WindowsForms.Console/WindowsForms.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net48;netcoreapp3.0;netcoreapp3.1;net5.0-windows;net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows
6 | true
7 | true
8 | 12
9 |
10 |
11 |
12 | On
13 |
14 |
15 |
16 | x64
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | <_Parameter1>$(AssemblyName).Tests
28 |
29 |
30 |
31 |
32 | 3.0.4
33 | 3.0.4
34 | True
35 | WindowsForms.Console
36 | WindowsForms.Console
37 | Component of WindowsForms, ConsoleGUI is added to WindowsForms Application. Now supports .NET 9.0 and previous versions.
38 | WindowsForms.Console component for WinForms applications. Supports .NET Framework 4.8, .NET Core 3.0/3.1, .NET 5.0-9.0 (Windows).
39 | Mustafa Salih ASLIM;
40 | https://github.com/msx752/WindowsForms.Console
41 | README.md
42 | https://github.com/msx752/WindowsForms.Console
43 | git
44 | True
45 | False
46 | wfc.png
47 | FConsole WindowsForms.Console WinConsole Console Component WinFormConsole net core
48 | LICENSE
49 | False
50 | True
51 | snupkg
52 | embedded
53 | True
54 | True
55 | True
56 | Copyright 2017
57 |
58 | True
59 |
60 |
61 |
62 |
63 | True
64 | \
65 |
66 |
67 | True
68 | \
69 |
70 |
71 | True
72 | \
73 |
74 |
75 |
76 |
77 |
78 | all
79 | runtime; build; native; contentfiles; analyzers; buildtransitive
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '{build}'
2 | pull_requests:
3 | do_not_increment_build_number: true
4 | branches:
5 | only:
6 | - master
7 | skip_tags: true
8 | image: Visual Studio 2019
9 | clone_depth: 5
10 | assembly_info:
11 | patch: true
12 | file: '**\AssemblyInfo.*'
13 | assembly_version: $(APPVEYOR_BUILD_VERSION)
14 | assembly_file_version: $(APPVEYOR_BUILD_VERSION)
15 | assembly_informational_version: $(APPVEYOR_BUILD_VERSION)
16 | install:
17 | - ps: >-
18 | if($($env:APPVEYOR))
19 |
20 | {
21 |
22 | $firstCommit = $(git log --pretty=format:'%H' -n -1).Length;
23 |
24 | $firstCommitHash = $(git log --pretty=format:'%H' -n -1)[$firstCommit-1];
25 |
26 | Write-Host "First Commit Hash:" $firstCommitHash;
27 |
28 | $firstCommitDate = (git show -s --format=%ci $firstCommitHash);
29 |
30 | Write-Host "First Commit Date:" $firstCommitDate;
31 |
32 | [datetime]$FCDateTime = $firstCommitDate;
33 |
34 | #Write-Host $FCDateTime
35 |
36 | $FCyear = $FCDateTime.ToString("y.").TrimEnd('.');
37 |
38 | #Write-Host $FCyear
39 |
40 | $timeZone0 = [TimeZoneInfo]::ConvertTimeBySystemTimeZoneId([DateTime]::UtcNow, "Turkey Standard Time");
41 |
42 | $timeZone = $timeZone0;
43 |
44 | Write-Host "Current System Time:" $timeZone;
45 |
46 | [datetime]$DateTime = $timeZone;
47 |
48 | $year = $DateTime.ToString("y.").TrimEnd('.');
49 |
50 | $month = $DateTime.ToString("M.").TrimEnd('.');
51 |
52 | $day = $DateTime.ToString("d.").TrimEnd('.');
53 |
54 | $hourMinute = $DateTime.ToString(".HHmm").TrimStart('.').TrimStart('0');
55 |
56 | $buildYear = (($year - $FCyear) + 1);
57 |
58 | #$buildTime = $DateTime.ToString("M.d.hmm");
59 |
60 | $newBuildNumber = "$buildYear.$month.$day.$hourMinute";
61 |
62 | Write-Host "New Nuget Package Version:" $newBuildNumber
63 |
64 | Update-AppveyorBuild -Version $newBuildNumber;
65 |
66 | }
67 |
68 | else
69 |
70 | {
71 | Write-Host "AppVeyor was not detected";
72 | }
73 | build_script:
74 | - ps: >-
75 | if($($env:APPVEYOR))
76 | {
77 |
78 | $SVersion = $($env:APPVEYOR_BUILD_VERSION);
79 | Write-Host "$($env:APPVEYOR_PROJECT_NAME) Version:$SVersion";
80 |
81 | $myapp = "$($env:APPVEYOR_PROJECT_NAME)";
82 |
83 | nuget restore $myapp.sln;
84 |
85 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.5 /p:OutputPath="bin\v4.5";
86 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.5.1 /p:OutputPath="bin\v4.5.1";
87 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.5.2 /p:OutputPath="bin\v4.5.2";
88 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.6 /p:OutputPath="bin\v4.6";
89 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.6.1 /p:OutputPath="bin\v4.6.1";
90 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.6.2 /p:OutputPath="bin\v4.6.2";
91 | #& msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=v4.7 /p:OutputPath="bin\v4.7";
92 | & msbuild $myapp.sln /property:Configuration=Release /p:TargetFrameworkVersion=netcoreapp3.0 /p:OutputPath="bin\netcoreapp3.0";
93 |
94 |
95 | dir -Directory;
96 |
97 | Write-Host $myapp;
98 |
99 |
100 | nuget pack "$myapp.nuspec" -version $newBuildNumber;
101 |
102 | Push-AppveyorArtifact "$($env:APPVEYOR_BUILD_FOLDER)\$myapp.$SVersion.nupkg" -FileName "$myapp.$SVersion.nupkg" -DeploymentName "$myapp";
103 | }
104 | else
105 | {
106 | Write-Host "AppVeyor was not detected";
107 | }
108 | test: off
109 | hosts:
110 | api.nuget.org: 93.184.221.200
111 | skip_commits:
112 | files:
113 | - '**/*.md'
114 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/SampleFormApplication.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {D6755EDE-9F23-4986-9AD5-A817FBC0A556}
8 | WinExe
9 | SampleFormApplication
10 | SampleFormApplication
11 | v4.8
12 | 512
13 | true
14 |
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 | x64
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | Form
52 |
53 |
54 | Form1.cs
55 |
56 |
57 |
58 |
59 | Form1.cs
60 |
61 |
62 | ResXFileCodeGenerator
63 | Resources.Designer.cs
64 | Designer
65 |
66 |
67 | True
68 | Resources.resx
69 | True
70 |
71 |
72 | SettingsSingleFileGenerator
73 | Settings.Designer.cs
74 |
75 |
76 | True
77 | Settings.settings
78 | True
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | {6298ab3a-b82c-4148-adaf-ade5f7b7a663}
90 | WindowsForms.Console
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/WindowsForms.Console.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WindowsForms.Console
5 | 2.0.0.10
6 | WindowsForms Console Implementation
7 | Mustafa Salih ASLIM
8 | Mustafa Salih ASLIM
9 | https://github.com/msx752/WindowsForms.Console/blob/master/LICENSE
10 | https://github.com/msx752/WindowsForms.Console
11 | https://github.com/msx752/WindowsForms.Console/blob/master/wfc.png?raw=true
12 | false
13 | Component of WindowsForms, ConsoleGUI is added to WindowsForms Application. Now supports .NET 9.0 and previous versions.
14 | Added support for .NET 9.0 (Windows) alongside previous versions.
15 | Copyright 2017
16 | FConsole WindowsForms.Console WinConsole Console Component WinFormConsole
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/WindowsForms.Console/Extensions/FConsoleExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsForms.Console.Extensions;
2 |
3 | ///
4 | /// Provides extension methods for easy access to the properties and methods of FConsole.
5 | ///
6 | public static class FConsoleExtensions
7 | {
8 | ///
9 | /// Extension method to read a single key from the console within the specified Form.
10 | ///
11 | /// The Form containing the FConsole control.
12 | /// The color of the text to be displayed when prompting for a key.
13 | /// A token to cancel the operation.
14 | /// A task representing the key read from the console.
15 | public static Task ReadKey(this Form f, Color? color = null, CancellationToken cancellationToken = default)
16 | {
17 | FConsole console = CheckFConsole(f);
18 | return console.ReadKey(color, cancellationToken);
19 | }
20 |
21 | ///
22 | /// Extension method to read a line of text from the console within the specified Form.
23 | ///
24 | /// The Form containing the FConsole control.
25 | /// A token to cancel the operation.
26 | /// A task representing the line read from the console.
27 | public static Task ReadLine(this Form f, CancellationToken cancellationToken = default)
28 | {
29 | FConsole console = CheckFConsole(f);
30 | return console.ReadLine(cancellationToken);
31 | }
32 |
33 | ///
34 | /// Extension method to write a message to the console within the specified Form.
35 | ///
36 | /// The Form containing the FConsole control.
37 | /// The message to be written to the console.
38 | /// The color of the text to be displayed.
39 | public static void Write(this Form f, string message = null, Color? color = null)
40 | {
41 | FConsole console = CheckFConsole(f);
42 | message ??= string.Empty;
43 | console.Write(message, color, false);
44 | }
45 |
46 | ///
47 | /// Extension method to write a message followed by a newline to the console within the specified Form.
48 | ///
49 | /// The Form containing the FConsole control.
50 | /// The message to be written to the console.
51 | /// The color of the text to be displayed.
52 | /// Indicates whether to show a timestamp with the message.
53 | public static void WriteLine(this Form f, string message = null, Color? color = null, bool showTimeTag = false)
54 | {
55 | FConsole console = CheckFConsole(f);
56 | message ??= string.Empty;
57 | console.WriteLine(message, color, showTimeTag);
58 | }
59 |
60 | ///
61 | /// Checks and retrieves the FConsole control from the specified Form.
62 | ///
63 | /// The Form to search for an FConsole control.
64 | /// The FConsole control found in the Form.
65 | /// Thrown if no FConsole control is found in the Form.
66 | /// Thrown if more than one FConsole control is found in the Form.
67 | private static FConsole CheckFConsole(Form f)
68 | {
69 | var fconsoles = FindControlByType(f, true);
70 | var count = fconsoles.Count();
71 |
72 | if (count == 0)
73 | throw new Exception("This WinForm does not have any FConsole component.");
74 | else if (count > 1)
75 | throw new NotSupportedException("Multiple FConsole components detected in the Form. Only one FConsole component is supported per Form.");
76 |
77 | return fconsoles.First();
78 | }
79 |
80 | ///
81 | /// Finds all controls of a specific type within the specified Form.
82 | ///
83 | /// The type of controls to search for.
84 | /// The main control to search within (e.g., the Form).
85 | /// Indicates whether to search within child controls as well.
86 | /// An enumerable collection of controls of the specified type.
87 | private static List FindControlByType(Control mainControl, bool getAllChild = false) where T : Control
88 | {
89 | var result = new List();
90 |
91 | var stack = new Stack();
92 | stack.Push(mainControl);
93 |
94 | while (stack.Count > 0)
95 | {
96 | var control = stack.Pop();
97 | if (control is T t)
98 | {
99 | result.Add(t);
100 | }
101 |
102 | if (getAllChild)
103 | {
104 | foreach (Control child in control.Controls)
105 | {
106 | stack.Push(child);
107 | }
108 | }
109 | }
110 |
111 | return result;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/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 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Form1.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 | using WindowsForms.Console.Extensions;
7 |
8 | namespace SampleFormApplication
9 | {
10 | public partial class Form1 : Form
11 | {
12 | public Form1()
13 | {
14 | InitializeComponent();
15 | }
16 |
17 | private void button1_Click(object sender, EventArgs e)
18 | {
19 | this.Write("this is an example line text!.",
20 | Color.FromName(comboBox1.Items[comboBox1.SelectedIndex].ToString()));//used SelectedIndex for preventing a crash
21 | }
22 |
23 | private void Form1_Load(object sender, EventArgs e)
24 | {
25 | comboBox1.Items.Add(nameof(Color.Aqua));
26 | comboBox1.Items.Add(nameof(Color.Red));
27 | comboBox1.Items.Add(nameof(Color.Blue));
28 | comboBox1.Items.Add(nameof(Color.White));
29 | comboBox1.Items.Add(nameof(Color.Yellow));
30 | comboBox1.Items.Add(nameof(Color.LightBlue));
31 | comboBox1.Items.Add(nameof(Color.DarkSeaGreen));
32 | comboBox1.SelectedIndex = 3;
33 |
34 | fconsole1.Text = "";
35 |
36 | cmbTimeTag.Items.Add("Hide Time Tag");
37 | cmbTimeTag.Items.Add("Show Time Tag");
38 | cmbTimeTag.SelectedIndex = 0;
39 | }
40 |
41 | private void button4_Click(object sender, EventArgs e)
42 | {
43 | fconsole1.ReadOnly = !fconsole1.ReadOnly;
44 | if (fconsole1.ReadOnly)
45 | {
46 | button4.Text = "ReadOnly (ON)";
47 | }
48 | else
49 | {
50 | button4.Text = "ReadOnly (OFF)";
51 |
52 | MessageBox.Show("ReadOnly=False is not recommended");
53 | //MessageBox.Show("some of features may not work with readonly mode such as readline and read key, but now it is okey until you see any error :)");
54 | }
55 | }
56 |
57 | private void button2_Click(object sender, EventArgs e)
58 | {
59 | this.WriteLine("this is an example line text!.",
60 | Color.FromName(comboBox1.Items[comboBox1.SelectedIndex].ToString()), cmbTimeTag.SelectedIndex == 1);////used SelectedIndex for preventing a crash
61 | }
62 |
63 | private void button3_Click(object sender, EventArgs e)
64 | {
65 | this.WriteLine(" http://github.com/msx752/WindowsForms.Console",
66 | Color.FromName(comboBox1.Items[comboBox1.SelectedIndex].ToString()), cmbTimeTag.SelectedIndex == 1);//used SelectedIndex for preventing a crash)
67 | }
68 |
69 | private void button5_Click(object sender, EventArgs e)
70 | {
71 | fconsole1.ForeColor = Color.FromName(comboBox1.Items[comboBox1.SelectedIndex].ToString());
72 | }
73 |
74 | private async void button6_Click(object sender, EventArgs e)
75 | {
76 | var line = await this.ReadLine();
77 | MessageBox.Show($"Value of ReadLine is '{line}'");
78 | }
79 |
80 | private async void button7_Click(object sender, EventArgs e)
81 | {
82 | var key = await this.ReadKey();
83 | MessageBox.Show($"Value of ReadKey is '{key}'");
84 | }
85 |
86 | private void btnAsyncWrite_Click(object sender, EventArgs e)
87 | {
88 | fconsole1.Clear();
89 | int counter = 1;
90 | this.WriteLine($"[Minimum Number:\t1\t]", Color.FromName(comboBox1.Items[0].ToString()), cmbTimeTag.SelectedIndex == 1);
91 | List tlist = new List();
92 | for (int i = 0; i < 7; i++)
93 | {
94 | int current = i;
95 | int count = counter;
96 | counter++;
97 | tlist.Add(Task.Run(() =>
98 | {
99 | this.WriteLine($"\t[Number:\t{count}\t]", Color.FromName(comboBox1.Items[current].ToString()), cmbTimeTag.SelectedIndex == 1);////used SelectedIndex for preventing a crash
100 | }));
101 | }
102 | for (int i = 0; i < 7; i++)
103 | {
104 | int current = i;
105 | int count = counter;
106 | counter++;
107 | tlist.Add(Task.Run(() =>
108 | {
109 | this.WriteLine($"\t[Number:\t{count}\t]", Color.FromName(comboBox1.Items[current].ToString()), cmbTimeTag.SelectedIndex == 1);////used SelectedIndex for preventing a crash
110 | }));
111 | }
112 | Task.WaitAll(tlist.ToArray());// if you dont do this, writeline squence may be unstable
113 | this.WriteLine($"[Maximum Number:\t14\t]", Color.FromName(comboBox1.Items[0].ToString()), cmbTimeTag.SelectedIndex == 1);
114 | }
115 |
116 | private void btnAsyncWrite_Click_1(object sender, EventArgs e)
117 | {
118 | fconsole1.Clear();
119 | List tlist = new List();
120 | this.WriteLine($"[Minimum Number:\t1\t]", Color.FromName(comboBox1.Items[0].ToString()), cmbTimeTag.SelectedIndex == 1);
121 | for (int i = 0; i < 7; i++)
122 | {
123 | int current = i;
124 | tlist.Add(Task.Run(() =>
125 | {
126 | this.Write($"{current + 1}\t", Color.FromName(comboBox1.Items[current].ToString()));////used SelectedIndex for preventing a crash
127 | }));
128 | }
129 | Task.WaitAll(tlist.ToArray());// if you dont do this, writeline squence may be unstable
130 | this.WriteLine();
131 | this.WriteLine($"[Maximum Number:\t7\t]", Color.FromName(comboBox1.Items[0].ToString()), cmbTimeTag.SelectedIndex == 1);
132 | }
133 |
134 | private void btnClearAll_Click(object sender, EventArgs e)
135 | {
136 | fconsole1.Clear();
137 | }
138 |
139 | private async void button8_Click(object sender, EventArgs e)
140 | {
141 | var key = await this.ReadKey(Color.FromName(comboBox1.Items[comboBox1.SelectedIndex].ToString()));
142 | MessageBox.Show($"Value of ReadKey is '{key}'");
143 | }
144 |
145 | private void button8_Click_1(object sender, EventArgs e)
146 | {
147 | Action action = (taskNumber, index) => this.WriteLine($"TaskNumber:\t{taskNumber}\tIndex:{index}", Color.FromName(comboBox1.Items[comboBox1.SelectedIndex].ToString()), true);
148 | List taskList = new List();
149 | this.WriteLine("un-ordered TaskNumber and indexes have been produced but note that there is no slip on TimeTagging", Color.Red, true);
150 | for (int t = 1; t <= 5; t++)
151 | {
152 | int tn = t;
153 | taskList.Add(Task.Run(() =>
154 | {
155 | for (int n = 1; n <= 50; n++)
156 | {
157 | int nn = n;
158 | taskList.Add(Task.Run(() => action(tn, nn)));
159 | }
160 | }));
161 | }
162 | Task.WaitAll(taskList.ToArray());
163 | }
164 | }
165 | }
--------------------------------------------------------------------------------
/SampleProject/SampleFormApplication/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 |
2 | using WindowsForms.Console.Enums;
3 |
4 | namespace SampleFormApplication
5 | {
6 | partial class Form1
7 | {
8 | ///
9 | /// Required designer variable.
10 | ///
11 | private System.ComponentModel.IContainer components = null;
12 |
13 | ///
14 | /// Clean up any resources being used.
15 | ///
16 | /// true if managed resources should be disposed; otherwise, false.
17 | protected override void Dispose(bool disposing)
18 | {
19 | if (disposing && (components != null))
20 | {
21 | components.Dispose();
22 | }
23 | base.Dispose(disposing);
24 | }
25 |
26 | #region Windows Form Designer generated code
27 |
28 | ///
29 | /// Required method for Designer support - do not modify
30 | /// the contents of this method with the code editor.
31 | ///
32 | private void InitializeComponent()
33 | {
34 | this.button1 = new System.Windows.Forms.Button();
35 | this.button2 = new System.Windows.Forms.Button();
36 | this.button3 = new System.Windows.Forms.Button();
37 | this.comboBox1 = new System.Windows.Forms.ComboBox();
38 | this.button4 = new System.Windows.Forms.Button();
39 | this.button5 = new System.Windows.Forms.Button();
40 | this.button6 = new System.Windows.Forms.Button();
41 | this.button7 = new System.Windows.Forms.Button();
42 | this.btnAsyncWriteLine = new System.Windows.Forms.Button();
43 | this.btnAsyncWrite = new System.Windows.Forms.Button();
44 | this.btnClearAll = new System.Windows.Forms.Button();
45 | this.fconsole1 = new WindowsForms.Console.FConsole();
46 | this.cmbTimeTag = new System.Windows.Forms.ComboBox();
47 | this.btnReadKeyColored = new System.Windows.Forms.Button();
48 | this.button8 = new System.Windows.Forms.Button();
49 | this.SuspendLayout();
50 | //
51 | // button1
52 | //
53 | this.button1.Location = new System.Drawing.Point(548, 46);
54 | this.button1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
55 | this.button1.Name = "button1";
56 | this.button1.Size = new System.Drawing.Size(112, 35);
57 | this.button1.TabIndex = 1;
58 | this.button1.Text = "Write";
59 | this.button1.UseVisualStyleBackColor = true;
60 | this.button1.Click += new System.EventHandler(this.button1_Click);
61 | //
62 | // button2
63 | //
64 | this.button2.Location = new System.Drawing.Point(238, 46);
65 | this.button2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
66 | this.button2.Name = "button2";
67 | this.button2.Size = new System.Drawing.Size(152, 35);
68 | this.button2.TabIndex = 1;
69 | this.button2.Text = "WriteLine";
70 | this.button2.UseVisualStyleBackColor = true;
71 | this.button2.Click += new System.EventHandler(this.button2_Click);
72 | //
73 | // button3
74 | //
75 | this.button3.Location = new System.Drawing.Point(912, 43);
76 | this.button3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
77 | this.button3.Name = "button3";
78 | this.button3.Size = new System.Drawing.Size(112, 35);
79 | this.button3.TabIndex = 1;
80 | this.button3.Text = "WriteLink";
81 | this.button3.UseVisualStyleBackColor = true;
82 | this.button3.Click += new System.EventHandler(this.button3_Click);
83 | //
84 | // comboBox1
85 | //
86 | this.comboBox1.FormattingEnabled = true;
87 | this.comboBox1.Location = new System.Drawing.Point(18, 8);
88 | this.comboBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
89 | this.comboBox1.Name = "comboBox1";
90 | this.comboBox1.Size = new System.Drawing.Size(210, 28);
91 | this.comboBox1.TabIndex = 2;
92 | //
93 | // button4
94 | //
95 | this.button4.Location = new System.Drawing.Point(399, 5);
96 | this.button4.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
97 | this.button4.Name = "button4";
98 | this.button4.Size = new System.Drawing.Size(140, 35);
99 | this.button4.TabIndex = 1;
100 | this.button4.Text = "ReadOnly (ON)";
101 | this.button4.UseVisualStyleBackColor = true;
102 | this.button4.Click += new System.EventHandler(this.button4_Click);
103 | //
104 | // button5
105 | //
106 | this.button5.Location = new System.Drawing.Point(238, 5);
107 | this.button5.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
108 | this.button5.Name = "button5";
109 | this.button5.Size = new System.Drawing.Size(152, 35);
110 | this.button5.TabIndex = 4;
111 | this.button5.Text = "Change All Color";
112 | this.button5.UseVisualStyleBackColor = true;
113 | this.button5.Click += new System.EventHandler(this.button5_Click);
114 | //
115 | // button6
116 | //
117 | this.button6.Location = new System.Drawing.Point(912, 5);
118 | this.button6.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
119 | this.button6.Name = "button6";
120 | this.button6.Size = new System.Drawing.Size(112, 35);
121 | this.button6.TabIndex = 5;
122 | this.button6.Text = "ReadLine";
123 | this.button6.UseVisualStyleBackColor = true;
124 | this.button6.Click += new System.EventHandler(this.button6_Click);
125 | //
126 | // button7
127 | //
128 | this.button7.Location = new System.Drawing.Point(548, 5);
129 | this.button7.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
130 | this.button7.Name = "button7";
131 | this.button7.Size = new System.Drawing.Size(112, 35);
132 | this.button7.TabIndex = 5;
133 | this.button7.Text = "ReadKey";
134 | this.button7.UseVisualStyleBackColor = true;
135 | this.button7.Click += new System.EventHandler(this.button7_Click);
136 | //
137 | // btnAsyncWriteLine
138 | //
139 | this.btnAsyncWriteLine.ForeColor = System.Drawing.Color.Navy;
140 | this.btnAsyncWriteLine.Location = new System.Drawing.Point(399, 46);
141 | this.btnAsyncWriteLine.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
142 | this.btnAsyncWriteLine.Name = "btnAsyncWriteLine";
143 | this.btnAsyncWriteLine.Size = new System.Drawing.Size(140, 35);
144 | this.btnAsyncWriteLine.TabIndex = 1;
145 | this.btnAsyncWriteLine.Text = "Async WriteLine";
146 | this.btnAsyncWriteLine.UseVisualStyleBackColor = true;
147 | this.btnAsyncWriteLine.Click += new System.EventHandler(this.btnAsyncWrite_Click);
148 | //
149 | // btnAsyncWrite
150 | //
151 | this.btnAsyncWrite.ForeColor = System.Drawing.Color.Navy;
152 | this.btnAsyncWrite.Location = new System.Drawing.Point(669, 46);
153 | this.btnAsyncWrite.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
154 | this.btnAsyncWrite.Name = "btnAsyncWrite";
155 | this.btnAsyncWrite.Size = new System.Drawing.Size(112, 35);
156 | this.btnAsyncWrite.TabIndex = 1;
157 | this.btnAsyncWrite.Text = "Async Write";
158 | this.btnAsyncWrite.UseVisualStyleBackColor = true;
159 | this.btnAsyncWrite.Click += new System.EventHandler(this.btnAsyncWrite_Click_1);
160 | //
161 | // btnClearAll
162 | //
163 | this.btnClearAll.Location = new System.Drawing.Point(790, 45);
164 | this.btnClearAll.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
165 | this.btnClearAll.Name = "btnClearAll";
166 | this.btnClearAll.Size = new System.Drawing.Size(112, 35);
167 | this.btnClearAll.TabIndex = 1;
168 | this.btnClearAll.Text = "Clear All";
169 | this.btnClearAll.UseVisualStyleBackColor = true;
170 | this.btnClearAll.Click += new System.EventHandler(this.btnClearAll_Click);
171 | //
172 | // fconsole1
173 | //
174 | this.fconsole1.Arguments = new string[0];
175 | this.fconsole1.AutoScrollToEndLine = true;
176 | this.fconsole1.BackColor = System.Drawing.Color.Black;
177 | this.fconsole1.BorderStyle = System.Windows.Forms.BorderStyle.None;
178 | this.fconsole1.Font = new System.Drawing.Font("Consolas", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(162)));
179 | this.fconsole1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(223)))), ((int)(((byte)(216)))), ((int)(((byte)(194)))));
180 | this.fconsole1.HyperlinkColor = System.Drawing.Color.Empty;
181 | this.fconsole1.Location = new System.Drawing.Point(0, 82);
182 | this.fconsole1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
183 | this.fconsole1.MaxLength = 32767;
184 | this.fconsole1.MinimumSize = new System.Drawing.Size(705, 308);
185 | this.fconsole1.Name = "fconsole1";
186 | this.fconsole1.ReadOnly = true;
187 | this.fconsole1.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
188 | this.fconsole1.SecureReadLine = true;
189 | this.fconsole1.Size = new System.Drawing.Size(1299, 471);
190 | this.fconsole1.State = WindowsForms.Console.Enums.ConsoleState.Writing;
191 | this.fconsole1.TabIndex = 3;
192 | this.fconsole1.Text = "WindowsForm Console";
193 | this.fconsole1.Title = "Form1";
194 | //
195 | // cmbTimeTag
196 | //
197 | this.cmbTimeTag.FormattingEnabled = true;
198 | this.cmbTimeTag.Location = new System.Drawing.Point(18, 46);
199 | this.cmbTimeTag.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
200 | this.cmbTimeTag.Name = "cmbTimeTag";
201 | this.cmbTimeTag.Size = new System.Drawing.Size(210, 28);
202 | this.cmbTimeTag.TabIndex = 2;
203 | //
204 | // btnReadKeyColored
205 | //
206 | this.btnReadKeyColored.ForeColor = System.Drawing.Color.Navy;
207 | this.btnReadKeyColored.Location = new System.Drawing.Point(669, 5);
208 | this.btnReadKeyColored.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
209 | this.btnReadKeyColored.Name = "btnReadKeyColored";
210 | this.btnReadKeyColored.Size = new System.Drawing.Size(234, 35);
211 | this.btnReadKeyColored.TabIndex = 5;
212 | this.btnReadKeyColored.Text = "ReadKey Colored";
213 | this.btnReadKeyColored.UseVisualStyleBackColor = true;
214 | this.btnReadKeyColored.Click += new System.EventHandler(this.button8_Click);
215 | //
216 | // button8
217 | //
218 | this.button8.ForeColor = System.Drawing.Color.Navy;
219 | this.button8.Location = new System.Drawing.Point(1067, 7);
220 | this.button8.Name = "button8";
221 | this.button8.Size = new System.Drawing.Size(238, 74);
222 | this.button8.TabIndex = 6;
223 | this.button8.Text = "WriteLine from multi-threads (massive Write call not recommended)";
224 | this.button8.UseVisualStyleBackColor = true;
225 | this.button8.Click += new System.EventHandler(this.button8_Click_1);
226 | //
227 | // Form1
228 | //
229 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
230 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
231 | this.ClientSize = new System.Drawing.Size(1317, 557);
232 | this.Controls.Add(this.button8);
233 | this.Controls.Add(this.btnReadKeyColored);
234 | this.Controls.Add(this.button7);
235 | this.Controls.Add(this.button6);
236 | this.Controls.Add(this.button5);
237 | this.Controls.Add(this.fconsole1);
238 | this.Controls.Add(this.cmbTimeTag);
239 | this.Controls.Add(this.comboBox1);
240 | this.Controls.Add(this.button4);
241 | this.Controls.Add(this.btnClearAll);
242 | this.Controls.Add(this.button3);
243 | this.Controls.Add(this.btnAsyncWriteLine);
244 | this.Controls.Add(this.button2);
245 | this.Controls.Add(this.btnAsyncWrite);
246 | this.Controls.Add(this.button1);
247 | this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
248 | this.Name = "Form1";
249 | this.Text = "Form1";
250 | this.Load += new System.EventHandler(this.Form1_Load);
251 | this.ResumeLayout(false);
252 |
253 | }
254 |
255 | #endregion
256 | private System.Windows.Forms.Button button1;
257 | private System.Windows.Forms.Button button2;
258 | private System.Windows.Forms.Button button3;
259 | private System.Windows.Forms.ComboBox comboBox1;
260 | private WindowsForms.Console.FConsole fconsole1;
261 | private System.Windows.Forms.Button button4;
262 | private System.Windows.Forms.Button button5;
263 | private System.Windows.Forms.Button button6;
264 | private System.Windows.Forms.Button button7;
265 | private System.Windows.Forms.Button btnAsyncWriteLine;
266 | private System.Windows.Forms.Button btnAsyncWrite;
267 | private System.Windows.Forms.Button btnClearAll;
268 | private System.Windows.Forms.ComboBox cmbTimeTag;
269 | private System.Windows.Forms.Button btnReadKeyColored;
270 | private System.Windows.Forms.Button button8;
271 | }
272 | }
273 |
274 |
--------------------------------------------------------------------------------
/src/WindowsForms.Console/FConsole.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace WindowsForms.Console;
4 |
5 | ///
6 | /// Represents a custom console control for Windows Forms.
7 | ///
8 | public class FConsole : RichTextBox
9 | {
10 | private const string _press_any_key_text = " Press Any Key...";
11 | private bool _inputEnable;
12 | private readonly object _lockInputEnable = new();
13 | private readonly object _lockLines = new();
14 | private readonly object _lockPause = new();
15 | private readonly object _lockReadLine = new();
16 | private bool _pause;
17 | private QueueTask _writeLineQueue = null;
18 | private readonly AutoResetEvent _autoResetEventInputEnable = new(false);
19 |
20 | ///
21 | /// Initializes a new instance of the FConsole class.
22 | ///
23 | public FConsole()
24 | {
25 | KeyDown += FConsole_KeyDown;
26 | LinkClicked += FConsole_LinkClicked;
27 | MouseDown += FConsole_MouseDown;
28 | MouseMove += FConsole_MouseMove;
29 | MouseUp += FConsole_MouseUp;
30 | InitializeFConsole();
31 | Form.CheckForIllegalCrossThreadCalls = false; // Important for async access with multi-threading
32 | }
33 |
34 | ///
35 | /// Gets or sets the arguments passed to the console.
36 | ///
37 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
38 | public string[] Arguments { get; set; }
39 |
40 | ///
41 | /// Gets or sets a value indicating whether the console should automatically scroll to the end line.
42 | ///
43 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
44 | public bool AutoScrollToEndLine { get; set; }
45 |
46 | ///
47 | /// Gets the current lines of text in the console.
48 | ///
49 | public string[] CurrentLines
50 | {
51 | get
52 | {
53 | lock (_lockLines)
54 | {
55 | return (string[])Lines.Clone(); // Avoiding external modifications
56 | }
57 | }
58 | }
59 |
60 | ///
61 | /// Gets or sets the color of hyperlinks in the console.
62 | ///
63 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
64 | public Color HyperlinkColor { get; set; }
65 |
66 | ///
67 | /// Gets the last used color in the console.
68 | ///
69 | public Color LastUsedColor { get; private set; }
70 |
71 | ///
72 | /// Gets or sets a value indicating whether the console should be read-only after calling ReadLine.
73 | ///
74 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
75 | public bool SecureReadLine { get; set; }
76 |
77 | ///
78 | /// Gets or sets the current state of the console.
79 | ///
80 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
81 | public ConsoleState State { get; set; }
82 |
83 | ///
84 | /// Gets or sets the title of the console.
85 | ///
86 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
87 | public string Title
88 | {
89 | get => Parent?.Text ?? string.Empty;
90 | set
91 | {
92 | if (Parent != null)
93 | {
94 | Parent.Text = value;
95 | }
96 | }
97 | }
98 |
99 | private char CurrentKey { get; set; }
100 |
101 | private string CurrentLine { get; set; }
102 |
103 | ///
104 | /// Gets or sets a value indicating whether input is enabled.
105 | ///
106 | private bool InputEnable
107 | {
108 | get
109 | {
110 | lock (_lockInputEnable)
111 | return _inputEnable;
112 | }
113 | set
114 | {
115 | lock (_lockInputEnable)
116 | {
117 | _inputEnable = value;
118 |
119 | if (_inputEnable)
120 | _autoResetEventInputEnable.Reset();
121 | else
122 | _autoResetEventInputEnable.Set();
123 | }
124 | }
125 | }
126 |
127 | ///
128 | /// Gets or sets a value indicating whether the console is paused.
129 | ///
130 | private bool Pause
131 | {
132 | get
133 | {
134 | lock (_lockPause)
135 | return _pause;
136 | }
137 | set
138 | {
139 | lock (_lockPause)
140 | _pause = value;
141 | }
142 | }
143 |
144 | private int ReadPoint { get; set; }
145 |
146 | private int RecentCount { get; set; }
147 |
148 | ///
149 | /// Gets or sets the recent list of lines entered in the console.
150 | ///
151 | private List _recentList = new();
152 |
153 | ///
154 | /// Clears the console and resets the recent list.
155 | ///
156 | public new void Clear()
157 | {
158 | base.Clear();
159 | _recentList.Clear();
160 | }
161 |
162 | public new void Dispose()
163 | {
164 | Dispose(true);
165 | GC.SuppressFinalize(this);
166 | }
167 |
168 | ///
169 | /// Disposes the FConsole and its resources.
170 | ///
171 | /// Indicates whether the method was called from the Dispose method.
172 | public new void Dispose(bool disposing)
173 | {
174 | try { _writeLineQueue?.Dispose(); } catch { }
175 |
176 | try { _autoResetEventInputEnable?.Dispose(); } catch { }
177 |
178 | _recentList.Clear();
179 | RecentCount = 0;
180 |
181 | base.Dispose(disposing);
182 | }
183 |
184 | ///
185 | /// Adjusts the RecentCount to ensure it stays within valid bounds.
186 | ///
187 | public void HistoryJumper()
188 | {
189 | #if !NET48
190 | RecentCount = Math.Clamp(RecentCount, 0, _recentList.Count - 1);
191 | #else
192 | if (RecentCount >= _recentList.Count)
193 | RecentCount = _recentList.Count - 1;
194 | else if (RecentCount < 0)
195 | RecentCount = 0;
196 | #endif
197 | }
198 |
199 | ///
200 | /// Initializes the FConsole with default settings.
201 | ///
202 | public void InitializeFConsole()
203 | {
204 | Name = "FConsole";
205 | Text = Name;
206 | Title = Name;
207 | Arguments = Array.Empty();
208 | BackColor = Color.Black;
209 | ForeColor = Color.FromArgb(0xdf, 0xd8, 0xc2);
210 | Dock = DockStyle.None;
211 | BorderStyle = BorderStyle.None;
212 | ReadOnly = true;
213 | Font = new Font("consolas", 10);
214 | MinimumSize = new Size(470, 200);
215 | ScrollBars = RichTextBoxScrollBars.Vertical;
216 | Pause = false;
217 | InputEnable = false;
218 |
219 | if (Parent != null)
220 | {
221 | ((Form)Parent).WindowState = FormWindowState.Normal;
222 | Parent.BackColor = BackColor;
223 | }
224 |
225 | DetectUrls = true;
226 | _recentList = new List();
227 | SecureReadLine = true;
228 | AutoScrollToEndLine = true;
229 | State = ConsoleState.Writing;
230 | LastUsedColor = SelectionColor;
231 | MaxLength = 32767;
232 | _writeLineQueue = new QueueTask(this);
233 | }
234 |
235 | ///
236 | /// Reads a single key from the console.
237 | ///
238 | /// The color of the text to display.
239 | /// A token to cancel the operation.
240 | /// The key pressed by the user.
241 | public Task ReadKey(Color? color = null, CancellationToken cancellationToken = default)
242 | {
243 | if (State == ConsoleState.ReadKey)
244 | InputEnable = false;
245 |
246 | State = ConsoleState.Writing;
247 | Color displayColor = color ?? ForeColor;
248 |
249 | WriteLine(_press_any_key_text, displayColor);
250 |
251 | return Task.Run(() =>
252 | {
253 | lock (_lockReadLine)
254 | {
255 | var recentReadState = ReadOnly;
256 | CurrentKey = ' ';
257 | ReadPoint = Text.Length;
258 | InputEnable = true;
259 | ReadOnly = false;
260 | State = ConsoleState.ReadKey;
261 |
262 | _autoResetEventInputEnable.WaitOne();
263 |
264 | ReadOnly = SecureReadLine ? true : recentReadState;
265 | State = ConsoleState.Writing;
266 |
267 | return CurrentKey;
268 | }
269 | }, cancellationToken);
270 | }
271 |
272 | ///
273 | /// Reads a line of text from the console.
274 | ///
275 | /// A token to cancel the operation.
276 | /// The line of text entered by the user.
277 | public Task ReadLine(CancellationToken cancellationToken = default)
278 | {
279 | return Task.Run(() =>
280 | {
281 | lock (_lockReadLine)
282 | {
283 | var recentReadState = ReadOnly;
284 | CurrentLine = string.Empty;
285 | ReadPoint = TextLength;
286 | InputEnable = true;
287 | ReadOnly = false;
288 | State = ConsoleState.ReadLine;
289 |
290 | _autoResetEventInputEnable.WaitOne();
291 | Cursor = Cursors.IBeam;
292 |
293 | ReadOnly = SecureReadLine ? true : recentReadState;
294 | State = ConsoleState.Writing;
295 |
296 | return CurrentLine;
297 | }
298 | }, cancellationToken);
299 | }
300 |
301 | ///
302 | /// Redoes the last undone entry in the console's history.
303 | ///
304 | /// The redone line.
305 | public string RecentRedo()
306 | {
307 | if (_recentList.Count > 0)
308 | {
309 | RecentCount++;
310 | HistoryJumper();
311 |
312 | return _recentList[RecentCount];
313 | }
314 | else
315 | {
316 | return string.Empty;
317 | }
318 | }
319 |
320 | ///
321 | /// Undoes the last entry in the console's history.
322 | ///
323 | /// The undone line.
324 | public string RecentUndo()
325 | {
326 | if (_recentList.Count > 0)
327 | {
328 | RecentCount--;
329 | HistoryJumper();
330 |
331 | return _recentList[RecentCount];
332 | }
333 | else
334 | {
335 | return string.Empty;
336 | }
337 | }
338 |
339 | ///
340 | /// Selects the last line in the console.
341 | ///
342 | public void SelectLastLine()
343 | {
344 | if (CurrentLines.Length > 0)
345 | {
346 | var line = CurrentLines.Length - 1;
347 | var s1 = GetFirstCharIndexOfCurrentLine();
348 | var s2 = line < CurrentLines.Length - 1 ? GetFirstCharIndexFromLine(line + 1) - 1 : Text.Length;
349 | Select(s1, s2 - s1);
350 | }
351 | }
352 |
353 | ///
354 | /// Sets the text in the console with the specified color.
355 | ///
356 | /// The message to display.
357 | /// The color to display the message in.
358 | public void SetText(string message, Color? color = null)
359 | {
360 | color ??= ForeColor;
361 | LastUsedColor = SelectionColor = color.Value;
362 | SelectedText = message;
363 | }
364 |
365 | ///
366 | /// Updates a specific line in the console with new text and color.
367 | ///
368 | /// The line number to update.
369 | /// The new message to display.
370 | /// The color to display the message in.
371 | public void UpdateLine(int line, string message, Color? color = null)
372 | {
373 | ReadOnly = true;
374 | color ??= ForeColor;
375 | SelectLastLine();
376 | SetText(message, color);
377 | }
378 |
379 | ///
380 | /// Writes a message to the console with optional color and timestamp.
381 | ///
382 | /// The message to display.
383 | /// The color to display the message in.
384 | /// Indicates whether to show a timestamp with the message.
385 | public void Write(string message, Color? color = null, bool showTimeTag = false)
386 | {
387 | _writeLineQueue.Enqueue(new QueueTaskObject(message, color, showTimeTag));
388 | }
389 |
390 | ///
391 | /// Writes a message to the console followed by a newline, with optional color and timestamp.
392 | ///
393 | /// The message to display.
394 | /// The color to display the message in.
395 | /// Indicates whether to show a timestamp with the message.
396 | public void WriteLine(string message, Color? color = null, bool showTimeTag = false)
397 | {
398 | Write(message + Environment.NewLine, color, showTimeTag);
399 | }
400 |
401 | ///
402 | /// Writes the specified message to the console.
403 | ///
404 | /// The message to write.
405 | /// The color to display the message in.
406 | /// Indicates whether to show a timestamp with the message.
407 | /// True if the message was written successfully; otherwise, false.
408 | internal bool OriginalWrite(string message, Color? color = null, bool showTimeTag = false)
409 | {
410 | if ((message.Length == _press_any_key_text.Length && !_press_any_key_text.Equals(message.Replace(Environment.NewLine, string.Empty))) && State == ConsoleState.ReadKey)
411 | return false;
412 |
413 | if (IsDisposed)
414 | return false;
415 |
416 | var recentReadState = ReadOnly;
417 | Select(TextLength, 0);
418 |
419 | if (!message.EndsWith(Environment.NewLine) || State == ConsoleState.ReadLine || State == ConsoleState.ReadKey || message == Environment.NewLine)
420 | showTimeTag = false;
421 |
422 | if (showTimeTag)
423 | message = $"{DateTime.Now}: {message}";
424 |
425 | SetText(message, color);
426 | DeselectAll();
427 |
428 | if (AutoScrollToEndLine)
429 | ScrollToCaret();
430 |
431 | ReadOnly = SecureReadLine ? true : recentReadState;
432 |
433 | return true;
434 | }
435 |
436 | private void FConsole_KeyDown(object sender, KeyEventArgs e)
437 | {
438 | if (State == ConsoleState.Closing)
439 | {
440 | e.SuppressKeyPress = true;
441 | return;
442 | }
443 |
444 | if ((e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) && State == ConsoleState.ReadLine)
445 | {
446 | if (_recentList.Count != 0)
447 | {
448 | var recentText = e.KeyCode == Keys.Up ? RecentUndo() : RecentRedo();
449 | SelectLastLine();
450 | SelectedText = recentText;
451 | }
452 |
453 | e.SuppressKeyPress = true;
454 | return;
455 | }
456 |
457 | Select(TextLength, 0);
458 |
459 | if (e.KeyData == (Keys.Control | Keys.V))
460 | {
461 | MultiplePaste();
462 | e.SuppressKeyPress = true;
463 | }
464 | else if (e.KeyCode == Keys.Enter && InputEnable && State == ConsoleState.ReadLine)
465 | {
466 | Cursor = Cursors.WaitCursor;
467 | ReadOnly = true;
468 | CurrentLine = CurrentLines[CurrentLines.Length - 1];
469 | _recentList.Add(CurrentLine);
470 | WriteLine(string.Empty);
471 | InputEnable = false;
472 | e.SuppressKeyPress = true;
473 | }
474 | else if (InputEnable && State == ConsoleState.ReadKey)
475 | {
476 | ReadOnly = true;
477 | CurrentKey = (char)e.KeyCode;
478 | InputEnable = false;
479 | }
480 | else if (e.KeyCode == Keys.Escape && !InputEnable)
481 | {
482 | Pause = false;
483 | }
484 | else if (e.KeyCode == Keys.Space && !InputEnable)
485 | {
486 | Pause = !Pause;
487 | }
488 | else if (e.KeyCode == Keys.Back && InputEnable && ReadPoint + 1 > TextLength)
489 | {
490 | e.SuppressKeyPress = true;
491 | }
492 | }
493 |
494 | private void FConsole_LinkClicked(object sender, LinkClickedEventArgs e)
495 | {
496 | try
497 | {
498 | var url = e.LinkText;
499 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
500 | {
501 | Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
502 | }
503 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
504 | {
505 | Process.Start("xdg-open", url);
506 | }
507 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
508 | {
509 | Process.Start("open", url);
510 | }
511 | else
512 | {
513 | Process.Start(url);
514 | }
515 | }
516 | catch
517 | {
518 | // Handle or log exceptions
519 | }
520 | }
521 |
522 | private void FConsole_MouseDown(object sender, MouseEventArgs e)
523 | {
524 | if (e.Button == MouseButtons.Right && InputEnable)
525 | {
526 | MultiplePaste();
527 | }
528 | else if (!InputEnable)
529 | {
530 | Select(Text.Length, 0);
531 | }
532 | }
533 |
534 | private void FConsole_MouseMove(object sender, MouseEventArgs e)
535 | {
536 | if (!InputEnable)
537 | {
538 | Select(Text.Length, 0);
539 | }
540 | }
541 |
542 | private void FConsole_MouseUp(object sender, MouseEventArgs e)
543 | {
544 | if (!InputEnable)
545 | {
546 | Select(Text.Length, 0);
547 | }
548 | }
549 |
550 | ///
551 | /// Handles multiple pastes by inserting the clipboard text at the current cursor position.
552 | ///
553 | private void MultiplePaste()
554 | {
555 | ReadOnly = true;
556 | CurrentLine = Clipboard.GetText();
557 | InputEnable = false;
558 | }
559 | }
560 |
--------------------------------------------------------------------------------