From 6e5f593aa81732fe7a7d19d19dc18fa57d026398 Mon Sep 17 00:00:00 2001 From: Gavin Landon Date: Sun, 23 Jul 2023 13:56:30 -0400 Subject: [PATCH] Add project files. --- Demo/App.config | 6 + Demo/Demo.csproj | 110 +++++ Demo/FormDemo.Designer.cs | 183 +++++++ Demo/FormDemo.cs | 223 +++++++++ Demo/FormDemo.resx | 120 +++++ Demo/Program.cs | 22 + Demo/Properties/AssemblyInfo.cs | 36 ++ Demo/Properties/Resources.Designer.cs | 71 +++ Demo/Properties/Resources.resx | 117 +++++ Demo/Properties/Settings.Designer.cs | 30 ++ Demo/Properties/Settings.settings | 7 + Demo/imgs/test.bmp | Bin 0 -> 197934 bytes Demo/imgs/test.gif | Bin 0 -> 3300 bytes Demo/imgs/test.ico | Bin 0 -> 163049 bytes Demo/imgs/test.jpg | Bin 0 -> 2116 bytes Demo/imgs/test.png | Bin 0 -> 1308 bytes Demo/imgs/test.tif | Bin 0 -> 263402 bytes SwitchWinForms.sln | 31 ++ SwitchWinForms/Handler/SWFBoxing.cs | 485 ++++++++++++++++++ SwitchWinForms/Handler/SWFTitlebar.cs | 378 ++++++++++++++ SwitchWinForms/Helper/BoxMethods.cs | 180 +++++++ SwitchWinForms/Models/BoxInfo.cs | 45 ++ SwitchWinForms/Models/ReplaceColor.cs | 31 ++ SwitchWinForms/Models/SWFBoxingOptions.cs | 115 +++++ SwitchWinForms/Models/SWFCursors.cs | 23 + SwitchWinForms/Models/SWFMessageEventArgs.cs | 23 + SwitchWinForms/Models/SWFTitlebarOptions.cs | 266 ++++++++++ SwitchWinForms/Models/SWFUnicodeChars.cs | 80 +++ SwitchWinForms/Models/ShadowingSetup.cs | 14 + SwitchWinForms/Models/TextUtil.cs | 37 ++ SwitchWinForms/Properties/AssemblyInfo.cs | 37 ++ SwitchWinForms/Static/Constants.cs | 97 ++++ SwitchWinForms/Static/Global.cs | 487 +++++++++++++++++++ SwitchWinForms/SwitchWinForms.csproj | 68 +++ 34 files changed, 3322 insertions(+) create mode 100644 Demo/App.config create mode 100644 Demo/Demo.csproj create mode 100644 Demo/FormDemo.Designer.cs create mode 100644 Demo/FormDemo.cs create mode 100644 Demo/FormDemo.resx create mode 100644 Demo/Program.cs create mode 100644 Demo/Properties/AssemblyInfo.cs create mode 100644 Demo/Properties/Resources.Designer.cs create mode 100644 Demo/Properties/Resources.resx create mode 100644 Demo/Properties/Settings.Designer.cs create mode 100644 Demo/Properties/Settings.settings create mode 100644 Demo/imgs/test.bmp create mode 100644 Demo/imgs/test.gif create mode 100644 Demo/imgs/test.ico create mode 100644 Demo/imgs/test.jpg create mode 100644 Demo/imgs/test.png create mode 100644 Demo/imgs/test.tif create mode 100644 SwitchWinForms.sln create mode 100644 SwitchWinForms/Handler/SWFBoxing.cs create mode 100644 SwitchWinForms/Handler/SWFTitlebar.cs create mode 100644 SwitchWinForms/Helper/BoxMethods.cs create mode 100644 SwitchWinForms/Models/BoxInfo.cs create mode 100644 SwitchWinForms/Models/ReplaceColor.cs create mode 100644 SwitchWinForms/Models/SWFBoxingOptions.cs create mode 100644 SwitchWinForms/Models/SWFCursors.cs create mode 100644 SwitchWinForms/Models/SWFMessageEventArgs.cs create mode 100644 SwitchWinForms/Models/SWFTitlebarOptions.cs create mode 100644 SwitchWinForms/Models/SWFUnicodeChars.cs create mode 100644 SwitchWinForms/Models/ShadowingSetup.cs create mode 100644 SwitchWinForms/Models/TextUtil.cs create mode 100644 SwitchWinForms/Properties/AssemblyInfo.cs create mode 100644 SwitchWinForms/Static/Constants.cs create mode 100644 SwitchWinForms/Static/Global.cs create mode 100644 SwitchWinForms/SwitchWinForms.csproj diff --git a/Demo/App.config b/Demo/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/Demo/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Demo/Demo.csproj b/Demo/Demo.csproj new file mode 100644 index 0000000..6e9d440 --- /dev/null +++ b/Demo/Demo.csproj @@ -0,0 +1,110 @@ + + + + + Debug + AnyCPU + {B8318FEF-8FC2-44CF-A490-F4AFB70745E8} + WinExe + Demo + Demo + v4.7.2 + 512 + true + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + Form + + + FormDemo.cs + + + + + FormDemo.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {7c49620c-5f61-4a4e-a6ca-166b18e4daa6} + SwitchWinForms + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + \ No newline at end of file diff --git a/Demo/FormDemo.Designer.cs b/Demo/FormDemo.Designer.cs new file mode 100644 index 0000000..2f8431e --- /dev/null +++ b/Demo/FormDemo.Designer.cs @@ -0,0 +1,183 @@ +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using SwitchWinForms; //Primary object for custom Titlebars, Body, Buttons, etc.. + +namespace Demo +{ + partial class FormDemo + { + /// + /// Required designer variable. + /// + private IContainer components = null; + private readonly Font DefaultButtonFont = new Font("Verdana", 12, FontStyle.Regular, GraphicsUnit.Pixel); + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(770, 488); + this.Name = "Form1"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Form1"; + this.Load += new System.EventHandler(this.Form1_Load); + this.ResumeLayout(false); + + } + #endregion + + #region Added User code + /// + /// In use of SwitchWinForms.dll + /// + private void LoadSwitchWinForms() + { + _tbOptions = new SWFTitlebarOptions() + { + RoundedCorners = SWF_ARC_CORNERS.TopLeft | SWF_ARC_CORNERS.TopRight, + Icon = this.Icon.ToBitmap(), + RoundedRadius = 15, + Height = 30, + Padding = new Padding(2, 2, 2, 2), + BackColor = Color.FromArgb(255, 30, 30, 30),// SystemColors.ActiveCaption, + BorderColor = Color.Black, + BorderSize = 2, + ButtonsEnabled = SWF_TITLE_BUTTON.All, + Close = new SWFTitlebarOptions.ButtonsState() //customizing only the close and defaults for Min and Max/Norm + { + RoundedCorners = SWF_ARC_CORNERS.TopRight, + RoundedRadius = 5, + BorderColor = Color.Transparent, + BorderSize = 1, + BackColor = Color.Wheat, + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Black, + Text = SWFUnicodeChars.CLOSE.ToString(), + Font = DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }, + Minimized = new SWFTitlebarOptions.ButtonsState() //customizing only the close and defaults for Min and Max/Norm + { + RoundedCorners = SWF_ARC_CORNERS.None, + RoundedRadius = 15, + BorderColor = Color.Transparent, + BorderSize = 1, + BackColor = Color.Wheat, + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Black, + Text = SWFUnicodeChars.MIN.ToString(), + Font = DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }, + Maximize = new SWFTitlebarOptions.ButtonsState() //customizing only the close and defaults for Min and Max/Norm + { + RoundedCorners = SWF_ARC_CORNERS.None, + RoundedRadius = 15, + BorderColor = Color.Transparent, + BorderSize = 1, + BackColor = Color.Wheat, + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Black, + Text = SWFUnicodeChars.MAX.ToString(), + Font = DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }, + Normal = new SWFTitlebarOptions.ButtonsState() //customizing only the close and defaults for Min and Max/Norm + { + RoundedCorners = SWF_ARC_CORNERS.None, + RoundedRadius = 15, + BorderColor = Color.Transparent, + BorderSize = 1, + BackColor = Color.Wheat, + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Black, + Text = SWFUnicodeChars.NORM.ToString(), + Font = DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }, + TextSetup = new TextUtil.TextOptions() + { + //BackgroundImage = (Image)SWFBoxing.ImageFromFile(@"imgs\test.png"), + //BackgroundImageLayout = SWF_BG_IMG_LAYOUT.Tile, + //ReplaceImageColor = new List() { new ReplaceColor(Color.FromArgb(241, 81, 27), Color.Transparent, 100) }, + Text = $"Demo v1", + Color = Color.Wheat, + Font = new Font("Verdana", 10, FontStyle.Bold), + HorizonalAlign = StringAlignment.Near, + VerticalAlign = StringAlignment.Center + }, + }; + _frmOptions = new SWFBoxingOptions() + { + Name = "FrmBody", + Type = SWF_BOX_TYPE.FormBody, + TitleBarHeight = _tbOptions.Height, //default is 30, if not set for SWF_BOX_TYPE.FormBody + RoundedCorners = SWF_ARC_CORNERS.BottomLeft | SWF_ARC_CORNERS.BottomRight, + RoundedRadius = 15, + BackColor = Color.FromArgb(255, 62, 62, 66), + BorderColor = Color.Black, + BorderSize = 2, + Location = new Point(0, 0), + Padding = new Padding(2), + Size = new Size(this.Width, this.Height), + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Wheat, + Text = "Gavin", + Font = new Font("Verdana", 24, FontStyle.Bold, GraphicsUnit.Pixel), + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center + }, + }; + + _frmMain = new SWFBoxing(this, _frmOptions); + _titleBar = new SWFTitlebar(this, _tbOptions); + } + + private SWFTitlebarOptions _tbOptions; + private SWFBoxingOptions _frmOptions; + private SWFTitlebar _titleBar; + private SWFBoxing _frmMain; + private SWFBoxing _btn1TileImg; + private SWFBoxing _btn2StretchImg; + private SWFBoxing _lblDisplay; + private SWFBoxing _txtInput; + #endregion + } +} + diff --git a/Demo/FormDemo.cs b/Demo/FormDemo.cs new file mode 100644 index 0000000..4775e99 --- /dev/null +++ b/Demo/FormDemo.cs @@ -0,0 +1,223 @@ +using System; //EventArgs - required by Form Events +using System.Collections.Generic; //List +using System.Drawing; //Color, SystemColors, Font, FrontStyle, GraphicsUnit, StringAlignment, Point, Size +using System.Windows.Forms; //Form +using SwitchWinForms; //Primary object for custom Titlebars, Body, Buttons, etc.. + +namespace Demo +{ + public partial class FormDemo : Form + { + /* + //pre-set unicode characters. + string close_Text_Example1 = SWFUnicodeChars.CLOSE; + //custom unicode characters can be passed here.. + string close_Text_Example2 = new SWFUnicodeChars(10062).ToString(); + */ + public FormDemo() + { + InitializeComponent(); + this.Icon = (Icon)SWFBoxing.ImageFromFile(@"imgs\test.png"); + this.LoadSwitchWinForms(); + } + + private void Form1_Load(object sender, EventArgs e) + { + //example of callback for form resize. Do this on or after load. + //anything prior can cause errors, because the form isn't ready yet. + _frmMain.Resize += Form1_Resize; + + SetupButtons(); + } + private void Form1_Resize(object sender, EventArgs e) + { + ResetSizes(); + } + private void SetupButtons() + { + _btn2StretchImg = new SWFBoxing(this, new SWFBoxingOptions() + { + Name = "BtnStretchedButton", + RoundedCorners = SWF_ARC_CORNERS.TopLeft | SWF_ARC_CORNERS.BottomRight, + RoundedRadius = 80, + BackColor = Color.DarkGray, + BorderColor = Color.Black, + BorderSize = 1, + Location = new Point(100, 100), + Padding = new Padding(2), + Size = new Size(200, 200), + IsAnimatedButton = true, + Type = SWF_BOX_TYPE.Button, + Cursors = new SWFCursors(Cursors.Hand, Cursors.Default), + Shadowing = new ShadowingSetup() + { + Visibilty = SWF_TRANSPARENT_PERCENTAGE.Forty, + Color = Color.Black, + Depth = 20 + }, + TextSetup = new TextUtil.TextOptions() + { + BackgroundImage = (Image)SWFBoxing.ImageFromFile(@"imgs\test.png"), + BackgroundImageLayout = SWF_BG_IMG_LAYOUT.Stretch, + ReplaceImageColor = new List() { + new ReplaceColor(Color.FromArgb(104, 104, 25), Color.Transparent, 100), + new ReplaceColor(Color.White, Color.Transparent, 90) + }, + Color = Color.Black, + Text = "Click Stretched Button", + Font = new Font("Verdana", 10, FontStyle.Bold, GraphicsUnit.Pixel), + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center + }, + }); + + _btn2StretchImg.MouseUp += (sender, e) => + { + lock (_lblDisplay.BoxingOptions.TextSetup) + { + SWFBoxing box = (SWFBoxing)sender; + _lblDisplay.BoxingOptions.TextSetup.Text = $"Name: \"{box.BoxingOptions.Name}\" - Text:\"{box.BoxingOptions.TextSetup.Text}\""; + } + }; + + _btn1TileImg = new SWFBoxing(this, new SWFBoxingOptions() + { + Name = "BtnTiledButton", + RoundedCorners = SWF_ARC_CORNERS.TopRight, + RoundedRadius = 40, + //BackColor = Color.Red, + BackColor = Color.Wheat, + BorderColor = Color.Black, + BorderSize = 1, + Location = new Point(_btn2StretchImg.BoxingOptions.Location.X + _btn2StretchImg.BoxingOptions.Size.Width + 30 + , _btn2StretchImg.BoxingOptions.Location.Y), + Padding = new Padding(2), + Size = new Size(200, 200), + IsAnimatedButton = true, + Cursors = new SWFCursors(Cursors.Hand, Cursors.Default), + Type = SWF_BOX_TYPE.Button, + Shadowing = new ShadowingSetup() + { + Visibilty = SWF_TRANSPARENT_PERCENTAGE.Ten, + Color = Color.Black, + Depth = 5 + }, + TextSetup = new TextUtil.TextOptions() + { + BackgroundImage = (Image)SWFBoxing.ImageFromFile(@"imgs\test.png"), + BackgroundImageLayout = SWF_BG_IMG_LAYOUT.Tile, + ReplaceImageColor = new List() { + new ReplaceColor(Color.FromArgb(251, 188, 9), Color.Transparent, 90), + new ReplaceColor(Color.FromArgb(104, 104, 25), Color.Transparent) }, + Color = Color.Black, + Text = "Click Tiled Button", + Font = new Font("Verdana", 10, FontStyle.Bold, GraphicsUnit.Pixel), + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center + }, + }); + + _btn1TileImg.MouseUp += (sender, e) => + { + lock (_lblDisplay.BoxingOptions.TextSetup) + { + SWFBoxing box = (SWFBoxing)sender; + _lblDisplay.BoxingOptions.TextSetup.Text = $"Name: \"{box.BoxingOptions.Name}\" - Text:\"{box.BoxingOptions.TextSetup.Text}\""; + } + }; + + _lblDisplay = new SWFBoxing(this, new SWFBoxingOptions() + { + Name = "LblDisplay", + BackColor = Color.FromArgb(60, 255, 255, 255), + BorderColor = Color.Black, + BorderSize = 1, + Padding = new Padding(2), + //Location = new Point(0, _frmMain.BoxingOptions.Size.Height), //handled at resize + //Size = new Size(_frmMain.BoxingOptions.Size.Width, 30), //handled at resize + Type = SWF_BOX_TYPE.Label, + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Black, + Text = "Waiting for click", + Font = new Font("Verdana", 10, FontStyle.Bold, GraphicsUnit.Pixel), + HorizonalAlign = StringAlignment.Near, + VerticalAlign = StringAlignment.Center + }, + }); + + _txtInput = new SWFBoxing(this, new SWFBoxingOptions() + { + Name = "TxtInput", + BackColor = Color.White, + BorderColor = Color.Black, + BorderSize = 1, + Padding = new Padding(2), + Cursors = new SWFCursors(Cursors.IBeam, Cursors.Default), + //Location = new Point(30, _lblDisplay.BoxingOptions.Location.Y - 40), //handled at resize + //Size = new Size(_frmMain.BoxingOptions.Size.Width - 60, 30), //handled at resize + Type = SWF_BOX_TYPE.TextBox, + TextSetup = new TextUtil.TextOptions() + { + Color = Color.Black, + Text = "[Email Here]", + ValidInputExpression = @"^((\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)\s*[;]{0,1}\s*)+$", + Font = new Font("Courier New", 12, FontStyle.Bold, GraphicsUnit.Pixel), + HorizonalAlign = StringAlignment.Near, + VerticalAlign = StringAlignment.Center + }, + }); + + _txtInput.Exception += (sender, e) => + { + lock (_txtInput.BoxingOptions.TextSetup) + { + SWFBoxing box = (SWFBoxing)sender; + + string msg = $"{box.BoxingOptions.Name}: {e.Exception.Message}"; + _lblDisplay.BoxingOptions.TextSetup.Text = msg; + MessageBox.Show(msg, "Exception"); + this.Invalidate(); + } + }; + + _txtInput.Success += (sender, e) => + { + lock (_txtInput.BoxingOptions.TextSetup) + { + SWFBoxing box = (SWFBoxing)sender; + + string msg = $"{box.BoxingOptions.Name}: {e.Message}"; + _lblDisplay.BoxingOptions.TextSetup.Text = msg; + this.Invalidate(); + } + }; + + ResetSizes(); + } + private void ResetSizes() + { + Size reSize = new Size(this.ClientSize.Width, this.ClientSize.Height - _tbOptions.Height); + + int w = (int)((double)reSize.Width * .3); + int h = (int)((double)reSize.Height * .3); + _btn1TileImg.BoxingOptions.Size = new Size(w, h); + + w = (int)((double)reSize.Width); + h = (int)((double)reSize.Height); + + int brd = _lblDisplay.BoxingOptions.BorderSize + 5; + _lblDisplay.BoxingOptions.Location = new Point(brd, h - 40); + _lblDisplay.BoxingOptions.Size = new Size(w - (brd * 2), 30); + + _txtInput.BoxingOptions.Location = new Point(brd, _lblDisplay.BoxingOptions.Location.Y - 40); + _txtInput.BoxingOptions.Size = _lblDisplay.BoxingOptions.Size; + } + protected override void WndProc(ref Message m) + { + //this handles all form edges and button mouse overs for title. + if (_titleBar == null || !_titleBar.WndProc(ref m)) + base.WndProc(ref m); + } + } +} diff --git a/Demo/FormDemo.resx b/Demo/FormDemo.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Demo/FormDemo.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Demo/Program.cs b/Demo/Program.cs new file mode 100644 index 0000000..0c07285 --- /dev/null +++ b/Demo/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Demo +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new FormDemo()); + } + } +} diff --git a/Demo/Properties/AssemblyInfo.cs b/Demo/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..eff49af --- /dev/null +++ b/Demo/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Demo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Demo")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b8318fef-8fc2-44cf-a490-f4afb70745e8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Demo/Properties/Resources.Designer.cs b/Demo/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8b245d3 --- /dev/null +++ b/Demo/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Demo.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demo.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Demo/Properties/Resources.resx b/Demo/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Demo/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Demo/Properties/Settings.Designer.cs b/Demo/Properties/Settings.Designer.cs new file mode 100644 index 0000000..d196517 --- /dev/null +++ b/Demo/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Demo.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Demo/Properties/Settings.settings b/Demo/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Demo/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Demo/imgs/test.bmp b/Demo/imgs/test.bmp new file mode 100644 index 0000000000000000000000000000000000000000..793b541ccf73c204fde0a07c1e3030f1ec0be1b0 GIT binary patch literal 197934 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 literal 0 HcmV?d00001 diff --git a/Demo/imgs/test.jpg b/Demo/imgs/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c86e937b1d3bda78d44ebedbce44f11588326cf GIT binary patch literal 2116 zcmbW1dsLH08pbDtkU&9=1n`F3LGS{EN&zcbQ9-07a?w;!q97uTCJHE2fp1X+K@+iuF^#%r0o}9;1R-*f3JnNK6a_?X3PM1VkT2hCtb2O)&uyRg%$%9?oO$2h%$ync z4EBRX+kO3g0ZtqHv;iOnEWX;hX^UlObkrd>=P)NGHagzYpB=T%a+m8m7gqqEgLFV3 z5J&`)A(3cksIRYYXk@6B(Vq~GKq46s4L&9?GBo&8OFvbC5?na|I0Ei>f&U7pgV!bK z5lQ+6pWy)hlc()Jx&LD>0y;Q6UPl*CAn599)1+uUpi3q!wsPI1XB@PjXnl-AP2*l6 z+4xjGFbS4U*}6r>oz^!nHCwWDnVr4EDo3Z!*Smk=;pw$`%T`~%ZT{OsLU-Ol0tm_xDO#wQ#a~jN{GS9js;ckY{kQ1n zU+y(DN**>fx3oU$?0VAO^YmG-Y+&&9(3|0r(XsJq`ONHxIfYU+Pu3#q=<4Eii64=1 zI*HnbC+iZdT=f=j3L@@5W^7GOBT;;~S1KRq+qeZ!nMB4(4NPr6AF!MLNc}tX|Hpj# zFG2so{0B0u2V@d(1ynpvOHan($v7wjhIpKIf+qtSm|+?z;~F5KXAcgpm3t;%p7h#) ztKa8^lhx79F9COEGuf;v*qNSrD|f&PG(^>Lt1Pch8ovCkLosTNT9X+wPg*79PC?>cLT`nH6ou z8Itx3ODjk}^?E#fPkH%I=806Zu$r;QO>1|Dm%lr1F?IWng-StF%rmidHN1%&4vOY} zgz?0x8TZtAt*Pdt+jAOToW3DRosYQUZ_&(H@oLE%%E)q0yD7h$0src;ujstjm*Dqn zgP4AD<-kPULJ0CgX}f8&QH=Uw=Y6 zdNt=j_mvyxS^aytXzMw;Y=c7=pDRnby-@YmOoP%fry5!eZKxQ-JIg)4W5y_`o|FCZ zSBlD%W(bP1G+kKt9>*)R6G%*adn9Llp6&9D21Tk1%e^^=5Y^1rBJq^Eo|@QNk^7 z32xyPj5&S)g4-PJ z9xlm>r>!s#WNcd&>MZ5yE%;vJu80{Po$DaJeBM~$lOM3mg&MuPdz-7QOPD?u>(R)LZpA7k&K#S<1KGjSN9a&t<2b zcBTSZ5Z}|`+he`gq?*{Yn}HOYrGbuWnR|h zch~JI9H>?YpdIIk+p&wMs%K_>G%SZ-q~;l&YgXax)J^woDkUxB5}iD=w zPDPNBTp)4h{DR7&%=C;BhBf?Wtbn3?V9}z~M37R2lFZyx2Gj5SoIn{)kW6rXT1k0g zQ7S`h!GDl)Zm{8*#mPB|K&3?t+YfB%2MTk5gu@ey@-p+%84gH4YX^$4L-dyxC8sic z{oni=rp!4%H#aq}gyGwnY5Rd7@o zYjpOrO$P6WWd)|d@DpHCP-GB7C8B<;KX~!t#XoQF?q0mj;KG+zq0{;0^Zu+qxVQTK z+3)Y;fo3U$hZpzD*WY;g^5wDj)qxy*e0;yso<9af-0JPw?-yHt{&n)EoBZ*6_v~x8 z{XYI8lBeM6mG9g0bgPbC1={H_8f);Bn^k@C;pfkv^J+fiToGfNwah-+-g35??f*wd zSIL)`x%nkcxSm^DS-JDY%*=Vu9g7>xTUTRdw}8LwCQZ?K#!`vhz(Rn*)78&qol`;+ E01B}1)iSKm+0 zCP{KW`8PR}G_uvvSL1j+mEF)7tV4FkRAV}ORFeFX)pWMbAD`E&gY{IlK0kQ;pV|7Y zp~t*4Sm)2bFm%j|gZ1CjXOj0CuN)ok*X%JfgY|FOdUohI3qwEaa<X$8&ei_Ph)nXMh9t zg1sOE9FPGH$N&dqfCDnX0U6+c43u$TcXu~D>VKgk?7_Y7z6{ID%Z1+$-rCvGrg6Zv%8NYV00&0B59IHHdf34M4sf6zd;LY%0{QJ6-~b0WzyS_$ zfCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h0 z0S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K0 z2ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`2 z9N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8 zaDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0W zzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h z00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70 z103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh1 z4sd`29N+*4IKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4 zIKTl8aDW3G-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G z-~b0WzyS_$fCC)h00%h00S<70103K02ROh14sd`29N+*4IKTl8aDW3G-~b0WzyS_a z<-p$FUU>3pM@86!ho8-bmCNlgDhtE+UBA8>zJ0Q!V(h^WAB2sKjl#3e=iY2KLz>m>z3YSIg*38d%%IX=V$+!UlkePfE-nkBgcq4M;wTIe)gaFRgnP>$WawJa*Vih z#DTcyXaAXB6&c`w995Ac$A~*e9Ef{<_MiDxkpT|KQ589IjJR{efw<>q|CwJE87SjG zyPbV5wcAxO_Mp=#^_jnRyA`_Kwu-a|M|-uz=RC_eu)Vzx!0_vZ zb*ogL^-I5A<_wg%9(bA0!|!IF$-wv-;K2C3lRLeelnih{mM104&SU&6b71`5$(`O! hN(ML}%af92=P`bkIWT_j + /// Building custom boxes on your form. + /// + public class SWFBoxing : BoxMethods + { + #region Public Form Events and Delegates + //public delegate void SWFExceptionEventHandler(object sender, SWFMessageEventArgs e); + public delegate void SWFMessageHandler(object sender, SWFMessageEventArgs e); + public event MouseEventHandler MouseDown; + public event MouseEventHandler MouseUp; + public event MouseEventHandler MouseMove; + public event EventHandler MouseLeave; + public event EventHandler Resize; + public event PaintEventHandler Paint; + public event KeyEventHandler KeyUp; + public event KeyEventHandler KeyDown; + public event KeyPressEventHandler KeyPress; + public event SWFMessageHandler Exception; + public event SWFMessageHandler Success; + #endregion + + #region Constructor + /// + /// Building custom boxes on your form. + /// + /// Form Handle => new SWFBoxing(this, ...) + /// + /// + public SWFBoxing(Form frm, SWFBoxingOptions options) + { + if (options == null) + throw new ArgumentNullException("Options is required."); + if (string.IsNullOrWhiteSpace(options.Name)) + throw new ArgumentNullException($"Name property for this box is required.\nType: {options.Type}\nText: {options.TextSetup.Text}"); + + if (GetZIndex(ref options, out int z)) + throw new ArgumentNullException($"'{options.Name}' already exists."); + + options.TextSetup.TextCursor = options.TextSetup.Text.Length; + + this.SetBoxOptions = options; + this.BoxingOptions.Parent = frm; + this.BoxingOptions.ZIndex = z; + + BoxingLoc = new Rectangle(this.BoxingOptions.Location, this.BoxingOptions.Size); + + SetupOptions(); + } + #endregion + + #region Private Properties + private Rectangle BoxingLoc { get; set; } = new Rectangle(); + private bool IgnoreKeyPress { get; set; } = false; + private bool ButtonClicked { get; set; } = false; + private bool InputStart { get; set; } = false; + private bool IsInBounds { get; set; } = false; + private bool CursorChanged { get; set; } = false; + private string DefaultTip { get; set; } = string.Empty; + private SWFBoxingOptions SetBoxOptions { get; set; } = new SWFBoxingOptions(); + #endregion + + #region Public Properties + + /// + /// All setup options for the object your creating. Can be passed in with Constructor or this property. + /// + public SWFBoxingOptions BoxingOptions { get { return SetBoxOptions; } } + + /// + /// Get bounderies for this object. + /// + public Rectangle Rectangle { get { return BoxingLoc; } } + + /// + /// Get location for this object. + /// + public Point Location { get { return BoxingLoc.Location; } } + + /// + /// Get size for this object. + /// + public Size Size { get { return BoxingLoc.Size; } } + + /// + /// Get left boundary for this object. + /// + public int Left { get { return BoxingLoc.X; } } + + /// + /// Get top boundary for this object. + /// + public int Top { get { return BoxingLoc.Y; } } + + /// + /// Get right boundary for this object. + /// + public int Right { get { return BoxingLoc.X + BoxingLoc.Width; } } + + /// + /// Get bottom boundary for this object. + /// + public int Bottom { get { return BoxingLoc.Y + BoxingLoc.Height; } } + #endregion + + #region Private Keyboard Events + private void MR_KeyUp(object sender, KeyEventArgs e) + { + KeyUp?.Invoke(this, e); + } + private void MR_KeyDown(object sender, KeyEventArgs e) + { + if (this.BoxingOptions != null && this.InputStart) + { + bool changes = false; + string text = this.BoxingOptions.TextSetup.Text; + + //KeyPress doesn't capture some keys. We must handle them here. + if (e.KeyCode == Keys.Right) + { + this.BoxingOptions.TextSetup.TextCursor++; + changes = true; + } + else if (e.KeyCode == Keys.Left) + { + this.BoxingOptions.TextSetup.TextCursor--; + changes = true; + } + else if (e.KeyCode == Keys.Delete) + { + Console.WriteLine($"KeyDown: {e.KeyCode}"); + //only used for Delete at the moment. + if (!string.IsNullOrEmpty(text)) + { + int textCursor = this.BoxingOptions.TextSetup.TextCursor; + if (text.Length - (textCursor) > 0) + { + string newText = text.Substring(0, textCursor); + newText += text.Substring(textCursor + 1, text.Length - (textCursor + 1)); + text = newText; + changes = true; + + if (textCursor - 1 > text.Length) + this.BoxingOptions.TextSetup.TextCursor--; + } + } + else + Console.WriteLine($"KeyDown: Nothing to {Keys.Delete}"); + } + else if (e.KeyCode == Keys.Enter) + { + bool valid = true; + string validMessage = "No expression found"; + + lock (SetBoxOptions) + this.IgnoreKeyPress = true; + + Console.WriteLine($"KeyDown: {e.KeyCode}"); + if (this.BoxingOptions.TextSetup.ValidInputExpression != null) + { + string pattern = this.BoxingOptions.TextSetup.ValidInputExpression; + valid = Regex.Match(text, pattern, RegexOptions.IgnoreCase).Success; + if (valid) + validMessage = "Expression is valid"; + } + + if (valid) + { + changes = true; + this.InputStart = false; + this.BoxingOptions.TextSetup.TextCursor = text.Length; + Success?.Invoke(this, + new SWFMessageEventArgs( + validMessage + )); + } + else + { + Exception?.Invoke(this, + new SWFMessageEventArgs( + new Exception("Failed regex expression.") + )); + } + } + else if (e.KeyCode == Keys.Escape) + { + lock (SetBoxOptions) + { + this.IgnoreKeyPress = true; + this.InputStart = false; + } + + Console.WriteLine($"KeyDown: {e.KeyCode}"); + changes = true; + text = this.DefaultTip; + this.BoxingOptions.TextSetup.TextCursor = text.Length; + } + else if (e.KeyCode == Keys.Back) + { + Console.WriteLine($"KeyDown: {e.KeyCode}"); + int textCursor = this.BoxingOptions.TextSetup.TextCursor; + if (!string.IsNullOrEmpty(text) && textCursor > 0) + { + string newText = text.Substring(0, textCursor - 1); + int size = text.Length > textCursor ? text.Length - textCursor : textCursor - text.Length; + newText += text.Substring(textCursor, size); + text = newText; + + changes = true; + this.BoxingOptions.TextSetup.TextCursor--; + } + else + Console.WriteLine($"Nothing to {e.KeyCode}"); + + lock (SetBoxOptions) + this.IgnoreKeyPress = true; + } + + if (this.BoxingOptions.TextSetup.TextCursor < 0) + this.BoxingOptions.TextSetup.TextCursor = 0; + else if (this.BoxingOptions.TextSetup.TextCursor > text.Length) + this.BoxingOptions.TextSetup.TextCursor = text.Length; + + if (changes) + { + this.BoxingOptions.TextSetup.Text = text; + this.BoxingOptions.Parent.Invalidate(); + } + } + + KeyDown?.Invoke(this, e); + } + private void MR_KeyPress(object sender, KeyPressEventArgs e) + { + if (this.BoxingOptions != null && this.InputStart) + { + lock (SetBoxOptions) + { + if (!this.IgnoreKeyPress) + { + Console.WriteLine($"KeyPress: {e.KeyChar}"); + + string text = this.BoxingOptions.TextSetup.Text; + int textCursor = this.BoxingOptions.TextSetup.TextCursor; + + string newText = string.IsNullOrEmpty(text) || textCursor == 0 ? "" : + text.Substring(0, textCursor); + string subText = string.IsNullOrEmpty(text) || textCursor == 0 ? "" : + text.Substring(textCursor, text.Length - textCursor); + + this.BoxingOptions.TextSetup.TextCursor++; + + text = newText; + text += e.KeyChar.ToString(); + text += subText; + + this.BoxingOptions.TextSetup.Text = text; + this.BoxingOptions.Parent.Invalidate(); + + if (this.BoxingOptions.TextSetup.TextCursor < 0) + this.BoxingOptions.TextSetup.TextCursor = 0; + else if (this.BoxingOptions.TextSetup.TextCursor > text.Length) + this.BoxingOptions.TextSetup.TextCursor = text.Length; + } + else + Console.WriteLine($"KeyPress: Ignoring {e.KeyChar}"); + + this.IgnoreKeyPress = false; + } + } + + KeyPress?.Invoke(this, e); + } + #endregion + + #region Private Mouse Events + private void MR_MouseLeave(object sender, EventArgs e) + { + if (CursorChanged && this.BoxingOptions != null) + { + CursorChanged = false; + this.BoxingOptions.Parent.Cursor = Cursors.Default; + } + this.MouseLeave?.Invoke(this, e); + } + private void MR_MouseUp(object sender, MouseEventArgs e) + { + if (this.BoxingOptions != null && this.ButtonClicked && this.IsInBounds) + { + this.ButtonClicked = false; + this.BoxingOptions.Location = new Point(this.BoxingOptions.Location.X - this.BoxingOptions.Shadowing.Depth, + this.BoxingOptions.Location.Y - this.BoxingOptions.Shadowing.Depth); + this.BoxingOptions.Parent.Invalidate(); + } + + if (this.IsInBounds) + MouseUp?.Invoke(this, e); + } + private void MR_MouseDown(object sender, MouseEventArgs e) + { + if (this.BoxingOptions == null) + return; + + if (IsClickable() && this.IsInBounds) + { + if (ImOnTop(this.BoxingOptions)) + { + if (this.BoxingOptions.Type == SWF_BOX_TYPE.TextBox) + { + this.InputStart = true; + string text = this.BoxingOptions.TextSetup.Text; + this.DefaultTip = text; + + if (text.StartsWith("[") && text.EndsWith("]")) + this.BoxingOptions.TextSetup.Text = ""; + this.BoxingOptions.Parent.Invalidate(); + } + else if (this.BoxingOptions.Type == SWF_BOX_TYPE.Button && this.BoxingOptions.Shadowing.Depth > 0) + { + this.ButtonClicked = true; + this.BoxingOptions.Location = new Point(this.BoxingOptions.Location.X + this.BoxingOptions.Shadowing.Depth, + this.BoxingOptions.Location.Y + this.BoxingOptions.Shadowing.Depth); + this.BoxingOptions.Parent.Invalidate(); + } + + this.MouseDown?.Invoke(this, e); + } + } + } + private void MR_MouseMove(object sender, MouseEventArgs e) + { + if (this.BoxingOptions == null) + return; + + if(Global.IsInBounds(this.BoxingOptions.Parent, e.Location, this.BoxingLoc)) + { + if (ImOnTop(this.BoxingOptions)) + { + this.IsInBounds = true; + bool isClickable = IsClickable(); + Cursor cursor = GetCursorByType(this.BoxingOptions.Parent, this.BoxingOptions.Cursors.OnMove, out bool cursorChanged); + + if (isClickable && cursorChanged) + { + this.BoxingOptions.Parent.Cursor = cursor; + this.CursorChanged = cursorChanged; + } + + this.MouseMove?.Invoke(this, e); + } + } + else + { + //check to see if this object was in bounds, if not, then ignore.. + if (this.IsInBounds) + { + this.IsInBounds = false; + this.BoxingOptions.Parent.Cursor = Cursors.Default; + this.CursorChanged = true; + this.MouseLeave?.Invoke(this, e); + } + + if (this.ButtonClicked) + { + this.ButtonClicked = false; + this.BoxingOptions.Location = new Point(this.BoxingOptions.Location.X - this.BoxingOptions.Shadowing.Depth, + this.BoxingOptions.Location.Y - this.BoxingOptions.Shadowing.Depth); + this.BoxingOptions.Parent.Invalidate(); + } + } + } + #endregion + + #region Private Form Events + private void MR_Resize(object sender, EventArgs e) + { + this.BoxingLoc = new Rectangle(this.BoxingOptions.Location, this.BoxingOptions.Size); + this.BoxingOptions.Parent.Invalidate(); + this.Resize?.Invoke(this, e); + } + private void MR_Paint(object sender, PaintEventArgs e) + { + Rectangle rec = e.ClipRectangle; + Graphics g = e.Graphics; + if (g != null && + this.BoxingOptions.Location.X < this.BoxingOptions.Parent.Width && + this.BoxingOptions.Location.Y < this.BoxingOptions.Parent.Height) + { + if (this.BoxingOptions.Type == SWF_BOX_TYPE.FormBody) + { + this.BoxingOptions.Location = new Point(0, this.BoxingOptions.TitleBarHeight - this.BoxingOptions.BorderSize); + this.BoxingOptions.Size = new Size(this.BoxingOptions.Parent.Width, + this.BoxingOptions.Parent.Height - this.BoxingOptions.TitleBarHeight); + + //cannot do shadowing on the form, as it's not able to draw off the form. + //possibly in the future, sizing of the form instead so shadow shows up, + //however, since the real form is pink, it might not work. + this.BoxingOptions.Shadowing = null; + } + + Rectangle titleBG = new Rectangle(this.BoxingOptions.Location, this.BoxingOptions.Size); + + BoxInfo bi = Global.CreateBox(g, new BoxInfo() + { + BackColor = this.BoxingOptions.BackColor, + ForeColor = this.BoxingOptions.TextSetup.Color, + BorderColor = this.BoxingOptions.BorderColor, + BorderSize = this.BoxingOptions.BorderSize, + Rectangle = titleBG, + HAlign = this.BoxingOptions.TextSetup.HorizonalAlign, + VAlign = this.BoxingOptions.TextSetup.VerticalAlign, + Font = this.BoxingOptions.TextSetup.Font, + Text = this.BoxingOptions.TextSetup.Text, + Padding = this.BoxingOptions.Padding, + Shadowing = this.BoxingOptions.Shadowing, + BackgroundImage = this.BoxingOptions.TextSetup.BackgroundImage, + RoundedCorners = this.BoxingOptions.RoundedCorners, + RoundedRadius = this.BoxingOptions.RoundedRadius, + BackgroundImageLayout = this.BoxingOptions.TextSetup.BackgroundImageLayout, + ReplaceImageColor = this.BoxingOptions.TextSetup.ReplaceImageColor, + ButtonClicked = this.ButtonClicked, + TextCursor = this.BoxingOptions.TextSetup.TextCursor, + Type = this.BoxingOptions.Type, + InputStart = this.InputStart, + }); + + if (bi.BackgroundImageModified) + { + this.BoxingOptions.TextSetup.BackgroundImage = bi.BackgroundImage; + this.BoxingOptions.TextSetup.ReplaceImageColor = bi.ReplaceImageColor; + } + + BoxingLoc = new Rectangle(this.BoxingOptions.Location, this.BoxingOptions.Size); + } + this.Paint?.Invoke(this, e); + } + #endregion + + #region Private Methods + private bool IsClickable() + { + if (this.MouseDown != null || + this.MouseUp != null || + this.BoxingOptions.Type == SWF_BOX_TYPE.Button || + this.BoxingOptions.Type == SWF_BOX_TYPE.TextBox) + return true; + else + return false; + } + private void SetupOptions() + { + this.BoxingOptions.Parent.MouseMove += MR_MouseMove; + this.BoxingOptions.Parent.MouseLeave += MR_MouseLeave; + this.BoxingOptions.Parent.MouseUp += MR_MouseUp; + this.BoxingOptions.Parent.MouseDown += MR_MouseDown; + this.BoxingOptions.Parent.Paint += MR_Paint; + this.BoxingOptions.Parent.Resize += MR_Resize; + this.BoxingOptions.Parent.KeyPress += MR_KeyPress; + this.BoxingOptions.Parent.KeyUp += MR_KeyUp; + this.BoxingOptions.Parent.KeyDown += MR_KeyDown; + } + #endregion + + #region Public Static Methods + /// + /// Load image from file. Supported files types are (gif,bmp,ico,tif,jpg,png). + /// + public static object ImageFromFile(string path) + { + if (typeof(T).Name.ToLower() == "image") + return (object)Global.GetImage(path); + else if (typeof(T).Name.ToLower() == "icon") + return (object)Global.GetIcon(path); + else + return null; + } + #endregion + } +} diff --git a/SwitchWinForms/Handler/SWFTitlebar.cs b/SwitchWinForms/Handler/SWFTitlebar.cs new file mode 100644 index 0000000..1d31bd4 --- /dev/null +++ b/SwitchWinForms/Handler/SWFTitlebar.cs @@ -0,0 +1,378 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.IO; + +namespace SwitchWinForms +{ + /// + /// Creating a custome Titlebar, this replaces your exists. Do not use more that one instnace per project. + /// + public partial class SWFTitlebar : BoxMethods + { + #region Constructor + public SWFTitlebar(Form frm, SWFTitlebarOptions options = null) + { + if (frm == null) + { + SetLastError = new ArgumentNullException("Missing Form Object"); + throw SetLastError; + } + + if (frm.FormBorderStyle != FormBorderStyle.None) + frm.FormBorderStyle = FormBorderStyle.None; + + //Ensure doublebuffered set on form. + //This stops major flickering. + SetDoubleBuffered(frm); + + frm.BackColor = Color.FromArgb(192, 0, 191); + frm.TransparencyKey = frm.BackColor; + + if (frm.MinimumSize.Width == 0 && + frm.MinimumSize.Height == 0) + frm.MinimumSize = new Size(100, 100); + + TitleOptions = options ?? new SWFTitlebarOptions(); + TitleOptions.GetSetParent = frm; + + if (TitleOptions.TextSetup != null && !TitleOptions.TextSetup.Empty) + TitleOptions.Parent.Text = TitleOptions.TextSetup?.Text; + + SetupOptions(); + } + #endregion + + #region Private Form Events + private void Form_MouseUp(object sender, MouseEventArgs e) + { + this.Drag = false; + } + private void Form_MouseDown(object sender, MouseEventArgs e) + { + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Close) == SWF_TITLE_BUTTON.Close + && Global.IsInBounds(TitleOptions.Parent, e.Location, this.BtnCloseRec, Cursors.Hand)) + { + TitleOptions.Parent.Close(); + } + else if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Minimize) == SWF_TITLE_BUTTON.Minimize + && Global.IsInBounds(TitleOptions.Parent, e.Location, this.BtnMinRec, Cursors.Hand)) + { + TitleOptions.Parent.WindowState = FormWindowState.Minimized; + } + else if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Maximize_Normal) == SWF_TITLE_BUTTON.Maximize_Normal + && Global.IsInBounds(TitleOptions.Parent, e.Location, this.BtnMaxRec, Cursors.Hand)) + { + + if (TitleOptions.Parent.WindowState == FormWindowState.Maximized) + TitleOptions.Parent.WindowState = FormWindowState.Normal; + else + TitleOptions.Parent.WindowState = FormWindowState.Maximized; + } + else if (TitleOptions.Height > e.Location.Y) + { + this.StartPoint = e.Location; + this.Drag = true; + } + } + private void Form_MouseMove(object sender, MouseEventArgs e) + { + if (this.Drag) + { + // if we should be dragging it, we need to figure out some movement + Point p1 = new Point(e.X, e.Y); + Point p2 = TitleOptions.Parent.PointToScreen(p1); + Point p3 = new Point(p2.X - this.StartPoint.X, + p2.Y - this.StartPoint.Y); + + TitleOptions.Parent.Location = p3; + } + else + { + if (Global.IsInBounds(TitleOptions.Parent, e.Location, TitleOptions.Rectangle) + && TitleOptions.Parent.Cursor != Cursors.Default) + { + int x = 0; + int t = 0; + int b = 0; + + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Minimize) == SWF_TITLE_BUTTON.Minimize) + { + x = this.BtnMinRec.Left; + t = this.BtnMinRec.Top; + b = this.BtnMinRec.Top + this.BtnMinRec.Height; + } + else if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Maximize_Normal) == SWF_TITLE_BUTTON.Maximize_Normal) + { + x = this.BtnMaxRec.Left; + t = this.BtnMaxRec.Top; + b = this.BtnMaxRec.Top + this.BtnMaxRec.Height; + } + else if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Close) == SWF_TITLE_BUTTON.Close) + { + x = this.BtnCloseRec.Left; + t = this.BtnCloseRec.Top; + b = this.BtnCloseRec.Top + this.BtnCloseRec.Height; + } + + if (e.X < x || e.Y < t || e.Y > b) + TitleOptions.Parent.Cursor = Cursors.Default; + } + } + } + private void Form_Resize(object sender, EventArgs e) + { + if ((TitleOptions.Parent.MinimumSize.Width == 0 && + TitleOptions.Parent.MinimumSize.Height == 0) || + (TitleOptions.Parent.MinimumSize.Width == 100 && + TitleOptions.Parent.MinimumSize.Height == 100)) + { + int w = 0; + int fWidth = TitleOptions.Parent.Width + (this.BtnMinRec.Width / 2); + + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Minimize) == SWF_TITLE_BUTTON.Minimize && this.BtnMinRec.Height > 0) + w = fWidth - this.BtnMinRec.Left; + else if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Maximize_Normal) == SWF_TITLE_BUTTON.Maximize_Normal && this.BtnMaxRec.Height > 0) + w = fWidth - this.BtnMaxRec.Left; + else if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Close) == SWF_TITLE_BUTTON.Close && this.BtnCloseRec.Height > 0) + w = fWidth - this.BtnCloseRec.Left; + + if (w > 0) + TitleOptions.Parent.MinimumSize = new Size(w, 100); + } + + TitleOptions.Parent.Invalidate(); + } + private void Form_Paint(object sender, PaintEventArgs e) + { + Graphics g = e.Graphics; + if (g != null) + { + TitleOptions.Location = new Point(0, 0); + TitleOptions.Size = new Size(TitleOptions.Parent.Width, TitleOptions.Height); + + /*if ((TitleOptions.RoundedCorners & SWF_ARC_CORNERS.TopLeft) > 0 && TitleOptions.TextSetup.HorizonalAlign == StringAlignment.Near) + { + float f = ((float)TitleOptions.RoundedRadius) * 0.5F; + int extra = (int)Math.Floor(f); + TitleOptions.Padding = new Padding(TitleOptions.Padding.Left + extra, TitleOptions.Padding.Top, TitleOptions.Padding.Right, TitleOptions.Padding.Bottom); + }*/ + + BoxInfo boxInfo = new BoxInfo() + { + BackColor = TitleOptions.BackColor, + ForeColor = TitleOptions.TextSetup.Color, + BorderColor = TitleOptions.BorderColor, + BorderSize = TitleOptions.BorderSize, + Rectangle = TitleOptions.Rectangle, + HAlign = TitleOptions.TextSetup.HorizonalAlign, + VAlign = TitleOptions.TextSetup.VerticalAlign, + Font = TitleOptions.TextSetup.Font, + Text = TitleOptions.TextSetup.Text, + Padding = TitleOptions.Padding, + BackgroundImage = TitleOptions.TextSetup.BackgroundImage, + RoundedCorners = TitleOptions.RoundedCorners, + RoundedRadius = TitleOptions.RoundedRadius, + BackgroundImageLayout = TitleOptions.TextSetup.BackgroundImageLayout, + ReplaceImageColor = TitleOptions.TextSetup.ReplaceImageColor, + Type = SWF_BOX_TYPE.Titlebar, + Icon = TitleOptions.Icon + }; + + BoxInfo bi = Global.CreateBox(g, boxInfo); //title + + if (bi.BackgroundImageModified) + { + TitleOptions.TextSetup.BackgroundImage = bi.BackgroundImage; + TitleOptions.TextSetup.ReplaceImageColor = bi.ReplaceImageColor; + } + + CreateButtons(g, boxInfo); //title buttons + } + } + #endregion + + #region Private Methods + private bool SetDoubleBuffered(Form frm) + { + bool retVal = false; + if (SystemInformation.TerminalServerSession) + { + SetLastError = new Exception("## WARN ##, Flicking may occur, because your in a terminal session."); + return retVal; + } + + if (frm != null) + { + try + { + PropertyInfo aProp = + typeof(Control).GetProperty("DoubleBuffered", + BindingFlags.NonPublic | BindingFlags.Instance); + + aProp.SetValue(frm, true, null); + retVal = true; + } + catch (Exception ex) + { + SetLastError = ex; + } + } + else + SetLastError = new Exception("## WARN ##, Missing Form object."); + + return retVal; + } + private void CreateButtons(Graphics g, BoxInfo boxInfo) + { + int buttonPadding = 2; + Rectangle titleRect = boxInfo.Rectangle; + Rectangle btnRect = boxInfo.Rectangle; + BoxInfo newBtnSetup; + + btnRect.Height = titleRect.Height - (TitleOptions.Padding.Top + TitleOptions.Padding.Bottom) - (boxInfo.BorderSize * 2); + btnRect.Width = btnRect.Height; + + float f = ((float)TitleOptions.RoundedRadius) * 0.5F; + int extra = (int)Math.Floor(f); + + if (TitleOptions.Icon != null) + { + btnRect.X = TitleOptions.Padding.Left + TitleOptions.BorderSize; + btnRect.Y = TitleOptions.Padding.Top + TitleOptions.BorderSize; + + if ((TitleOptions.RoundedCorners & SWF_ARC_CORNERS.TopLeft) > 0) + btnRect.X += extra; + + newBtnSetup = new BoxInfo() + { + Rectangle = btnRect, + BackgroundImageLayout = SWF_BG_IMG_LAYOUT.Normal, + BorderSize = TitleOptions.Close.BorderSize, + BorderColor = TitleOptions.Close.BorderColor, + RoundedCorners = TitleOptions.Close.RoundedCorners, + RoundedRadius = TitleOptions.Close.RoundedRadius, + BackgroundImage = TitleOptions.Icon, + }; + //newBtnSetup.Rectangle = new Rectangle(new Point(30, 0), new Size(200, 200)); + + Global.CreateBox(g, newBtnSetup); + } + + btnRect.X = titleRect.Width - btnRect.Width - TitleOptions.Padding.Right - TitleOptions.BorderSize; + btnRect.Y = boxInfo.Rectangle.Y + TitleOptions.Padding.Top + TitleOptions.BorderSize; + + if ((TitleOptions.RoundedCorners & SWF_ARC_CORNERS.TopRight) > 0) + btnRect.X -= extra; + + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Close) > 0) + { + newBtnSetup = new BoxInfo() + { + BackColor = TitleOptions.Close.BackColor, + ForeColor = TitleOptions.Close.TextSetup.Color, + BorderSize = TitleOptions.Close.BorderSize, + BorderColor = TitleOptions.Close.BorderColor, + Font = TitleOptions.Close.TextSetup.Font, + Padding = TitleOptions.Close.Padding, + HAlign = TitleOptions.Close.TextSetup.HorizonalAlign, + VAlign = TitleOptions.Close.TextSetup.VerticalAlign, + Rectangle = btnRect, + Text = TitleOptions.Close.TextSetup.Text, + RoundedCorners = TitleOptions.Close.RoundedCorners, + RoundedRadius = TitleOptions.Close.RoundedRadius + }; + + this.BtnCloseRec = newBtnSetup.Rectangle; + Global.CreateBox(g, newBtnSetup); + btnRect.X -= (btnRect.Width + buttonPadding + boxInfo.BorderSize); + newBtnSetup.Rectangle = btnRect; + } + else + this.BtnCloseRec = new Rectangle(); + + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Maximize_Normal) > 0) + { + if (TitleOptions.Parent.WindowState == FormWindowState.Maximized) + { + newBtnSetup = new BoxInfo() + { + BackColor = TitleOptions.Maximize.BackColor, + ForeColor = TitleOptions.Maximize.TextSetup.Color, + BorderSize = TitleOptions.Maximize.BorderSize, + BorderColor = TitleOptions.Maximize.BorderColor, + Font = TitleOptions.Maximize.TextSetup.Font, + Padding = TitleOptions.Maximize.Padding, + HAlign = TitleOptions.Maximize.TextSetup.HorizonalAlign, + VAlign = TitleOptions.Maximize.TextSetup.VerticalAlign, + Rectangle = btnRect, + Text = TitleOptions.Maximize.TextSetup.Text, + RoundedCorners = TitleOptions.Maximize.RoundedCorners, + RoundedRadius = TitleOptions.Maximize.RoundedRadius + }; + } + else + { + newBtnSetup = new BoxInfo() + { + BackColor = TitleOptions.Normal.BackColor, + ForeColor = TitleOptions.Normal.TextSetup.Color, + BorderSize = TitleOptions.Normal.BorderSize, + BorderColor = TitleOptions.Normal.BorderColor, + Font = TitleOptions.Normal.TextSetup.Font, + Padding = TitleOptions.Normal.Padding, + HAlign = TitleOptions.Normal.TextSetup.HorizonalAlign, + VAlign = TitleOptions.Normal.TextSetup.VerticalAlign, + Rectangle = btnRect, + Text = TitleOptions.Normal.TextSetup.Text, + RoundedCorners = TitleOptions.Normal.RoundedCorners, + RoundedRadius = TitleOptions.Normal.RoundedRadius + }; + } + + this.BtnMaxRec = newBtnSetup.Rectangle; + Global.CreateBox(g, newBtnSetup); + btnRect.X -= (btnRect.Width + buttonPadding + boxInfo.BorderSize); + newBtnSetup.Rectangle = btnRect; + } + else + this.BtnMaxRec = new Rectangle(); + + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Minimize) > 0) + { + newBtnSetup = new BoxInfo() + { + BackColor = TitleOptions.Minimized.BackColor, + ForeColor = TitleOptions.Minimized.TextSetup.Color, + BorderSize = TitleOptions.Minimized.BorderSize, + BorderColor = TitleOptions.Minimized.BorderColor, + Font = TitleOptions.Minimized.TextSetup.Font, + Padding = TitleOptions.Minimized.Padding, + HAlign = TitleOptions.Minimized.TextSetup.HorizonalAlign, + VAlign = TitleOptions.Minimized.TextSetup.VerticalAlign, + Rectangle = btnRect, + Text = TitleOptions.Minimized.TextSetup.Text, + RoundedCorners = TitleOptions.Minimized.RoundedCorners, + RoundedRadius = TitleOptions.Minimized.RoundedRadius + }; + + this.BtnMinRec = newBtnSetup.Rectangle; + Global.CreateBox(g, newBtnSetup); + btnRect.X -= (btnRect.Width + buttonPadding + boxInfo.BorderSize); + newBtnSetup.Rectangle = btnRect; + } + else + this.BtnMinRec = new Rectangle(); + } + private void SetupOptions() + { + TitleOptions.Parent.MouseMove += Form_MouseMove; + TitleOptions.Parent.MouseUp += Form_MouseUp; + TitleOptions.Parent.MouseDown += Form_MouseDown; + TitleOptions.Parent.Paint += Form_Paint; + TitleOptions.Parent.Resize += Form_Resize; + } + #endregion + } +} diff --git a/SwitchWinForms/Helper/BoxMethods.cs b/SwitchWinForms/Helper/BoxMethods.cs new file mode 100644 index 0000000..16e06e3 --- /dev/null +++ b/SwitchWinForms/Helper/BoxMethods.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Security.Permissions; +using System.Windows.Forms; + +namespace SwitchWinForms +{ + public abstract class BoxMethods + { + private static SWFTitlebarOptions _titleOptions = null; + + const int cursorFormEdge = 5; + const int WM_NCHITTEST = 0x0084; + + private SWF_RESIZEABLE _resizeable = SWF_RESIZEABLE.None; + + + #region Internal Properties + internal static Dictionary ZIndex { get; } = new Dictionary(); + internal static int LatestZIndex { get; set; } = 0; + internal Rectangle BtnCloseRec { get; set; } = new Rectangle(); + internal Rectangle BtnMinRec { get; set; } = new Rectangle(); + internal Rectangle BtnMaxRec { get; set; } = new Rectangle(); + internal Point StartPoint { get; set; } = new Point(0, 0); // also for the moving + internal bool Drag { get; set; } = false; // determine if we should be moving the form + internal Exception SetLastError { get; set; } + #endregion + + #region Public Methods + [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] + public bool WndProc(ref Message m) + { + bool retVal = false; + + if (m.Msg == WM_NCHITTEST && IsFormResizeable()) + { + int x = (int)(m.LParam.ToInt64() & 0xFFFF); + int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16); + Point pt = SWFTitlebar.TitleOptions.Parent.PointToClient(new Point(x, y)); + Size clientSize = SWFTitlebar.TitleOptions.Parent.ClientSize; + + if (Global.IsInBounds(SWFTitlebar.TitleOptions.Parent, pt, this.BtnCloseRec, Cursors.Hand) || + Global.IsInBounds(SWFTitlebar.TitleOptions.Parent, pt, this.BtnMinRec, Cursors.Hand) || + Global.IsInBounds(SWFTitlebar.TitleOptions.Parent, pt, this.BtnMaxRec, Cursors.Hand)) + { + retVal = false; + } + else if (pt.X <= cursorFormEdge && pt.Y >= clientSize.Height - cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWFTitlebar.TitleOptions.Parent.IsMirrored ? SWF_HITTEST.HT_BOTTOMRIGHT : SWF_HITTEST.HT_BOTTOMLEFT); + retVal = true; + } + else if (pt.X >= clientSize.Width - cursorFormEdge && pt.Y >= clientSize.Height - cursorFormEdge && clientSize.Width >= cursorFormEdge) + { + m.Result = (IntPtr)(SWFTitlebar.TitleOptions.Parent.IsMirrored ? SWF_HITTEST.HT_BOTTOMLEFT : SWF_HITTEST.HT_BOTTOMRIGHT); + retVal = true; + } + else if (pt.X <= cursorFormEdge && pt.Y <= cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWFTitlebar.TitleOptions.Parent.IsMirrored ? SWF_HITTEST.HT_TOPRIGHT : SWF_HITTEST.HT_TOPLEFT); + retVal = true; + } + else if (pt.X >= clientSize.Width - cursorFormEdge && pt.Y <= cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWFTitlebar.TitleOptions.Parent.IsMirrored ? SWF_HITTEST.HT_TOPLEFT : SWF_HITTEST.HT_TOPRIGHT); + retVal = true; + } + else if (pt.Y <= cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWF_HITTEST.HT_TOP); + retVal = true; + } + else if (pt.Y >= clientSize.Height - cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWF_HITTEST.HT_BOTTOM); + retVal = true; + } + else if (pt.X <= cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWF_HITTEST.HT_LEFT); + retVal = true; + } + else if (pt.X >= clientSize.Width - cursorFormEdge && clientSize.Height >= cursorFormEdge) + { + m.Result = (IntPtr)(SWF_HITTEST.HT_RIGHT); + retVal = true; + } + else + { + //SWFTitlebar.TitleOptions.Parent.Cursor = Cursors.Default; + retVal = false; + } + } + + return retVal; + } + public static SWFTitlebarOptions TitleOptions + { + get { return _titleOptions; } + set + { + _titleOptions = value; + if (TitleOptions.Parent != null && !string.IsNullOrWhiteSpace(TitleOptions.TextSetup?.Text)) + TitleOptions.Parent.Text = TitleOptions.TextSetup.Text; + } + } + public Exception LastError { get { return SetLastError; } } + #endregion + + #region Private/Internal Methods + internal bool GetZIndex(ref SWFBoxingOptions options, out int idx) + { + bool retVal = false; + + lock (ZIndex) + { + if (ZIndex.TryGetValue(options.Name, out SWFBoxingOptions foundOpt)) + { + idx = foundOpt.ZIndex; + retVal = true; + } + else + { + idx = ++LatestZIndex; + options.ZIndex = idx; + ZIndex.Add(options.Name, options); + } + } + + return retVal; + } + internal bool ImOnTop(SWFBoxingOptions options) + { + bool retVal = true; + + foreach (SWFBoxingOptions bopt in ZIndex.Values) + { + if (options.Name == bopt.Name) + continue; + + if (bopt.ZIndex > options.ZIndex) + { + if (options.Rectangle.Contains(bopt.Rectangle)) + { + retVal = false; + break; + } + } + } + + return retVal; + } + private bool IsFormResizeable() + { + if (this._resizeable == SWF_RESIZEABLE.None) + { + if ((TitleOptions.ButtonsEnabled & SWF_TITLE_BUTTON.Maximize_Normal) > 0) + this._resizeable = SWF_RESIZEABLE.Yes; + else + this._resizeable = SWF_RESIZEABLE.No; + } + + return this._resizeable == SWF_RESIZEABLE.Yes; + } + internal Cursor GetCursorByType(Form frm, Cursor defaultCursor, out bool cursorChanged) + { + Cursor retVal = frm.Cursor; + cursorChanged = false; + + if (retVal != defaultCursor) + { + cursorChanged = true; + retVal = defaultCursor; + } + return retVal; + } + #endregion + } +} diff --git a/SwitchWinForms/Models/BoxInfo.cs b/SwitchWinForms/Models/BoxInfo.cs new file mode 100644 index 0000000..096f204 --- /dev/null +++ b/SwitchWinForms/Models/BoxInfo.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +//test +namespace SwitchWinForms +{ + internal class BoxInfo + { + public int BorderSize { get; set; } + public Padding Padding { get; set; } + public Rectangle Rectangle { get; set; } + public SWF_BOX_TYPE Type { get; set; } + public int TextCursor { get; set; } + public string Text { get; set; } + public Image Icon { get; set; } + public Font Font { get; set; } + public StringAlignment VAlign { get; set; } + public StringAlignment HAlign { get; set; } + public Color BackColor { get; set; } + public Color BorderColor { get; set; } + public Color ForeColor { get; set; } + public Image BackgroundImage { get; set; } = null; + public List ReplaceImageColor { get; set; } = new List() { }; + public ShadowingSetup Shadowing { get; set; } = new ShadowingSetup(); + public SWF_BG_IMG_LAYOUT BackgroundImageLayout { get; set; } = SWF_BG_IMG_LAYOUT.Stretch; + public SWF_ARC_CORNERS RoundedCorners { get; set; } = SWF_ARC_CORNERS.None; + public int RoundedRadius { get; set; } = 0; + public bool Empty { get { return (this == new BoxInfo()); } } + + internal bool ButtonClicked { get; set; } = false; + internal bool InputStart { get; set; } = false; + internal Image BackgroundImageOrg { get; set; } = null; + internal bool BackgroundImageModified { get; set; } = false; + /// + /// Deprecated Method. + /// + /// + [Obsolete("IsTextEmpty() is deprecated, please use 'Empty' property instead.")] + public bool IsTextEmpty() + { + return Empty; + } + } +} diff --git a/SwitchWinForms/Models/ReplaceColor.cs b/SwitchWinForms/Models/ReplaceColor.cs new file mode 100644 index 0000000..bd0686b --- /dev/null +++ b/SwitchWinForms/Models/ReplaceColor.cs @@ -0,0 +1,31 @@ +using System; +using System.Drawing; + +namespace SwitchWinForms +{ + public class ReplaceColor + { + private int _defaultImageColorTolerance = 10; + public ReplaceColor() { } + public ReplaceColor(Color delete, Color add, int clrTol = 100) + { + Delete = delete; + Add = add; + ImageColorTolerance = clrTol; + } + public Color Delete { get; set; } = Color.Empty; + public Color Add { get; set; } = Color.Empty; + public int ImageColorTolerance + { + get => this._defaultImageColorTolerance; + set + { + if (value > 100 || value < 0) + throw new Exception("Invalid image color tolerance.\nValid range: 0 - 100"); + + this._defaultImageColorTolerance = value; + } + } + public bool Empty { get { return this == new ReplaceColor(); } } + } +} diff --git a/SwitchWinForms/Models/SWFBoxingOptions.cs b/SwitchWinForms/Models/SWFBoxingOptions.cs new file mode 100644 index 0000000..338e7d5 --- /dev/null +++ b/SwitchWinForms/Models/SWFBoxingOptions.cs @@ -0,0 +1,115 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace SwitchWinForms +{ + public class SWFBoxingOptions : TextUtil + { + private SWF_BOX_TYPE _type = SWF_BOX_TYPE.Frame; + private int _titleBarHeight = -1; + /// + /// To access the box it's easier with a name. + /// + public string Name { get; set; } = string.Empty; + /// + /// Required to be setup, as different types of objects work differently based on type. + /// + public SWF_BOX_TYPE Type + { + get { return _type; } + set { + _type = value; + if (_type != SWF_BOX_TYPE.FormBody) + _titleBarHeight = -1; + else if (_titleBarHeight == -1) + _titleBarHeight = 30; //default + } + } + /// + /// On mouse over or click, cursor changes. + /// + public SWFCursors Cursors { get; set; } = new SWFCursors(); + /// + /// Parent allows zindex. + /// + public Form Parent { get; set; } = null; + /// + /// Select corners to round off. Default None. + /// + public SWF_ARC_CORNERS RoundedCorners { get; set; } = SWF_ARC_CORNERS.None; + /// + /// Arc of the corners. 0 = Square. + /// + public int RoundedRadius { get; set; } = 0; + /// + /// Pixle size of the border for all 4 sides. + /// + public int BorderSize { get; set; } = 2; + /// + /// Padding for each size. Example: new Padding(5,2,2,2) + /// + public Padding Padding { get; set; } = new Padding(0); + /// + /// Get or Set the Location of the box. + /// + public Point Location { get; set; } = new Point(0, 0); + /// + /// Get or Set the Bounderies of the box. + /// + public Size Size { get; set; } = new Size(0, 0); + /// + /// Get or Set the Location and Bounderies of the box. + /// + public Rectangle Rectangle + { + get { return new Rectangle(Location, Size); } + set + { + Location = value == null ? Point.Empty : value.Location; + Size = value == null ? Size.Empty : value.Size; + } + } + /// + /// If there is a custom titlebar and if this this box type is
+ /// a SWF_BOX_TYPE.FormBody, auto-sizing requires to know how tall the titlebar is.
+ /// This setting will be ignored if this object type is not a SWF_BOX_TYPE.FormBody. + ///
+ public int TitleBarHeight + { + get { return _titleBarHeight; } + set + { + _titleBarHeight = value; + } + } + /// + /// Text location, value, font, etc.. + /// + public TextOptions TextSetup { get; set; } = new TextOptions(); + /// + /// Back ground color + /// + public Color BackColor { get; set; } = SystemColors.Control; + /// + /// Border color, if exists. + /// + public Color BorderColor { get; set; } = SystemColors.ActiveCaption; + /// + /// Setup shadowing color, opacity and depth + /// + public ShadowingSetup Shadowing { get; set; } = new ShadowingSetup(); + /// + /// If setup as a button, if has a shadow, when clicked, should button look like it's clicked on move down and mouse up + /// + public bool IsAnimatedButton { get; set; } = false; + /// + /// Internal tracking for mouse up and down, if animation on. + /// + internal bool ButtonClicked { get; set; } = false; + /// + /// Since everyting is painted on a form, mouse over icons and clicks need to ver reviewd based on zindex + /// + internal int ZIndex { get; set; } = 0; + } +} diff --git a/SwitchWinForms/Models/SWFCursors.cs b/SwitchWinForms/Models/SWFCursors.cs new file mode 100644 index 0000000..2ed54b0 --- /dev/null +++ b/SwitchWinForms/Models/SWFCursors.cs @@ -0,0 +1,23 @@ +using System.Windows.Forms; + +/* CursorConverter cConverter = new CursorConverter(); + Cursor hand = (Cursor)cConverter.ConvertFromString("Hand"); + string hhh = this.BoxingOptions.Parent.Cursor.cu.ToString(); + string iii =Cursor.Current.ToString(); +*/ +namespace SwitchWinForms +{ + public class SWFCursors + { + internal Cursor OnMove { get; set; } = Cursors.Default; + internal Cursor OnClick { get; set; } = Cursors.Default; + public SWFCursors(Cursor onMove = null, Cursor onClick = null) + { + if (onMove != null) + this.OnMove = onMove; + + if (onClick != null) + this.OnClick = onClick; + } + } +} diff --git a/SwitchWinForms/Models/SWFMessageEventArgs.cs b/SwitchWinForms/Models/SWFMessageEventArgs.cs new file mode 100644 index 0000000..bda0207 --- /dev/null +++ b/SwitchWinForms/Models/SWFMessageEventArgs.cs @@ -0,0 +1,23 @@ +using System; + +namespace SwitchWinForms +{ + public class SWFMessageEventArgs : EventArgs + { + private Exception _exception = null; + private string _message = string.Empty; + + public SWFMessageEventArgs(Exception exception) + { + this._exception = exception; + this._message = exception.Message; + } + + public SWFMessageEventArgs(string message) => + this._message = message; + + public Exception Exception { get { return this._exception; } } + public string Message { get { return this._message; } } + public bool Success { get { return this._exception == null; } } + } +} diff --git a/SwitchWinForms/Models/SWFTitlebarOptions.cs b/SwitchWinForms/Models/SWFTitlebarOptions.cs new file mode 100644 index 0000000..f3bd006 --- /dev/null +++ b/SwitchWinForms/Models/SWFTitlebarOptions.cs @@ -0,0 +1,266 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace SwitchWinForms +{ + public class SWFTitlebarOptions : TextUtil + { + private int _borderSize = 2; + /// + /// Name of Titlebar Option + /// + public string Name { get; set; } = string.Empty; + /// + /// Parent Form + /// + internal Form GetSetParent { get; set; } + /// + /// titlebar is always location 0,0 + /// + internal Point Location { get; set; } = new Point(0, 0); + /// + /// Size is updated by paint. + /// + internal Size Size { get; set; } = new Size(0, 0); + public Image Icon { get; set; } + /// + /// The primary form. + /// + public Form Parent { get { return GetSetParent; } } + /// + /// Get Location and Size of titlebar. + /// + public Rectangle Rectangle { get { return new Rectangle(this.Location, this.Size); } } + /// + /// Border size. + /// Valid alues (0-5). + /// Default: 2 + /// + public int BorderSize + { + get { return _borderSize; } + set + { + if (value < 0 || value > 5) + throw new Exception("BorderSize must be between 0-5"); + + _borderSize = value; + } + } + /// + /// Rounding corners specified. + /// + /// + /// Default: None + /// + public SWF_ARC_CORNERS RoundedCorners { get; set; } = SWF_ARC_CORNERS.None; + /// + /// Radius of the arc for the rounded corners. + /// Will be ignored if RoundedCorners is set to None. + /// Default: 0 + /// + public int RoundedRadius { get; set; } = 0; + /// + /// All text and buttons will be adjusted based on padding. + /// Usage: Padding(Left, Top, Right, Bottom) + /// Default: 0 + /// + public Padding Padding { get; set; } = new Padding(0); + /// + /// Height of titlebar. + /// Default: 30 + /// + public int Height { get; set; } = 30; + /// + /// Enable the Minimize, Maximum/Normal, and Close buttons for titlebar. + /// Usage: SWF_TITLE_BUTTON.Minimize | SWF_TITLE_BUTTON.Close + /// Default: SWF_TITLE_BUTTON.All + /// + public SWF_TITLE_BUTTON ButtonsEnabled { get; set; } = SWF_TITLE_BUTTON.All; + /// + /// Setup or use defaults for Minimized button. + /// + /// + /// Default:
+ /// BackColor = SystemColors.Window,
+ /// BorderColor = SystemColors.WindowFrame,
+ /// TextSetup = new TextOptions()
+ /// {
+ /// Color = SystemColors.WindowText,
+ /// Text = SWFUnicodeChars.MIN,
+ /// Font = Global.DefaultButtonFont,
+ /// HorizonalAlign = StringAlignment.Center,
+ /// VerticalAlign = StringAlignment.Center,
+ /// }
+ ///
+ public ButtonsState Minimized { get; set; } = new ButtonsState() + { + BackColor = SystemColors.Window, + BorderColor = SystemColors.WindowFrame, + TextSetup = new TextOptions() + { + Color = SystemColors.WindowText, + Text = SWFUnicodeChars.MIN, + Font = Global.DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }; + /// + /// Setup or use defaults for Maximize button. + /// + /// + /// Default:
+ /// BackColor = SystemColors.Window,
+ /// BorderColor = SystemColors.WindowFrame,
+ /// TextSetup = new TextOptions()
+ /// {
+ /// Color = SystemColors.WindowText,
+ /// Text = SWFUnicodeChars.MAX,
+ /// Font = Global.DefaultButtonFont,
+ /// HorizonalAlign = StringAlignment.Center,
+ /// VerticalAlign = StringAlignment.Center,
+ /// }
+ ///
+ public ButtonsState Maximize { get; set; } = new ButtonsState() + { + BackColor = SystemColors.Window, + BorderColor = SystemColors.WindowFrame, + TextSetup = new TextOptions() + { + Color = SystemColors.WindowText, + Text = SWFUnicodeChars.MAX, + Font = Global.DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }; + /// + /// Setup or use defaults for Normal button. + /// + /// + /// Default: + /// BackColor = SystemColors.Window,
+ /// BorderColor = SystemColors.WindowFrame,
+ /// TextSetup = new TextOptions()
+ /// {
+ /// Color = SystemColors.WindowText,
+ /// Text = SWFUnicodeChars.NORM,
+ /// Font = Global.DefaultButtonFont,
+ /// HorizonalAlign = StringAlignment.Center,
+ /// VerticalAlign = StringAlignment.Center,
+ /// }
+ ///
+ public ButtonsState Normal { get; set; } = new ButtonsState() + { + BackColor = SystemColors.Window, + BorderColor = SystemColors.WindowFrame, + TextSetup = new TextOptions() + { + Color = SystemColors.WindowText, + Text = SWFUnicodeChars.NORM, + Font = Global.DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }; + /// + /// Setup or use defaults for Close button. + /// + /// + /// Default: + /// BackColor = SystemColors.Window,
+ /// BorderColor = SystemColors.WindowFrame,
+ /// TextSetup = new TextOptions()
+ /// {
+ /// Color = SystemColors.WindowText,
+ /// Text = Global.GetUnicode(SWF_UNICODE_BUTTONS.CLOSE),
+ /// Font = Global.DefaultButtonFont,
+ /// HorizonalAlign = StringAlignment.Center,
+ /// VerticalAlign = StringAlignment.Center,
+ /// }
+ ///
+ public ButtonsState Close { get; set; } = new ButtonsState() + { + BackColor = SystemColors.Window, + BorderColor = SystemColors.WindowFrame, + TextSetup = new TextOptions() + { + Color = SystemColors.WindowText, + Text = SWFUnicodeChars.CLOSE, + Font = Global.DefaultButtonFont, + HorizonalAlign = StringAlignment.Center, + VerticalAlign = StringAlignment.Center, + } + }; + /// + /// Titlebar caption information + /// + public TextOptions TextSetup { get; set; } = new TextOptions(); + /// + /// Titlebar background color. + /// Default: SystemColors.GradientActiveCaption + /// + public Color BackColor { get; set; } = SystemColors.GradientActiveCaption; + /// + /// Titlebar border color. + /// Default: SystemColors.ActiveBorder + /// + public Color BorderColor { get; set; } = SystemColors.ActiveBorder; + /// + /// All button setup shown on the title bar. This includes, Minimum, Normal/Maximum, Close buttons. + /// + public class ButtonsState : TextUtil + { + /// + /// Border size around buttons.
+ /// Default: 1 + ///
+ public int BorderSize { get; set; } = 1; + /// + /// Seperations between buttons. + /// Default: 2 + /// + public int MarginRight { get; set; } = 2; + /// + /// Buttons border color
+ /// Default: SystemColors.ActiveBorder + ///
+ public Color BorderColor { get; set; } = SystemColors.ActiveBorder; + /// + /// Button Background Color
+ /// Default: SystemColors.ActiveCaption + ///
+ public Color BackColor { get; set; } = SystemColors.ActiveCaption; + /// + /// Button's text configuration + /// + public TextOptions TextSetup { get; set; } = new TextOptions(); + /// + /// Button's padding + /// Default: 0 + /// + public Padding Padding { get; set; } = new Padding(0); + /// + /// Which corners to be rounded for this button.
+ /// Default: None + ///
+ public SWF_ARC_CORNERS RoundedCorners { get; set; } = SWF_ARC_CORNERS.None; + /// + /// Radius of the arc for each corner.
+ /// Default: 0
+ /// Suggest: 2-10 + ///
+ public int RoundedRadius { get; set; } = 0; + /// + /// Is default ButtonsState class without any settings. + /// + public bool Empty { get { return this == new ButtonsState(); } } + } + /// + /// Is default SWFTitlebarOptions class without any settings. + /// + public bool Empty { get { return this == new SWFTitlebarOptions(); } } + } +} diff --git a/SwitchWinForms/Models/SWFUnicodeChars.cs b/SwitchWinForms/Models/SWFUnicodeChars.cs new file mode 100644 index 0000000..fda3a11 --- /dev/null +++ b/SwitchWinForms/Models/SWFUnicodeChars.cs @@ -0,0 +1,80 @@ +using System.Globalization; + +namespace SwitchWinForms +{ + /// + /// Unicode for special characters. + /// + public class SWFUnicodeChars + { + private const int min = 10134; + private const int max = 11026; + private const int norm = 11027; + private const int close = 10062; //10060-X; + private const int txtCursor = 10626; //10070-❖ 10626-⦂ + private int ucode = 0; + /// + /// You can pass any unicode number and use + /// .ToString() to get the local string value. + /// + /// + public SWFUnicodeChars(int ucode) => + this.ucode = ucode; + /// + /// Internal method to convert unicode to current culture string value. + /// + /// + /// + private static string MakeString(int unicode) + { + return ((char)unicode) + .ToString(new CultureInfo(CultureInfo.CurrentCulture.Name)); + } + /// + /// Returns the default value for Minimum button text. + /// + public static string MIN + { + get { return MakeString(min); } + } + /// + /// Returns the default value for Text Cursor text. + /// + public static string TXT_CURSOR + { + get { return MakeString(txtCursor); } + } + /// + /// Returns the default value for Maximum button text. + /// + public static string MAX + { + get { return MakeString(max); } + } + /// + /// Returns the default value for Normal button text. + /// + public static string NORM + { + get { return MakeString(norm); } + } + /// + /// Returns the default value for Close button text. + /// + public static string CLOSE + { + get { return MakeString(close); } + } + /// + /// Converts the unicode value passed in to the curent culture string value. + /// + public override string ToString() + { + return MakeString(this.ucode); + } + /// + /// Has class been called. + /// + public bool Empty { get { return this.ucode == 0; } } + } +} diff --git a/SwitchWinForms/Models/ShadowingSetup.cs b/SwitchWinForms/Models/ShadowingSetup.cs new file mode 100644 index 0000000..0c58ec1 --- /dev/null +++ b/SwitchWinForms/Models/ShadowingSetup.cs @@ -0,0 +1,14 @@ + +using System.Drawing; + +namespace SwitchWinForms +{ + public class ShadowingSetup + { + public Color Color { get; set; } = Color.Black; + public SWF_TRANSPARENT_PERCENTAGE Visibilty { get; set; } = SWF_TRANSPARENT_PERCENTAGE.Empty; + public int Depth { get; set; } = 5; + internal int getVisibilty { get { return (int)Visibilty; } } + public bool Empty { get { return this == new ShadowingSetup(); } } + } +} diff --git a/SwitchWinForms/Models/TextUtil.cs b/SwitchWinForms/Models/TextUtil.cs new file mode 100644 index 0000000..8da2330 --- /dev/null +++ b/SwitchWinForms/Models/TextUtil.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace SwitchWinForms +{ + public abstract class TextUtil + { + public class TextOptions + { + internal int TextCursor { get; set; } = 0; + public string Text { get; set; } = string.Empty; + /// + /// Only used for SWF_BOX_TYPE.TextBox + /// + public string ValidInputExpression { get; set; } = null; + public Image BackgroundImage { get; set; } = null; + public SWF_BG_IMG_LAYOUT BackgroundImageLayout { get; set; } = SWF_BG_IMG_LAYOUT.Stretch; + public List ReplaceImageColor { get; set; } = new List() { }; + public Font Font { get; set; } = Global.DefaultFont; + public Color Color { get; set; } = Global.DefaultFontColor; + public StringAlignment VerticalAlign { get; set; } = StringAlignment.Near; + public StringAlignment HorizonalAlign { get; set; } = StringAlignment.Near; + public bool Empty { get { return this == new TextOptions(); } } + /// + /// Deprecated Method + /// + /// + [Obsolete("IsEmpty() is deprecated, please use 'Empty' property instead.")] + public bool IsEmpty() { + return Empty; + } + } + } +} \ No newline at end of file diff --git a/SwitchWinForms/Properties/AssemblyInfo.cs b/SwitchWinForms/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fe7aa53 --- /dev/null +++ b/SwitchWinForms/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SwitchWinForms")] +[assembly: AssemblyDescription("Create new forms with flare or use it for certain components.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("chizl.com")] +[assembly: AssemblyProduct("SwitchWinForms")] +[assembly: AssemblyCopyright("copyright (c) chizl.com 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7c49620c-5f61-4a4e-a6ca-166b18e4daa6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.1.0.0")] +[assembly: AssemblyFileVersion("2.1.0.317")] +[assembly: AssemblyInformationalVersion("2.1.0.0")] \ No newline at end of file diff --git a/SwitchWinForms/Static/Constants.cs b/SwitchWinForms/Static/Constants.cs new file mode 100644 index 0000000..24bf991 --- /dev/null +++ b/SwitchWinForms/Static/Constants.cs @@ -0,0 +1,97 @@ +namespace SwitchWinForms +{ + public enum SWF_BG_IMG_LAYOUT + { + Normal, + Center, + Stretch, + Tile + } + public enum SWF_BOX_TYPE + { + Empty, + Titlebar, + FormBody, + Button, + Frame, + Label, + TextBox + } + public enum SWF_ARC_CORNERS + { + None = 0, + TopLeft = 1, + TopRight = 2, + BottomLeft = 4, + BottomRight = 8, + Left = TopLeft | BottomLeft, + Right = TopRight | BottomRight, + Top = TopLeft | TopRight, + Bottom = BottomLeft | BottomRight, + All = TopLeft | TopRight | BottomLeft | BottomRight, + } + public enum SWF_TRANSPARENT_PERCENTAGE + { + Empty = 0, + Five = 13, + Ten = 26, + Fifteen = 38, + Twenty = 51, + TwentyFive = 64, + Thirty = 77, + ThirtyFive = 89, + Forty = 102, + FortyFive = 115, + Fifty = 127, + FiftyFive = 140, + Sixty = 153, + SixtyFive = 166, + Seventy = 179, + SeventyFive = 191, + Eighty = 204, + EightyFive = 217, + Ninty = 230, + NintyFive = 242, + Hundered = 255 + } + public enum SWF_TITLE_BUTTON + { + Minimize = 1, + Maximize_Normal = 2, + Close = 4, + All = Minimize | Maximize_Normal | Close + } + internal enum SWF_RESIZEABLE + { + None = 0, + Yes = 1, + No = 2 + } + internal enum SWF_HITTEST + { + HT_ERROR = -2, + HT_TRANSPARENT = -1, + HT_NOWHERE = 0, + HT_CLIENT = 1, + HT_CAPTION = 2, + HT_SYSMENU = 3, + HT_GROWBOX = 4, + HT_MENU = 5, + HT_HSCROLL = 6, + HT_VSCROLL = 7, + HT_MINBUTTON = 8, + HT_MAXBUTTON = 9, + HT_LEFT = 10, + HT_RIGHT = 11, + HT_TOP = 12, + HT_TOPLEFT = 13, + HT_TOPRIGHT = 14, + HT_BOTTOM = 15, + HT_BOTTOMLEFT = 16, + HT_BOTTOMRIGHT = 17, + HT_BORDER = 18, + HT_OBJECT = 19, + HT_CLOSE = 20, + HT_HELP = 21 + } +} \ No newline at end of file diff --git a/SwitchWinForms/Static/Global.cs b/SwitchWinForms/Static/Global.cs new file mode 100644 index 0000000..aac1890 --- /dev/null +++ b/SwitchWinForms/Static/Global.cs @@ -0,0 +1,487 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace SwitchWinForms +{ + internal class Global + { + [DllImport("user32.dll", CharSet = CharSet.Auto)] + extern static bool DestroyIcon(IntPtr handle); + + private const string DefaultTextFont = "Courier New"; + internal static List IgnoreKeys { get; } = new List() { Keys.Right, Keys.Left, Keys.Home, Keys.End, + Keys.Enter, Keys.Return, Keys.Back, Keys.Delete, + Keys.Escape, Keys.Shift, Keys.ShiftKey, Keys.Capital, + Keys.Alt, Keys.Control, Keys.ControlKey, + Keys.CapsLock, Keys.Snapshot, Keys.Print, Keys.PrintScreen, + Keys.Menu, Keys.Apps, Keys.Up, Keys.Down, Keys.PageDown, + Keys.PageUp, Keys.VolumeDown, + Keys.VolumeUp, Keys.VolumeMute }; + internal static Dictionary ConvertKey { get; } = new Dictionary() + { + { Keys.Enter, '\n' }, + { Keys.Tab, '\t' }, + { Keys.OemPeriod, '.' }, + { Keys.Decimal, '.' }, + { Keys.NumPad1, '1' }, + { Keys.NumPad2, '2' }, + { Keys.NumPad3, '3' }, + { Keys.NumPad4, '4' }, + { Keys.NumPad5, '5' }, + { Keys.NumPad6, '6' }, + { Keys.NumPad7, '7' }, + { Keys.NumPad8, '8' }, + { Keys.NumPad9, '9' }, + { Keys.NumPad0, '0' }, + { Keys.D1, '1' }, + { Keys.D2, '2' }, + { Keys.D3, '3' }, + { Keys.D4, '4' }, + { Keys.D5, '5' }, + { Keys.D6, '6' }, + { Keys.D7, '7' }, + { Keys.D8, '8' }, + { Keys.D9, '9' }, + { Keys.D0, '0' }, + }; + internal static Font DefaultFont { get; } = new Font("Verdana", 12, FontStyle.Regular, GraphicsUnit.Pixel); + internal static Font DefaultButtonFont { get; } = new Font("Verdana", 12, FontStyle.Regular, GraphicsUnit.Pixel); + internal static Color DefaultFontColor { get; } = Color.Black; + internal static bool IsInBounds(Form frm, Point pt, Rectangle rect, Cursor cursorType = null) + { + bool retVal = false; + + if (pt.X >= rect.Left && + pt.Y >= rect.Top && + pt.X <= rect.Left + rect.Width && + pt.Y <= rect.Top + rect.Height) + { + if (frm != null && cursorType != null) + frm.Cursor = cursorType; + + retVal = true; + } + + return retVal; + } + internal static bool MouseIsClose(Point pt, Rectangle rect) + { + int count = 0; + int closeBy = 2; + bool[] hasBool = new bool[4]; + + hasBool[0] = pt.X < rect.X && (rect.X - pt.X <= closeBy) ? true : false; + hasBool[1] = pt.Y < rect.Y && (rect.Y - pt.Y <= closeBy) ? true : false; + hasBool[2] = pt.X > (rect.X + rect.Width) && (pt.X - (rect.X + rect.Width) <= closeBy) ? true : false; + hasBool[3] = pt.Y > (rect.Y + rect.Height) && (pt.Y - (rect.Y + rect.Height) <= closeBy) ? true : false; + + for(int i= 0; i < 4; i++) + { + if (hasBool[i]) + count++; + } + + return count >= 1; + } + internal static BoxInfo CreateBox(Graphics g, BoxInfo boxInfo) + { + int buffer = 1; + Size maxSize = boxInfo.Rectangle.Size; + Rectangle innerBoxRect = boxInfo.Rectangle; + + if (innerBoxRect.Width < 1 || innerBoxRect.Height < 1) + return boxInfo; + + //create the shadow first. + if (boxInfo.Shadowing != null && + boxInfo.Shadowing.Visibilty != SWF_TRANSPARENT_PERCENTAGE.Empty && + !boxInfo.ButtonClicked) + { + Color shaColor = Color.FromArgb( + boxInfo.Shadowing.getVisibilty, + boxInfo.Shadowing.Color.R, + boxInfo.Shadowing.Color.G, + boxInfo.Shadowing.Color.B); + + Brush shadowBrush = new SolidBrush(shaColor); + + Rectangle shadowBox = new Rectangle( + boxInfo.Rectangle.X + boxInfo.Shadowing.Depth, + boxInfo.Rectangle.Y + boxInfo.Shadowing.Depth, + boxInfo.Rectangle.Width, + boxInfo.Rectangle.Height); + + FillRoundedRectangle(g, shadowBrush, boxInfo, shadowBox, true); + } + + //&& !boxInfo.BackgroundImageModified + if (boxInfo.BackgroundImage != null ) + { + Image newImg = boxInfo.BackgroundImage; + if (boxInfo.ReplaceImageColor.Count > 0) + { + //we dont want to call MakeTransparent each roll, this + //will cause jumping excuted mutliple times. + foreach (ReplaceColor rc in boxInfo.ReplaceImageColor) + newImg = MakeTransparent(newImg, rc, rc.ImageColorTolerance); + + boxInfo.ReplaceImageColor = new List(); + //This makes it perminate until next restart. + + boxInfo.BackgroundImage = newImg; + boxInfo.BackgroundImageModified = true; + } + + if (boxInfo.BackgroundImageLayout != SWF_BG_IMG_LAYOUT.Tile && + (boxInfo.BackgroundImage.Width > boxInfo.Rectangle.Width || + boxInfo.BackgroundImage.Height > boxInfo.Rectangle.Height)) + { + newImg = ResizeBitmap(new Bitmap(newImg), boxInfo.Rectangle.Size); + boxInfo.BackgroundImage = newImg; + boxInfo.BackgroundImageModified = true; + } + } + + //create the background. + SolidBrush bgColor = new SolidBrush(boxInfo.BackColor); + FillRoundedRectangle(g, bgColor, boxInfo, boxInfo.Rectangle, false); + + //if border, then draw border ontop of background. + if (boxInfo.BorderSize > 0) + { + for (int i = 0; i < boxInfo.BorderSize; i++) + { + Rectangle borderRect = new Rectangle() + { + Location = new Point(boxInfo.Rectangle.Location.X + i, boxInfo.Rectangle.Location.Y + i), + Size = new Size((maxSize.Width - (i * 2)) - buffer, (maxSize.Height - (i * 2)) - buffer) + }; + + //create the border + Pen titlePen = new Pen(boxInfo.BorderColor, boxInfo.BorderSize); + DrawRoundedRectangle(g, titlePen, boxInfo, borderRect); + + innerBoxRect = borderRect; + } + } + + if (!string.IsNullOrWhiteSpace(boxInfo.Text)) + { + StringFormat stringFormat = new StringFormat() + { + Alignment = boxInfo.HAlign, + LineAlignment = boxInfo.VAlign + }; + + innerBoxRect = new Rectangle(innerBoxRect.Left + boxInfo.Padding.Left, + innerBoxRect.Top + boxInfo.Padding.Top, + innerBoxRect.Width - boxInfo.Padding.Right, + innerBoxRect.Height - boxInfo.Padding.Bottom); + + if (boxInfo.Type == SWF_BOX_TYPE.Titlebar && boxInfo.Icon != null) + innerBoxRect.Location = new Point((innerBoxRect.X * 2) + innerBoxRect.Height + (boxInfo.Padding.Left * 2), innerBoxRect.Y); + else if (boxInfo.Type == SWF_BOX_TYPE.Titlebar) + innerBoxRect.Location = new Point((innerBoxRect.X * 2) + (boxInfo.Padding.Left * 2), innerBoxRect.Y); + + Font ft = boxInfo.Font; + if (boxInfo.Type == SWF_BOX_TYPE.TextBox && boxInfo.InputStart) + { + //We have to change the font to "Courier New", since I"m overlaying so I can add the * at the cursor spot. + //An asterisk can be a differnt size than a letter for example if not using a squared font letter. + ft = new Font(DefaultTextFont, boxInfo.Font.Size, boxInfo.Font.Style, GraphicsUnit.Pixel); + int cursor = boxInfo.TextCursor; + string text; + + if (cursor > 0) + text = boxInfo.Text.Substring(0, cursor) + "*"; + else + text = "*"; + + g.DrawString(text, ft, new SolidBrush(Color.Gray), innerBoxRect, stringFormat); + } + + g.DrawString(boxInfo.Text, ft, new SolidBrush(boxInfo.ForeColor), innerBoxRect, stringFormat); + } + + return boxInfo; + } + internal static bool IsValidGraphic(Graphics g) + { + bool retVal = true; + + try + { + if (!g.IsClipEmpty) + retVal = false; + } + catch + { + retVal = false; + } + + return retVal; + } + internal static Image GetImage(string path) + { + if (!File.Exists(path)) + throw new IOException($"File not found.\n${path}"); + + Image retVal; + FileInfo fi = new FileInfo(path); + try + { + switch (fi.Extension.ToLower()) + { + case ".exe": + case ".ico": + retVal = (Image)GetEXEImage(path); + break; + default: + retVal = Image.FromFile(path); + break; + } + } + catch + { + throw new IOException("Invalid filetype."); + } + + return retVal; + } + internal static Icon GetIcon(string path) + { + if (!File.Exists(path)) + throw new IOException($"File not found.\n${path}"); + + FileInfo fi = new FileInfo(path); + Icon retVal; + try + { + switch (fi.Extension.ToLower()) + { + case ".exe": + case ".ico": + retVal = (Icon)GetEXEImage(path); + break; + default: + Bitmap bmp = (Bitmap)Image.FromFile(path); + if (bmp.Width > 128 || bmp.Height > 128) //max icon size: 128x128 .ico + bmp = ResizeBitmap(bmp, new Size(128, 128)); + IntPtr Hicon = bmp.GetHicon(); + retVal = (Icon)Icon.FromHandle(Hicon).Clone(); + //Required cleanup or creates memory leak. + DestroyIcon(Hicon); + break; + } + } + catch + { + throw new IOException("Invalid filetype."); + } + + return retVal; + } + private static Bitmap ResizeBitmap(Bitmap img, Size sz) + { + float width = sz.Width; + float height = sz.Height; + var brush = new SolidBrush(Color.Transparent); + float scale = Math.Min(width / ((float)img.Width), height / ((float)img.Height)); + var bmp = new Bitmap(sz.Width, sz.Height); + var graph = Graphics.FromImage(bmp); + var scaleWidth = (int)(img.Width * scale); + var scaleHeight = (int)(img.Height * scale); + RectangleF rec = new RectangleF(((int)width - scaleWidth) / 2, ((int)height - scaleHeight) / 2, scaleWidth, scaleHeight); + graph.FillRectangle(brush, rec); + graph.DrawImage(img, rec); + + return bmp; + } + internal static void DrawRoundedRectangle(Graphics graphics, Pen pen, BoxInfo boxInfo, Rectangle bounds) + { + if (graphics == null) + throw new ArgumentNullException("graphics"); + if (pen == null) + throw new ArgumentNullException("pen"); + + using (GraphicsPath path = RoundedRect(bounds, boxInfo)) + { + graphics.DrawPath(pen, path); + } + } + internal static void FillRoundedRectangle(Graphics graphics, Brush brush, BoxInfo boxInfo, Rectangle bounds, bool isShadow = false) + { + if (graphics == null) + throw new ArgumentNullException("graphics"); + if (brush == null) + throw new ArgumentNullException("brush"); + + using (GraphicsPath path = RoundedRect(bounds, boxInfo)) + { + graphics.FillPath(brush, path); + if (boxInfo.BackgroundImage != null && !isShadow) + { + if (boxInfo.BackgroundImageLayout == SWF_BG_IMG_LAYOUT.Normal) + graphics.DrawImage(boxInfo.BackgroundImage, bounds.Location); + //if (boxInfo.BackgroundImageLayout == SWF_BG_IMG_LAYOUT.Tile) + else + { + Brush gbrush = new TextureBrush(boxInfo.BackgroundImage); + graphics.FillPath(gbrush, path); + } + /*else if (boxInfo.BackgroundImageLayout == SWF_BG_IMG_LAYOUT.Stretch) + { + graphics.DrawImage(boxInfo.BackgroundImage, bounds.Location); + } + else if (boxInfo.BackgroundImageLayout == SWF_BG_IMG_LAYOUT.Center) + { + graphics.DrawImage(boxInfo.BackgroundImage, bounds.Location); + }*/ + } + } + } + internal static GraphicsPath PointsToGraphicsPath(List points) + { + GraphicsPath gp = new GraphicsPath(); + gp.AddLines(points.ToArray()); + return gp; + } + internal static List GraphicsPathToPoints(GraphicsPath gp) + { + return gp.PathPoints.ToList(); + } + internal static bool DeleteFile(string path) + { + bool retVal = true; + + try + { + if (File.Exists(path)) + File.Delete(path); + } + catch + { + retVal = false; + } + + return retVal; + } + private static GraphicsPath RoundedRect(Rectangle bounds, BoxInfo boxInfo) + { + int radiusTopLeft = 0; + int radiusTopRight = 0; + int radiusBottomRight = 0; + int radiusBottomLeft = 0; + + if ((boxInfo.RoundedCorners & SWF_ARC_CORNERS.TopLeft) > 0) + radiusTopLeft = boxInfo.RoundedRadius; + if ((boxInfo.RoundedCorners & SWF_ARC_CORNERS.TopRight) > 0) + radiusTopRight = boxInfo.RoundedRadius; + if ((boxInfo.RoundedCorners & SWF_ARC_CORNERS.BottomRight) > 0) + radiusBottomRight = boxInfo.RoundedRadius; + if ((boxInfo.RoundedCorners & SWF_ARC_CORNERS.BottomLeft) > 0) + radiusBottomLeft = boxInfo.RoundedRadius; + + var size = new Size(radiusTopLeft << 1, radiusTopLeft << 1); + var arc = new Rectangle(bounds.Location, size); + var path = new GraphicsPath(); + + // top left arc + if (radiusTopLeft == 0) + path.AddLine(arc.Location, arc.Location); + else + path.AddArc(arc, 180, 90); + + // top right arc + if (radiusTopRight != radiusTopLeft) + { + size = new Size(radiusTopRight << 1, radiusTopRight << 1); + arc.Size = size; + } + + arc.X = bounds.Right - size.Width; + if (radiusTopRight == 0) + path.AddLine(arc.Location, arc.Location); + else + path.AddArc(arc, 270, 90); + + // bottom right arc + if (radiusTopRight != radiusBottomRight) + { + size = new Size(radiusBottomRight << 1, radiusBottomRight << 1); + arc.X = bounds.Right - size.Width; + arc.Size = size; + } + + arc.Y = bounds.Bottom - size.Height; + if (radiusBottomRight == 0) + path.AddLine(arc.Location, arc.Location); + else + path.AddArc(arc, 0, 90); + + // bottom left arc + if (radiusBottomRight != radiusBottomLeft) + { + arc.Size = new Size(radiusBottomLeft << 1, radiusBottomLeft << 1); + arc.Y = bounds.Bottom - arc.Height; + } + + arc.X = bounds.Left; + if (radiusBottomLeft == 0) + path.AddLine(arc.Location, arc.Location); + else + path.AddArc(arc, 90, 90); + + path.CloseFigure(); + return path; + } + private static object GetEXEImage(string path) + { + object retVal; + string typeofName = typeof(T).Name.ToLower(); + try + { + Icon IEIcon = Icon.ExtractAssociatedIcon(path); + if (typeofName == "icon") + retVal = (object)IEIcon; + else + retVal = IEIcon.ToBitmap(); + } + catch + { + retVal = null; + } + + return retVal; + } + private static Image MakeTransparent(Image image, ReplaceColor color, int tolerance) + { + return MakeTransparent(new Bitmap(image), color, tolerance); + } + private static Bitmap MakeTransparent(Bitmap bitmap, ReplaceColor color, int tolerance) + { + Bitmap transparentImage = new Bitmap(bitmap); + + for (int i = transparentImage.Size.Width - 1; i >= 0; i--) + { + for (int j = transparentImage.Size.Height - 1; j >= 0; j--) + { + var currentColor = transparentImage.GetPixel(i, j); + if (Math.Abs(color.Delete.R - currentColor.R) < tolerance && + Math.Abs(color.Delete.G - currentColor.G) < tolerance && + Math.Abs(color.Delete.B - currentColor.B) < tolerance) + transparentImage.SetPixel(i, j, color.Add); + } + } + + //transparentImage.MakeTransparent(color.Delete); + return transparentImage; + } + } +} diff --git a/SwitchWinForms/SwitchWinForms.csproj b/SwitchWinForms/SwitchWinForms.csproj new file mode 100644 index 0000000..ba6a0c2 --- /dev/null +++ b/SwitchWinForms/SwitchWinForms.csproj @@ -0,0 +1,68 @@ + + + + + Debug + AnyCPU + {7C49620C-5F61-4A4E-A6CA-166B18E4DAA6} + Library + Properties + SwitchWinForms + SwitchWinForms + v4.7.2 + 512 + true + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + C:\Code\~VBS\setVersion.vbs "$(ProjectDir)" + + \ No newline at end of file