DotNet 4.8.1 build of DotNetBar

This commit is contained in:
2025-02-07 10:35:23 -05:00
parent 33439b63a0
commit 6b0a5d60f4
2609 changed files with 989814 additions and 7 deletions

View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{57C1D8BE-55D4-4403-BC65-FC59D8148504}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DevComponents.DotNetBar.Keyboard</RootNamespace>
<AssemblyName>DevComponents.DotNetBar.Keyboard</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\DevComponents.DotNetBar.Keyboard.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release2005|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisLogFile>bin\Release\DevComponents.DotNetBar.Keyboard.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<DocumentationFile>bin\Release\DevComponents.DotNetBar.Keyboard.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseTrial2005|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;TRIAL</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisLogFile>bin\Release\DevComponents.DotNetBar.Keyboard.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
<DocumentationFile>bin\Release\DevComponents.DotNetBar.Keyboard.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>dotnetbar.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Dpi.cs" />
<Compile Include="Keyboard.cs" />
<Compile Include="PopupVirtualKeyboard.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderer.cs" />
<Compile Include="TouchKeyboard.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Touch\TouchHandler.cs" />
<Compile Include="Touch\WinApi.cs" />
<Compile Include="KeyboardControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="VirtualKeyboardColors.cs" />
<Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
</ItemGroup>
<ItemGroup>
<None Include="dotnetbar.snk" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="KeyboardControl.ico" />
<EmbeddedResource Include="TouchKeyboard.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
namespace DevComponents.DotNetBar.Keyboard
{
/// <summary>
/// Provides High DPI support for DotNetBar controls.
/// </summary>
public static class Dpi
{
private static SizeF _Factor = new SizeF(1f, 1f);
private static bool _UseFactor = false;
static Dpi()
{
Debug.WriteLine("Static constructor");
}
public static SizeF Factor
{
get { return _Factor; }
}
public static Size Size(Size size)
{
if (!_UseFactor) return size;
size.Width = (int)(size.Width * _Factor.Width);
size.Height = (int)(size.Height * _Factor.Height);
return size;
}
public static Rectangle Size(Rectangle r)
{
if (!_UseFactor) return r;
r.Width = (int)(r.Width * _Factor.Width);
r.Height = (int)(r.Height * _Factor.Height);
return r;
}
public static Point Size(Point p)
{
if (!_UseFactor) return p;
p.X = (int)(p.X * _Factor.Width);
p.Y = (int)(p.Y * _Factor.Height);
return p;
}
//public static DevComponents.DotNetBar.Padding Size(DevComponents.DotNetBar.Padding padding)
//{
// if (!_UseFactor) return padding;
// return new Padding((int)(padding.Left * _Factor.Width), (int)(padding.Right * _Factor.Width), (int)(padding.Top * _Factor.Height), (int)(padding.Bottom * _Factor.Height));
//}
public static int DescaleWidth(int width)
{
if (!_UseFactor) return width;
return (int)(width / _Factor.Width);
}
public static int DescaleHeight(int height)
{
if (!_UseFactor) return height;
return (int)(height / _Factor.Height);
}
internal static System.Drawing.Size Descale(System.Drawing.Size size)
{
if (!_UseFactor) return size;
size.Width = (int)(size.Width / _Factor.Width);
size.Height = (int)(size.Height / _Factor.Height);
return size;
}
public static int Width(int width)
{
if (!_UseFactor) return width;
return (int)(width * _Factor.Width);
}
public static int Height(int height)
{
if (!_UseFactor) return height;
return (int)(height * _Factor.Height);
}
public static float Height(float height)
{
if (!_UseFactor) return height;
return (height * _Factor.Height);
}
private static int _CaptionVerticalPadding = 10;
public static int CaptionVerticalPadding
{
get
{
if (!_UseFactor) return 0;
return _CaptionVerticalPadding;
}
}
public static void SetScaling(SizeF factor)
{
if(factor==_Factor) return;
if (factor.Width == 1f && factor.Height == 1f)
{
_UseFactor = false;
_Factor = factor;
}
else
{
_UseFactor = true;
_Factor = factor;
}
UpdateStaticSizes();
}
private static void UpdateStaticSizes()
{
Width1 = Dpi.Width(1);
Width2 = Dpi.Width(2);
Width3 = Dpi.Width(3);
Width4 = Dpi.Width(4);
Width5 = Dpi.Width(5);
Width6 = Dpi.Width(6);
Width7 = Dpi.Width(7);
Width8 = Dpi.Width(8);
Width9 = Dpi.Width(9);
Width10 = Dpi.Width(10);
Width11 = Dpi.Width(11);
Width12 = Dpi.Width(12);
Width13 = Dpi.Width(13);
Width14 = Dpi.Width(14);
Width15 = Dpi.Width(15);
Width16 = Dpi.Width(16);
Width17 = Dpi.Width(17);
Width18 = Dpi.Width(18);
Width22 = Dpi.Width(22);
Width24 = Dpi.Width(24);
Width25 = Dpi.Width(25);
Width28 = Dpi.Width(28);
Width32 = Dpi.Width(32);
Width34 = Dpi.Width(34);
Height1 = Dpi.Height(1);
Height2 = Dpi.Height(2);
Height3 = Dpi.Height(3);
Height4 = Dpi.Height(4);
Height5 = Dpi.Height(5);
Height6 = Dpi.Height(6);
Height7 = Dpi.Height(7);
Height8 = Dpi.Height(8);
Height9 = Dpi.Height(9);
Height10 = Dpi.Height(10);
Height11 = Dpi.Height(11);
Height12 = Dpi.Height(12);
Height13 = Dpi.Height(13);
Height14 = Dpi.Height(14);
Height15 = Dpi.Height(15);
Height16 = Dpi.Height(16);
Height17 = Dpi.Height(17);
Height18 = Dpi.Height(18);
Height20 = Dpi.Height(20);
Height22 = Dpi.Height(22);
Height23 = Dpi.Height(23);
Height24 = Dpi.Height(24);
Height25 = Dpi.Height(25);
Height28 = Dpi.Height(28);
Height32 = Dpi.Height(32);
}
#region Static Sizes
public static int Width1 = 1;
public static int Width2 = 2;
public static int Width3 = 3;
public static int Width5 = 5;
public static int Width4 = 4;
public static int Width6 = 6;
public static int Width7 = 7;
public static int Width8 = 8;
public static int Width9 = 9;
public static int Width10 = 10;
public static int Width11 = 11;
public static int Width12 = 12;
public static int Width13 = 13;
public static int Width14 = 14;
public static int Width15 = 15;
public static int Width16 = 16;
public static int Width17 = 17;
public static int Width18 = 18;
public static int Width22 = 22;
public static int Width24 = 24;
public static int Width25 = 25;
public static int Width28 = 28;
public static int Width32 = 32;
public static int Width34 = 34;
public static int Height1 = 1;
public static int Height2 = 2;
public static int Height3 = 3;
public static int Height4 = 4;
public static int Height5 = 5;
public static int Height6 = 6;
public static int Height7 = 7;
public static int Height8 = 8;
public static int Height9 = 9;
public static int Height10 = 10;
public static int Height11 = 11;
public static int Height12 = 12;
public static int Height13 = 13;
public static int Height14 = 14;
public static int Height15 = 15;
public static int Height16 = 16;
public static int Height17 = 17;
public static int Height18 = 18;
public static int Height20 = 20;
public static int Height22 = 22;
public static int Height23 = 23;
public static int Height24 = 24;
public static int Height25 = 25;
public static int Height28 = 28;
public static int Height32 = 32;
#endregion
}
}

View File

@@ -0,0 +1,778 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Collections.ObjectModel;
namespace DevComponents.DotNetBar.Keyboard
{
// A Keyboard is defined by one or more KeyboardLayout objects.
// A KeyboardLayout is a layout of certain Key objects.
// A Key object represents all the data that a virtual key needs (caption, actual key-information to send
// to the attached control, hint, bounds, style, etc).
// Because in this version of the VirtualKeyboard control the user cannot design new layouts for the keyboard,
// we will not publicly expose the model classes of the keyboard.
/// <summary>
/// Holds information about a single virtual keyboard Key.
/// </summary>
public class Key
{
private string _Caption;
/// <summary>
/// Gets the caption on the key.
/// </summary>
public string Caption
{
get { return _Caption; }
}
private string _Info;
/// <summary>
/// Gets the actual key-information that is sent to the attached control. The format of this information
/// must confirm to the description for the SendKeys.Send function. For more details, see:
/// http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
/// </summary>
public string Info
{
get { return _Info; }
}
private Rectangle _Bounds;
/// <summary>
/// Gets the bounds of the key.
/// </summary>
public Rectangle Bounds
{
get { return _Bounds; }
internal set { _Bounds = value; }
}
private KeyStyle _Style;
/// <summary>
/// Gets a value representing the way the key looks on the virtual keyboard. A key might look normal,
/// lighter, darker or with a pressed effect.
/// </summary>
public KeyStyle Style
{
get { return _Style; }
}
private int _ChangeToLayout;
/// <summary>
/// Gets the index of the layout to change to, if this key is pressed. A positive value represents a new layout.
/// KeyboardLayout.NoChange and KeyboardLayout.PreviousLayout constants can also be used with special meaning.
/// </summary>
/// <remarks>
/// If this is a positive integer ( >= 0 ), it represents the index of the layout to switch to when this key
/// is pressed. In this case, the keyboard does not send any key information to the attached control (the Info
/// field is ignored), only changes the layout.
///
/// If this is KeyboardLayout.NoChange the keyboard will send the info to the attached control.
///
/// If this is KeyboardLayout.PreviousLayout the keyboard will switch to the previous set layout. The keyboard
/// maintains internally a stack of all used layouts. If no more layouts in the stakc, the keyboard switches to
/// the layout with index 0.
/// </remarks>
public int ChangeToLayout
{
get { return _ChangeToLayout; }
}
private int _ChangeToLayoutEx;
/// <summary>
/// Gets the index of the layout to change to, when this key is double clicked. A positive value represents a new layout.
/// KeyboardLayout.NoChange and KeyboardLayout.PreviousLayout constants can also be used with special meaning.
/// </summary>
/// <remarks>
/// If this is a positive integer ( >= 0 ), it represents the index of the layout to switch to when this key
/// is pressed. In this case, the keyboard does not send any key information to the attached control (the Info
/// field is ignored), only changes the layout.
///
/// If this is KeyboardLayout.NoChange the keyboard will send the info to the attached control.
///
/// If this is KeyboardLayout.PreviousLayout the keyboard will switch to the previous set layout. The keyboard
/// maintains internally a stack of all used layouts. If no more layouts in the stakc, the keyboard switches to
/// the layout with index 0.
/// </remarks>
public int ChangeToLayoutEx
{
get { return _ChangeToLayoutEx; }
}
private string _Hint;
/// <summary>
/// Gets the text that will be displayed in the upper part of the keyboard, as a hint for what the key does,
/// usually in combination with a modifier key (e.g. Underline, Undo, etc).
/// </summary>
public string Hint
{
get { return _Hint; }
}
/// <summary>
/// Creates a new Key object.
/// </summary>
/// <param name="caption">The text displayed on the key.</param>
/// <param name="info">The information that will be sent to the attached control.</param>
/// <param name="hint">The text in the upper part of the key, that provides a hint for the user about what the key does.</param>
/// <param name="style">The way the key looks.</param>
/// <param name="changeToLayout">The index of the layout to switch to.</param>
public Key(string caption, string info = null, string hint = "", KeyStyle style = KeyStyle.Normal, int changeToLayout = KeyboardLayout.NoChange, int changeToLayoutEx = KeyboardLayout.NoChange)
{
_Caption = caption;
_Info = info != null ? info : caption;
_Style = style;
_Hint = hint;
_ChangeToLayout = changeToLayout;
_ChangeToLayoutEx = changeToLayoutEx;
}
/// <summary>
/// Returns a string that represents the current Key.
/// </summary>
/// <returns>A string that represents the current Key.</returns>
public override string ToString()
{
return Caption;
}
}
/// <summary>
/// Specifies the way a key looks, specifically what color it uses from the ColorTable.
/// </summary>
public enum KeyStyle
{
/// <summary>
/// Key should be drawn as a normal key colors.
/// </summary>
Normal,
/// <summary>
/// Key should be drawn with lighter colors.
/// </summary>
Light,
/// <summary>
/// Key should be drawn with darker colors.
/// </summary>
Dark,
/// <summary>
/// Key should be drawn with the pressed color.
/// </summary>
Pressed,
/// <summary>
/// Key should be drawn with the toggled color.
/// </summary>
Toggled
}
/// <summary>
/// Represents a layout for a virtual keyboard.
/// </summary>
/// The Keys have coordinates in the KeyboardLayout specified in logical layout units. By default for this version
/// of the control, a normal key is 10 logical units (LUs) width and 10 LUs height. A space between two keys is 1 LU.
/// When rendering, we assume the whole Layout is stretched over the Keyboard control, so we need to change from
/// LUs (ranging from 0 to layout.LogicalWidth) to pixels (ranging from 0 to control.Width).
/// This allows the layout to be resized to almost any sizes.
public class KeyboardLayout
{
/// <summary>
/// Indicates that a key should switch the Keyboard to the previous layout.
/// </summary>
public const int PreviousLayout = -2;
/// <summary>
/// Indicates that a key does not switch to any layout.
/// </summary>
public const int NoChange = -1;
private KeysCollection _Keys = new KeysCollection();
/// <summary>
/// Gets the collection of the Keys in this KeyboardLayout.
/// </summary>
public KeysCollection Keys
{
get { return _Keys; }
}
/// <summary>
/// Gets the logical width of this KeyboardLayout.
/// </summary>
public virtual int LogicalWidth
{
get
{
int w = 0;
foreach (Key key in Keys)
{
if (key.Bounds.Right > w)
w = key.Bounds.Right;
}
return w;
}
}
/// <summary>
/// Gets the logical height of this KeyboardLayout.
/// </summary>
public virtual int LogicalHeight
{
get
{
int h = 0;
foreach (Key key in Keys)
{
if (key.Bounds.Bottom > h)
h = key.Bounds.Bottom;
}
return h;
}
}
/// <summary>
/// Tests if a certain point hits a key on the virtual keyboard.
/// </summary>
/// <param name="x">The x-coordinate of the hit point (in logical units of this KeyboardLayout)</param>
/// <param name="y">The y-coordinate of the hit point (in logical units of this KeyboardLayout)</param>
/// <returns>Returns the key that was hit, or null if the point didn't hit any keys.</returns>
public Key KeyHitTest(int x, int y)
{
foreach (Key key in Keys)
{
if (key.Bounds.Contains(x, y))
return key;
}
return null;
}
}
/// <summary>
/// Represents a layout for a virtual keyboard in which keys are defined in a linear way. This class
/// allows creation of layouts in which keys can be ordered from left to right and from top to bottom.
/// </summary>
/// <remarks>
/// With the linear layout, the keys are allowed to have any width. The height, however, must be the same.
/// This layout is build by adding to it spaces, keys and new lines.
/// A key represents a virtual key AND a space after it.
/// A space represents a placeholder between two keys and it is used when there is need for a larger space
/// between two certain keys
/// A new line represents the fact that a new line of keys should be defined.
/// </remarks>
/// <example>
/// The default virtual keyboard of the VirtualKeyboard control is defined in the following way:
/// <code>
/// AddKey("q");
/// AddKey("w");
/// AddKey("e");
/// // ...
/// AddKey("p");
/// AddKey("Backspace");
///
/// AddLine(); // Starts a new row of keys.
/// AddSpace(4); // Creates a larger space at the beginning of the second row.
///
/// AddKey("a");
/// AddKey("s");
/// // ...
/// </code>
/// </example>
public class LinearKeyboardLayout : KeyboardLayout
{
private int _LastXOffset = 0;
private int _LastYOffset = 0;
/// <summary>
/// The logical size of the space between two keys.
/// </summary>
public const int SpaceSize = 1;
/// <summary>
/// The logical size of a key.
/// </summary>
public const int NormalKeySize = 10;
/// <summary>
/// Adds a space to this LinearKeyboardLayout.
/// </summary>
/// <param name="width">The size of the space, in logical units.</param>
public void AddSpace(int width = SpaceSize)
{
width = Dpi.Width(width);
_LastXOffset += width;
}
/// <summary>
/// Starts a new row of keys in this LinearKeyboardLayout.
/// </summary>
public void AddLine()
{
_LastXOffset = 0;
_LastYOffset += Dpi.Width(NormalKeySize + SpaceSize);
}
/// <summary>
/// Adds a new key to this LinearKeayboardLayout.
/// </summary>
/// <param name="caption">The text displayed on the key.</param>
/// <param name="info">The information that will be sent to the attached control.</param>
/// <param name="hint">The text in the upper part of the key, that provides a hint for the user about what the key does.</param>
/// <param name="width">The width of the key, in logical units.</param>
/// <param name="height">The height of the key, in logical units.</param>
/// <param name="style">The way the key looks.</param>
/// <param name="changeToLayout">The index of the layout to switch to.</param>
/// <param name="changeToLayoutEx">The index of the layout to switch to, when key is double clicked.</param>
public void AddKey(string caption, string info = null, string hint = "", int width = NormalKeySize, int height = NormalKeySize, KeyStyle style = KeyStyle.Normal, int layout = KeyboardLayout.NoChange, int layoutEx = KeyboardLayout.NoChange)
{
Key key = new Key(caption, info, hint, style, layout, layoutEx);
width = Dpi.Width(width);
height = Dpi.Height(height);
key.Bounds = new Rectangle(_LastXOffset, _LastYOffset, width, height);
_LastXOffset += width;
AddSpace();
Keys.Add(key);
}
}
/// <summary>
/// Represents a Virtual Keyboard.
/// </summary>
/// Each Keyboard has a collection of KeyboardLayout objects. The Keyboard also maintains the current Layout among all its layouts.
public class Keyboard
{
private KeyboardLayoutsCollection _Layouts = new KeyboardLayoutsCollection();
/// <summary>
/// Gets the collection of the keyboard layouts in this Keyboard.
/// </summary>
public KeyboardLayoutsCollection Layouts
{
get { return _Layouts; }
}
private int _CurrentLayoutIndex;
/// <summary>
/// Gets or sets the current layout index of this Keyboard.
/// </summary>
public int CurrentLayoutIndex
{
get { return _CurrentLayoutIndex; }
set
{
_LayoutStack.Push(_CurrentLayoutIndex);
_CurrentLayoutIndex = value;
}
}
/// <summary>
/// Gets the current layout of this Keyboard.
/// </summary>
public KeyboardLayout CurrentLayout
{
get { return _Layouts[_CurrentLayoutIndex]; }
}
private Stack<int> _LayoutStack = new Stack<int>();
/// <summary>
/// Switches the Keyboard to the previous layout.
/// </summary>
public void ChangeToPreviousLayout()
{
if (_LayoutStack.Count > 0)
_CurrentLayoutIndex = _LayoutStack.Pop();
else
_CurrentLayoutIndex = 0;
}
/// <summary>
/// Switches the Keyboard to the first layout and resets the layout stack.
/// </summary>
public void ResetLayoutStack()
{
_LayoutStack.Clear();
_CurrentLayoutIndex = 0;
}
/// <summary>
/// Creates the default Keyboard populated with common layouts and functionality.
/// </summary>
/// <returns>A new Keyboard instance representing a default keyboard.</returns>
public static Keyboard CreateDefaultKeyboard()
{
Keyboard keyboard = new Keyboard();
LinearKeyboardLayout kc; // Actually there are 4 layout objects, but for code simplicity this variable is reused for creating each of them.
#region Normal style configuration (no modifier keys pressed)
kc = new LinearKeyboardLayout();
keyboard._Layouts.Add(kc);
kc.AddKey("q");
kc.AddKey("w");
kc.AddKey("e");
kc.AddKey("r");
kc.AddKey("t");
kc.AddKey("y");
kc.AddKey("u");
kc.AddKey("i");
kc.AddKey("o");
kc.AddKey("p");
kc.AddKey("Backspace", info: "{BACKSPACE}", width: 21);
kc.AddLine();
kc.AddSpace(4);
kc.AddKey("a");
kc.AddKey("s");
kc.AddKey("d");
kc.AddKey("f");
kc.AddKey("g");
kc.AddKey("h");
kc.AddKey("j");
kc.AddKey("k");
kc.AddKey("l");
kc.AddKey("'");
kc.AddKey("Enter", info: "{ENTER}", width: 17);
kc.AddLine();
kc.AddKey("Shift", info: "", style: KeyStyle.Dark, layout: 1);
kc.AddKey("z");
kc.AddKey("x");
kc.AddKey("c");
kc.AddKey("v");
kc.AddKey("b");
kc.AddKey("n");
kc.AddKey("m");
kc.AddKey(",");
kc.AddKey(".");
kc.AddKey("?");
kc.AddKey("Shift", info: "", style: KeyStyle.Dark, layout: 1);
kc.AddLine();
kc.AddKey("Ctrl", info: "", style: KeyStyle.Dark, layout: 2);
kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark);
//kc.AddKey("Alt", info: "%", style: KeyStyle.Dark);
kc.AddKey(" ", width: 76);
kc.AddKey("<", info: "{LEFT}", style: KeyStyle.Dark);
kc.AddKey(">", info: "{RIGHT}", style: KeyStyle.Dark);
#endregion
#region Shift modifier pressed
kc = new LinearKeyboardLayout();
keyboard._Layouts.Add(kc);
kc.AddKey("Q", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("W", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("E", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("R", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("T", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Y", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("U", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("I", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("O", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("P", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Backspace", info: "{BACKSPACE}", width: 21);
kc.AddLine();
kc.AddSpace(4);
kc.AddKey("A", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("S", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("D", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("F", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("G", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("H", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("J", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("K", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("L", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("\"", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Enter", info: "{ENTER}", width: 17);
kc.AddLine();
kc.AddKey("Shift", info: "", style: KeyStyle.Pressed, layout: 0, layoutEx: 4);
kc.AddKey("Z", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("X", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("C", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("V", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("B", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("N", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("M", layout: KeyboardLayout.PreviousLayout);
kc.AddKey(";", layout: KeyboardLayout.PreviousLayout);
kc.AddKey(":", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("!", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Shift", info: "", style: KeyStyle.Pressed, layout: 0, layoutEx: 4);
kc.AddLine();
kc.AddKey("Ctrl", info: "", style: KeyStyle.Dark, layout: 2);
kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
kc.AddKey(" ", width: 76, layout: KeyboardLayout.PreviousLayout);
kc.AddKey("<", info: "+{LEFT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
kc.AddKey(">", info: "+{RIGHT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
#endregion
#region Ctrl modifier pressed
kc = new LinearKeyboardLayout();
keyboard._Layouts.Add(kc);
kc.AddKey("q", info: "^q", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("w", info: "^w", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("e", info: "^e", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("r", info: "^r", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("t", info: "^t", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("y", info: "^y", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("u", info: "^u", hint: "Underline", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("i", info: "^i", hint: "Italic", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("o", info: "^o", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("p", info: "^p", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Backspace", info: "^{BACKSPACE}", width: 21, layout: KeyboardLayout.PreviousLayout);
kc.AddLine();
kc.AddSpace(4);
kc.AddKey("a", info: "^a", hint: "Select all", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("s", info: "^s", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("d", info: "^d", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("f", info: "^f", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("g", info: "^g", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("h", info: "^h", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("j", info: "^j", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("k", info: "^k", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("l", info: "^l", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("'", info: "^'", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Enter", info: "^{ENTER}", width: 17, layout: KeyboardLayout.PreviousLayout);
kc.AddLine();
kc.AddKey("Shift", info: "", layout: 1);
kc.AddKey("z", info: "^z", hint: "Undo", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("x", info: "^x", hint: "Cut", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("c", info: "^c", hint: "Copy", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("v", info: "^v", hint: "Paste", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("b", info: "^b", hint: "Bold", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("n", info: "^n", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("m", info: "^m", layout: KeyboardLayout.PreviousLayout);
kc.AddKey(",", info: "^,", layout: KeyboardLayout.PreviousLayout);
kc.AddKey(".", info: "^.", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("?", info: "^?", layout: KeyboardLayout.PreviousLayout);
kc.AddKey("Shift", info: "", layout: 1);
kc.AddLine();
kc.AddKey("Ctrl", info: "", style: KeyStyle.Pressed, layout: KeyboardLayout.PreviousLayout);
kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
kc.AddKey(":-)", info: "^:-{)}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
kc.AddKey(" ", info: "^ ", width: 76, layout: KeyboardLayout.PreviousLayout);
kc.AddKey("<", info: "^{LEFT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
kc.AddKey(">", info: "^{RIGHT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
#endregion
#region Symbols and numbers (&123) modifier pressed
kc = new LinearKeyboardLayout();
keyboard._Layouts.Add(kc);
kc.AddKey("!");
kc.AddKey("@");
kc.AddKey("#");
kc.AddKey("$");
kc.AddKey("½");
kc.AddKey("-");
kc.AddKey("+", info: "{+}");
kc.AddSpace(5);
kc.AddKey("1", style: KeyStyle.Light);
kc.AddKey("2", style: KeyStyle.Light);
kc.AddKey("3", style: KeyStyle.Light);
kc.AddSpace(5);
kc.AddKey("Bcks", info: "{BACKSPACE}", style: KeyStyle.Dark);
kc.AddLine();
// second line
kc.AddKey(";");
kc.AddKey(":");
kc.AddKey("\"");
kc.AddKey("%", info: "{%}");
kc.AddKey("&");
kc.AddKey("/");
kc.AddKey("*");
kc.AddSpace(5);
kc.AddKey("4", style: KeyStyle.Light);
kc.AddKey("5", style: KeyStyle.Light);
kc.AddKey("6", style: KeyStyle.Light);
kc.AddSpace(5);
kc.AddKey("Enter", info: "{ENTER}", style: KeyStyle.Dark);
kc.AddLine();
// third line
kc.AddKey("(", info: "{(}");
kc.AddKey(")", info: "{)}");
kc.AddKey("[", info: "{[}");
kc.AddKey("]", info: "{]}");
kc.AddKey("_");
kc.AddKey("\\");
kc.AddKey("=");
kc.AddSpace(5);
kc.AddKey("7", style: KeyStyle.Light);
kc.AddKey("8", style: KeyStyle.Light);
kc.AddKey("9", style: KeyStyle.Light);
kc.AddSpace(5);
kc.AddKey("Tab", info: "{TAB}", style: KeyStyle.Dark);
kc.AddLine();
// forth line
kc.AddKey("...", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
kc.AddKey("&123", info: "", style: KeyStyle.Pressed, layout: KeyboardLayout.PreviousLayout);
kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark);
kc.AddKey("<", info: "{LEFT}", style: KeyStyle.Dark);
kc.AddKey(">", info: "{RIGHT}", style: KeyStyle.Dark);
kc.AddKey("Space", info: "^ ", width: 21);
kc.AddSpace(5);
kc.AddKey("0", style:KeyStyle.Light, width: 21);
kc.AddKey(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, style: KeyStyle.Dark);
kc.AddSpace(5);
kc.AddLine();
#endregion
#region Shift modifier toggled
kc = new LinearKeyboardLayout();
keyboard._Layouts.Add(kc);
kc.AddKey("Q");
kc.AddKey("W");
kc.AddKey("E");
kc.AddKey("R");
kc.AddKey("T");
kc.AddKey("Y");
kc.AddKey("U");
kc.AddKey("I");
kc.AddKey("O");
kc.AddKey("P");
kc.AddKey("Backspace", info: "{BACKSPACE}", width: 21);
kc.AddLine();
kc.AddSpace(4);
kc.AddKey("A");
kc.AddKey("S");
kc.AddKey("D");
kc.AddKey("F");
kc.AddKey("G");
kc.AddKey("H");
kc.AddKey("J");
kc.AddKey("K");
kc.AddKey("L");
kc.AddKey("'");
kc.AddKey("Enter", info: "{ENTER}", width: 17);
kc.AddLine();
kc.AddKey("Shift", info: "", style: KeyStyle.Toggled, layout: 0);
kc.AddKey("Z");
kc.AddKey("X");
kc.AddKey("C");
kc.AddKey("V");
kc.AddKey("B");
kc.AddKey("N");
kc.AddKey("M");
kc.AddKey(",");
kc.AddKey(".");
kc.AddKey("?");
kc.AddKey("Shift", info: "", style: KeyStyle.Toggled, layout: 0);
kc.AddLine();
kc.AddKey("Ctrl", info: "", style: KeyStyle.Dark, layout: 2);
kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark);
kc.AddKey(" ", width: 76);
kc.AddKey("<", info: "+{LEFT}", style: KeyStyle.Dark);
kc.AddKey(">", info: "+{RIGHT}", style: KeyStyle.Dark);
#endregion
return keyboard;
}
}
/// <summary>
/// Contains a collection of Key objects.
/// </summary>
public class KeysCollection : Collection<Key>
{
}
/// <summary>
/// Contains a collection of KeyboardLayout objects.
/// </summary>
public class KeyboardLayoutsCollection : Collection<KeyboardLayout>
{
}
}

View File

@@ -0,0 +1,874 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections;
using System.Runtime.InteropServices;
using DevComponents.DotNetBar.Touch;
namespace DevComponents.DotNetBar.Keyboard
{
/// <summary>
/// Represents virtual keyboard control.
/// </summary>
[ToolboxItem(true)]
public class KeyboardControl : Control
{
private TouchHandler _TouchHandler = null;
/// <summary>
/// Creates a new VirtualKeyboard control.
/// </summary>
public KeyboardControl()
{
_ColorTable = _DefaultColorTable;
// Do not allow the control to receive focus.
SetStyle(ControlStyles.Selectable, false);
// Do not call OnPaintBackground().
SetStyle(ControlStyles.Opaque, true);
// Enable double buffering. OptimizedDoubleBuffer and AllPaintingInWmPaint are set by the DoubleBuffered property below.
//SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
//SetStyle(ControlStyles.AllPaintingInWmPaint, true);
DoubleBuffered = true;
ResizeRedraw = true;
_RepeatTimer = new Timer();
_RepeatTimer.Tick += new EventHandler(RepeatTimer_Tick);
}
// The model for the Keyboard. This object contains all the information about the keys
// and the possible layouts of the keyboard.
private Keyboard _Keyboard = null; //Keyboard.CreateDefaultKeyboard();
/// <summary>
/// Gets or sets the Keyboard object that describes the VirtualKeyboard.
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Keyboard Keyboard
{
get
{
if(_Keyboard==null)
_Keyboard = Keyboard.CreateDefaultKeyboard();
return _Keyboard;
}
set { _Keyboard = value; }
}
/// <summary>
/// Default width for the keyboard in pixels.
/// </summary>
public static int DefaultWidth
{
get { return 740; }
}
/// <summary>
/// Default height for the keyboard in pixels.
/// </summary>
public static int DefaultHeight {
get { return 250; }
}
protected override Size DefaultSize
{
get
{
return Dpi.Size(new Size(DefaultWidth, DefaultHeight));
}
}
private VirtualKeyboardColorTable _DefaultColorTable = new VirtualKeyboardColorTable();
private VirtualKeyboardColorTable _ColorTable;
/// <summary>
/// Gets or set the ColorTable used to draw the keyboard.
/// </summary>
public VirtualKeyboardColorTable ColorTable
{
get { return _ColorTable; }
set
{
_ColorTable = value;
Invalidate(); // Ok to invalidate entire control, to render everything with the new colors.
}
}
private Renderer _Renderer = new FlatStyleRenderer();
/// <summary>
/// Gets or sets the Renderer used to render the keyboard.
/// </summary>
public Renderer Renderer
{
get { return _Renderer; }
set
{
if (value == null)
value = new FlatStyleRenderer();
_Renderer = value;
Invalidate(); // Ok to invalidate entire control, to redraw everything with the new renderer.
}
}
// Through this method, the keys generated by the Virtual Keyboard are sent to the target control.
// In this version, the current target control is always the control with input focus and the keyboard
// is only visible when the control (to which the keyboard was previously attached) has input focus.
// Therefore, SendKeys.Send offers all the logic needed for this version of the keyboard.
//
// For future versions, we might consider using the Win32 API SendInput function for greater flexibility.
private void SendKeysToTarget(string info)
{
KeyboardKeyCancelEventArgs cancelArgs = new KeyboardKeyCancelEventArgs(info);
OnSendingKey(cancelArgs);
if (cancelArgs.Cancel) return;
SendKeys.Send(info);
OnKeySent(new KeyboardKeyEventArgs(info));
}
#region Send repeating key if mouse is hold down
private Timer _RepeatTimer; // Used to send repeated keys to the target control.
private Key _PressedKey; // Used to keep the keys that is repeatedly sent to the target control.
private void RepeatTimer_Tick(object sender, EventArgs e)
{
if (_PressedKey != null)
{
if (_RepeatTimer.Interval == KeyboardDelay)
_RepeatTimer.Interval = KeyboardSpeed;
SendKeysToTarget(_PressedKey.Info);
}
}
private void CancelRepeatKey()
{
_PressedKey = null;
_RepeatTimer.Stop();
}
private void StartRepeatKey(Key key)
{
_PressedKey = key;
_RepeatTimer.Start();
_RepeatTimer.Interval = KeyboardDelay;
}
private static int KeyboardDelay
{
get
{
// SystemInformation.KeyboardDelay is between 0 (2.5 repetitions per second) and 31 (about 30 per second)
// but these values arre hardware dependendant, so the fomula below is a fast and accurate enough not to feel
// any difference between this and a real keyboard at the same values.
return 1000 / (SystemInformation.KeyboardDelay + 1);
}
}
private static int KeyboardSpeed
{
get
{
// See KeyboardDelay for details.
return 1000 / (SystemInformation.KeyboardSpeed + 1);
}
}
#endregion
private bool _IsTopBarVisible = true;
/// <summary>
/// Gets or sets a value indicating if the top bar of the keyboard is visible.
/// </summary>
[DefaultValue(true)]
[Description("Indicates if the top bar of the keyboard is visible.")]
[Category("Appearance")]
public bool IsTopBarVisible
{
get { return _IsTopBarVisible; }
set
{
_IsTopBarVisible = value;
this.Invalidate();
}
}
private int _CaptionHeight = 20;
/// <summary>
/// Indicates the height of the keyboard caption which hosts the close button.
/// </summary>
[DefaultValue(20), Category("Appearance"), Description("Indicates the height of the keyboard caption which hosts the close button.")]
public int CaptionHeight
{
get { return _CaptionHeight; }
set
{
if (value != _CaptionHeight)
{
int oldValue = _CaptionHeight;
_CaptionHeight = value;
this.Invalidate();
}
}
}
//private const int TopBarHeight = 20;
private int TopBarVisibleHeight
{
get { return IsTopBarVisible ? ActualCaptionHeight + Border : 0; }
}
public int Border {
get { return Dpi.Width10; }
}
private readonly Key HideKeyboardKey = new Key("Hide", info: null);
private int ActualCaptionHeight
{
get { return Dpi.Height(_CaptionHeight); }
}
private Rectangle TopBarRectangle
{
get { return new Rectangle(Border, Border, Width - 2 * Border, ActualCaptionHeight); }
}
private Rectangle CloseButtonRectangle
{
get { return new Rectangle(Width - ActualCaptionHeight - Border, Border, ActualCaptionHeight, ActualCaptionHeight); }
}
private Rectangle KeysRectangle
{
get
{
Rectangle rect = new Rectangle(Border, Border, Width - 2 * Border, Height - 2 * Border);
if (IsTopBarVisible)
{
rect.Y += ActualCaptionHeight + Border;
rect.Height -= ActualCaptionHeight + Border;
}
return rect;
}
}
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
Dpi.SetScaling(factor);
base.ScaleControl(factor, specified);
}
protected override void OnPaint(PaintEventArgs e)
{
KeyboardLayout currentLayout = Keyboard.CurrentLayout;
if (currentLayout.LogicalWidth <= 0 || currentLayout.LogicalHeight <= 0)
return;
Rectangle rectKeys = KeysRectangle;
float sfx = (float)rectKeys.Width / currentLayout.LogicalWidth;
float sfy = (float)rectKeys.Height / currentLayout.LogicalHeight;
Renderer.ColorTable = ColorTable;
Renderer.BeginFrame(new BeginFrameRendererEventArgs(e.Graphics, e.ClipRectangle, rectKeys, Font, currentLayout));
Renderer.DrawBackground(new BackgroundRendererEventArgs(e.Graphics, e.ClipRectangle, new Rectangle(0, 0, Width, Height)));
if (IsTopBarVisible)
{
Renderer.DrawTopBar(new TopBarRendererEventArgs(e.Graphics, e.ClipRectangle, TopBarRectangle, Text, Font));
Renderer.DrawCloseButton(new CloseButtonRendererEventArgs(e.Graphics, _PressedKey == HideKeyboardKey, e.ClipRectangle, CloseButtonRectangle));
}
foreach (Key key in currentLayout.Keys)
{
Rectangle rectKey = new Rectangle((int)(key.Bounds.X * sfx), (int)(key.Bounds.Y * sfy),
(int)(key.Bounds.Width * sfx), (int)(key.Bounds.Height * sfy));
rectKey.Offset(rectKeys.Left, rectKeys.Top);
Renderer.DrawKey(new KeyRendererEventArgs(e.Graphics, key, key == _PressedKey, e.ClipRectangle, rectKey));
}
Renderer.EndFrame();
#if TRIAL
using (Font font = new System.Drawing.Font(this.Font.FontFamily, 7, FontStyle.Regular))
{
using (SolidBrush brush = new SolidBrush(Color.FromArgb(24, Color.White)))
e.Graphics.DrawString("DotNetBar Trial Version", font, brush, (this.ClientRectangle.Width - 80) / 2, this.ClientRectangle.Height - 32);
}
#endif
}
private void PerformMoveAction(Point location)
{
if (IsTopBarVisible && CloseButtonRectangle.Contains(location))
{
Cursor = Cursors.Hand;
}
else
{
KeyboardLayout currentLayout = Keyboard.CurrentLayout;
Rectangle rectKeys = KeysRectangle;
float fx = (float)rectKeys.Width / currentLayout.LogicalWidth;
float fy = (float)rectKeys.Height / currentLayout.LogicalHeight;
if (_PressedKey == HideKeyboardKey)
{
if (_PressedKey != null)
{
Invalidate(GetKeyPhysicalBounds(_PressedKey, fx, fy));
}
_PressedKey = null;
Invalidate(CloseButtonRectangle);
this.Update();
}
Key key = null;
if (KeysRectangle.Contains(location))
key = currentLayout.KeyHitTest((int)((location.X - rectKeys.Left) / fx), (int)((location.Y - rectKeys.Top) / fy));
// If the mouse is over a key, change the cursor to the Hand cursor, to provide
// a visual feedback for the user to know that it can interact with this key.
Key pressedKey = _PressedKey;
if (key == null)
{
Cursor = Cursors.Arrow;
CancelRepeatKey();
if (pressedKey != null)
{
Invalidate(GetKeyPhysicalBounds(pressedKey, fx, fy)); // Only invalidate area under the currently pressed key.
this.Update();
}
}
else if (key != pressedKey)
{
Cursor = Cursors.Hand;
CancelRepeatKey();
if (pressedKey != null)
{
Invalidate(GetKeyPhysicalBounds(pressedKey, fx, fy)); // Only invalidate area under the currently pressed key.
this.Update();
}
}
else
{
Cursor = Cursors.Hand;
}
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (ProcessMouseAction)
{
PerformMoveAction(e.Location);
_LastTouchAction = null;
}
base.OnMouseMove(e);
}
protected override void OnMouseLeave(EventArgs e)
{
KeyboardLayout currentLayout = Keyboard.CurrentLayout;
Rectangle rectKeys = KeysRectangle;
float fx = (float)rectKeys.Width / currentLayout.LogicalWidth;
float fy = (float)rectKeys.Height / currentLayout.LogicalHeight;
if (_PressedKey != HideKeyboardKey)
Invalidate(CloseButtonRectangle);
else if (_PressedKey != null)
{
Invalidate(GetKeyPhysicalBounds(_PressedKey, fx, fy)); // Only invalidate area under the currently pressed key.
this.Update();
}
CancelRepeatKey();
}
private bool _TouchEnabled = true;
/// <summary>
/// Indicates whether touch support is enabled when provided by hardware.
/// </summary>
[DefaultValue(true), Category("Behavior"), Description("Indicates whether touch support is enabled when provided by hardware.")]
public bool TouchEnabled
{
get { return _TouchEnabled; }
set
{
if (value != _TouchEnabled)
{
bool oldValue = _TouchEnabled;
_TouchEnabled = value;
OnTouchEnabledChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when TouchEnabled property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnTouchEnabledChanged(bool oldValue, bool newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("TouchEnabled"));
}
protected override void OnHandleCreated(EventArgs e)
{
if (TouchHandler.IsTouchEnabled)
{
_TouchHandler = new TouchHandler(this, eTouchHandlerType.Touch);
_TouchHandler.TouchDown += new EventHandler<TouchEventArgs>(TouchHandlerTouchDown);
_TouchHandler.TouchUp += new EventHandler<TouchEventArgs>(TouchHandlerTouchUp);
// Don't need touch move action for keyboard handling
//_TouchHandler.TouchMove += new EventHandler<TouchEventArgs>(TouchHandlerTouchMove);
}
base.OnHandleCreated(e);
}
private DateTime? _LastTouchAction = null;
//void TouchHandlerTouchMove(object sender, TouchEventArgs e)
//{
// PerformMoveAction(e.Location);
// _LastTouchAction = DateTime.Now;
//}
void TouchHandlerTouchUp(object sender, TouchEventArgs e)
{
if (_TouchEnabled)
{
// Process keybaord hiding through the MouseUp event instead of touch event since if closed using touch the mouse up will occur on control
// which is under keyboard after keyboard is hidden which is not desired
if (IsTopBarVisible && CloseButtonRectangle.Contains(e.Location))
{
_LastTouchAction = null;
return;
}
PerformUpAction(e.Location);
_LastTouchAction = DateTime.Now;
}
}
void TouchHandlerTouchDown(object sender, TouchEventArgs e)
{
if (_TouchEnabled)
{
PerformDownAction(e.Location);
_LastTouchAction = DateTime.Now;
}
}
/// <summary>
/// Returns the Key at given location. Location expected is in control coordinates.
/// </summary>
/// <param name="location">Location is control coordinates.</param>
/// <returns>Key if there is a key at given location or null/nothing if no key exists at given location.</returns>
public Key HitTest(Point location)
{
KeyboardLayout currentLayout = Keyboard.CurrentLayout;
Rectangle rectKeys = KeysRectangle;
float fx = (float)rectKeys.Width / currentLayout.LogicalWidth;
float fy = (float)rectKeys.Height / currentLayout.LogicalHeight;
Key key = null;
if (KeysRectangle.Contains(location))
key = currentLayout.KeyHitTest((int)((location.X - rectKeys.Left) / fx), (int)((location.Y - rectKeys.Top) / fy));
return key;
}
private void PerformDownAction(Point location)
{
if (_PressedKey != null) // This can happen because multi-touch can send multiple down messages
{
PerformUpAction(location);
}
if (IsTopBarVisible && CloseButtonRectangle.Contains(location))
{
_PressedKey = HideKeyboardKey;
Invalidate(CloseButtonRectangle);
}
else
{
KeyboardLayout currentLayout = Keyboard.CurrentLayout;
Rectangle rectKeys = KeysRectangle;
float fx = (float)rectKeys.Width / currentLayout.LogicalWidth;
float fy = (float)rectKeys.Height / currentLayout.LogicalHeight;
Key key = HitTest(location);
if (key != null)
{
TimeSpan ts = DateTime.Now.Subtract(_LastMouseUpEvent);
if (_LastKeyUp != null && key.Caption == _LastKeyUp.Caption && ts < TimeSpan.FromMilliseconds(SystemInformation.DoubleClickTime) && key.ChangeToLayoutEx >= 0)
{
Keyboard.CurrentLayoutIndex = key.ChangeToLayoutEx;
_LastMouseUpEvent = DateTime.MinValue;
Invalidate();
}
else
{
_PressedKey = key;
if (_PressedKey.Info != null && _PressedKey.Info != "")
{
StartRepeatKey(key);
SendKeysToTarget(key.Info);
}
}
Invalidate(GetKeyPhysicalBounds(key, fx, fy)); // Only invalidate area under the currently pressed key.
}
}
this.Update();
}
private int TouchMouseInputFilterDelay = 2000;
private bool ProcessMouseAction
{
get
{
return _LastTouchAction == null ||
(_LastTouchAction != null && DateTime.Now.Subtract(_LastTouchAction.Value).TotalMilliseconds > TouchMouseInputFilterDelay);
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (ProcessMouseAction)
{
PerformDownAction(e.Location);
_LastTouchAction = null;
}
base.OnMouseDown(e);
}
private DateTime _LastMouseUpEvent = DateTime.MinValue;
private Key _LastKeyUp = null;
private void PerformUpAction(Point location)
{
if (IsTopBarVisible && CloseButtonRectangle.Contains(location))
{
if (_PressedKey == HideKeyboardKey)
{
HideKeyboard();
_PressedKey = null;
}
CancelRepeatKey();
}
else
{
Key pressedKey = _PressedKey;
CancelRepeatKey();
if (pressedKey != null)
{
KeyboardLayout currentLayout = Keyboard.CurrentLayout;
Rectangle rectKeys = KeysRectangle;
float fx = (float)rectKeys.Width / currentLayout.LogicalWidth;
float fy = (float)rectKeys.Height / currentLayout.LogicalHeight;
_LastMouseUpEvent = DateTime.Now;
_LastKeyUp = pressedKey;
if (pressedKey.ChangeToLayout >= 0)
{
Keyboard.CurrentLayoutIndex = pressedKey.ChangeToLayout;
Invalidate(); // Ok to invalidate entire control because we need to draw a whole new layout.
}
else if (pressedKey.ChangeToLayout == KeyboardLayout.PreviousLayout)
{
Keyboard.ChangeToPreviousLayout();
Invalidate(); // Ok to invalidate entire control because we need to draw a whole new layout.
}
else
{
Invalidate(GetKeyPhysicalBounds(pressedKey, fx, fy)); // Only invalidate area under the currently pressed key.
}
}
}
this.Update();
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (ProcessMouseAction)
{
PerformUpAction(e.Location);
base.OnMouseUp(e);
}
_LastTouchAction = null;
}
private Rectangle GetKeyPhysicalBounds(Key key, float scaleFactorX, float scaleFactorY)
{
Rectangle r = key.Bounds;
r.X = (int)(r.X * scaleFactorX) + Border;
r.Y = (int)(r.Y * scaleFactorY) + Border + TopBarVisibleHeight;
r.Width = (int)(r.Width * scaleFactorX);
r.Height = (int)(r.Height * scaleFactorY);
return r;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_DefaultColorTable != null)
_DefaultColorTable.Dispose();
if (_RepeatTimer != null)
_RepeatTimer.Dispose();
}
base.Dispose(disposing);
}
/// <summary>
/// Attaches the Keyboard to the specified control. The keyboard will automatically appear when the control receives input focus.
/// </summary>
/// <param name="control">The control to which the Keyboard will be attached.</param>
public void AttachTo(Control control)
{
control.GotFocus += new EventHandler(control_GotFocus);
control.LostFocus += new EventHandler(control_LostFocus);
}
/// <summary>
/// Detaches the Keyboard from the specified control.
/// </summary>
/// <param name="control">The control from which the Keyboard will be detached.</param>
public void DetachFrom(Control control)
{
control.GotFocus -= new EventHandler(control_GotFocus);
control.LostFocus -= new EventHandler(control_LostFocus);
}
public void UnlockCapsLock()
{
if (Control.IsKeyLocked(Keys.CapsLock))
{
OSVERSIONINFO info=new OSVERSIONINFO();
info.dwOSVersionInfoSize= System.Runtime.InteropServices.Marshal.SizeOf(typeof(OSVERSIONINFO));
GetVersionEx(ref info);
byte[] keys= new byte[255];
if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) // Win95/98
{
keys[VK_CAPITAL] = 1;
SetKeyboardState(keys);
}
else if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
// Simulate Key Press
keybd_event(VK_CAPITAL, 0X45, KEYEVENTF_EXTENDEDKEY | 0, 0);
// Simulate Key Release
keybd_event(VK_CAPITAL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
}
void control_GotFocus(object sender, EventArgs e)
{
Show();
}
void control_LostFocus(object sender, EventArgs e)
{
HideKeyboard();
}
private void HideKeyboard()
{
CancelEventArgs ce = new CancelEventArgs();
OnKeyboardClosing(ce);
if (ce.Cancel) return;
this.Hide();
OnKeyboardClosed(EventArgs.Empty);
}
/// <summary>
/// Occurs before the keyboard is closed and allows canceling of keyboard closing.
/// </summary>
[Description("Occurs before the keyboard is closed and allows canceling of keyboard closing.")]
public event CancelEventHandler KeyboardClosing;
/// <summary>
/// Raises KeyboardClosing event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeyboardClosing(CancelEventArgs e)
{
CancelEventHandler handler = KeyboardClosing;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs after keyboard is closed.
/// </summary>
[Description("Occurs after keyboard is closed.")]
public event EventHandler KeyboardClosed;
/// <summary>
/// Raises KeyboardClosed event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeyboardClosed(EventArgs e)
{
EventHandler handler = KeyboardClosed;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs before the key pressed on keyboard is sent to target control and allows cancellation of the message
/// </summary>
[Description("Occurs before the key pressed on keyboard is sent to target control and allows cancellation of the message.")]
public event KeyCancelEventHandler SendingKey;
/// <summary>
/// Raises SendingKey event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnSendingKey(KeyboardKeyCancelEventArgs e)
{
KeyCancelEventHandler handler = SendingKey;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs after the key is sent to target control.
/// </summary>
[Description("Occurs after the key is sent to target control.")]
public event KeyEventHandler KeySent;
/// <summary>
/// Raises KeySent event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeySent(KeyboardKeyEventArgs e)
{
KeyEventHandler handler = KeySent;
if (handler != null)
handler(this, e);
}
protected override void OnTextChanged(EventArgs e)
{
this.Invalidate();
base.OnTextChanged(e);
}
#region Windows API
// Declare Type for API call:
[StructLayout(LayoutKind.Sequential)]
internal struct OSVERSIONINFO
{
public int dwOSVersionInfoSize;
public int dwMajorVersion;
public int dwMinorVersion;
public int dwBuildNumber;
public int dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szCSDVersion;
}
// Constant declarations:
const int VK_CAPITAL = 0x14;
const int KEYEVENTF_EXTENDEDKEY = 1;
const int KEYEVENTF_KEYUP = 2;
const int VER_PLATFORM_WIN32_NT = 2;
const int VER_PLATFORM_WIN32_WINDOWS = 1;
// API declarations:
[DllImport("kernel32.Dll")]
private static extern short GetVersionEx(ref OSVERSIONINFO o);
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
[DllImport("user32.dll")]
static extern bool SetKeyboardState(byte[] lpKeyState);
#endregion
}
/// <summary>
/// Defines delegate for key-related events.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void KeyEventHandler(object sender, KeyboardKeyEventArgs e);
/// <summary>
/// Provides data for key related events.
/// </summary>
public class KeyboardKeyEventArgs : EventArgs
{
/// <summary>
/// Gets the key being pressed. The format of this information
/// must confirm to the description for the SendKeys.Send function. For more details, see:
/// http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
/// </summary>
public readonly string Key;
/// <summary>
/// Initializes a new instance of the KeyboardKeyEventArgs class.
/// </summary>
/// <param name="key"></param>
public KeyboardKeyEventArgs(string key)
{
Key = key;
}
}
/// <summary>
/// Defines delegate for key-related events.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void KeyCancelEventHandler(object sender, KeyboardKeyCancelEventArgs e);
/// <summary>
/// Provides data for key related events.
/// </summary>
public class KeyboardKeyCancelEventArgs : CancelEventArgs
{
/// <summary>
/// Gets the key being pressed. The format of this information
/// must confirm to the description for the SendKeys.Send function. For more details, see:
/// http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
/// </summary>
public readonly string Key;
/// <summary>
/// Initializes a new instance of the KeyCancelEventArgs class.
/// </summary>
/// <param name="key"></param>
public KeyboardKeyCancelEventArgs(string key)
{
Key = key;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
namespace DevComponents.DotNetBar.Keyboard
{
internal class PopupVirtualKeyboard : Form
{
/// <summary>
/// Creates a new floating virtual keyboard.
/// </summary>
public PopupVirtualKeyboard()
{
StartPosition = FormStartPosition.Manual;
// Make sure the popup window does not appear in the taskbar.
ShowInTaskbar = false;
MinimizeBox = false;
MaximizeBox = false;
//ControlBox = false;
}
#region Window activation handling
// We need to prevent the keyboard window from activating, otherwise will still focus from our target control.
// Also to achieve this effect, there must be no focusable control in the popup window.
private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATE = 0x0003;
private const int WS_EX_NOACTIVATE = 0x08000000;
// Override CreateParams to specify that this Form should not be activated.
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle = createParams.ExStyle & WS_EX_NOACTIVATE;
return createParams;
}
}
protected override void WndProc(ref Message m)
{
// This prevents the window from being activated with the mouse,
// but allows the window to be resized (with the mouse).
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = (IntPtr)MA_NOACTIVATE;
}
else
{
base.WndProc(ref m);
}
}
protected override void OnActivated(EventArgs e)
{
Owner.Activate();
}
#endregion
protected override void OnClosing(CancelEventArgs e)
{
// Cancel the Closing event as this will Dispose the form.
e.Cancel = true;
Hide();
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible && CurrentControl != _LastControl && CurrentControl != null)
{
_LastControl = CurrentControl;
}
}
internal Control CurrentControl { get; set; }
private Control _LastControl;
/*
public void MoveNearControl(Control control)
{
// We want to show the keyboard near the target control, horizontally centered,
// under the control or above it and without overlapping it, if possible.
// First try to position the Keyboard under the target control.
Point location = control.PointToScreen(Point.Empty);
location.Offset(control.Width / 2 - Width / 2, control.Height);
Location = location;
// And make sure it is in the screen containing the control.
EnsureInScreen(control);
// Now check if this position does not overlap the control.
if (!OverlapsControl(control))
return;
// Now we try to position the Keyboard above the control.
location = control.PointToScreen(Point.Empty);
location.Offset(control.Width / 2 - Width / 2, -Height);
Location = location;
// And again make sure this location is in the screen with the control.
EnsureInScreen(control);
// And check if it does not overlap the control.
if (!OverlapsControl(control))
return;
// If both below and above the control was not a good position, then this means the
// target control is quite large, so show the Keyboard inside it.
location = control.PointToScreen(Point.Empty);
location.Offset(control.Width / 2 - Width / 2, control.Height / 2 - Height / 2);
// And again, make sure the Keybboard is not clipped by the screen.
EnsureInScreen(control);
}
/// <summary>
/// Returns true if the Keyboard overlaps the specified control.
/// </summary>
/// <param name="control">The control for which to check if it is overlapped by the Keyboard.</param>
/// <returns></returns>
private bool OverlapsControl(Control control)
{
Rectangle rect = new Rectangle(control.PointToScreen(Point.Empty), control.Size);
return rect.IntersectsWith(Bounds);
}
/// <summary>
/// Checks if the Keyboard is in the screen containing the specified control, and if
/// the Keyboard is not fully visible, adjusts it's location accordingly.
/// </summary>
/// <param name="control">The control from which the screen is checked. If null, the primary screen is used.</param>
private void EnsureInScreen(Control control)
{
Screen screen = Screen.PrimaryScreen;
if(control != null)
screen = Screen.FromControl(control);
Rectangle rect = screen.WorkingArea;
if (Location.X < rect.Left)
Location = new Point(rect.Left, Location.Y);
if (Location.Y < rect.Top)
Location = new Point(Location.X, rect.Top);
if (Bounds.Right > rect.Right)
Location = new Point(rect.Right - Width, Location.Y);
if (Bounds.Bottom > rect.Bottom)
Location = new Point(Location.X, rect.Bottom - Height);
}
*/
}
}

View File

@@ -0,0 +1,546 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace DevComponents.DotNetBar.Keyboard
{
/// <summary>
/// Represents a renderer for a VirtualKeyboard.
/// </summary>
public abstract class Renderer
{
private VirtualKeyboardColorTable _ColorTable;
/// <summary>
/// Gets or sets the ColorTable used by this renderer to render the virtual keyboard.
/// </summary>
public VirtualKeyboardColorTable ColorTable
{
get { return _ColorTable; }
set { _ColorTable = value; }
}
/// <summary>
/// Draws the top bar of the VirtualKeyboard.
/// </summary>
/// <param name="args"></param>
public abstract void DrawTopBar(TopBarRendererEventArgs args);
public abstract void DrawCloseButton(CloseButtonRendererEventArgs args);
/// <summary>
/// Draws the background of the VirtualKeyboard.
/// </summary>
/// <param name="args">Provides context information.</param>
public abstract void DrawBackground(BackgroundRendererEventArgs args);
/// <summary>
/// Draws a key of the VirtualKeyboard.
/// </summary>
/// <param name="args">Provides context information.</param>
public abstract void DrawKey(KeyRendererEventArgs args);
/// <summary>
/// Called when the control starts rendering a new frame.
/// </summary>
/// <param name="args">Provides context information.</param>
public virtual void BeginFrame(BeginFrameRendererEventArgs args) { }
/// <summary>
/// Called after the control finished rendering the frame.
/// </summary>
public virtual void EndFrame() { }
}
/// <summary>
/// Represents a VirtualKeyboard renderer with a flat style.
/// </summary>
public class FlatStyleRenderer : Renderer
{
// The ratio between the key size and the font that displays the letters on the keys.
private const float _KeyFontSizeRatio = 4;
// The ratio between the key size and the font that displays the hints (e.g. Underline, Italic) on the keys.
private const float _HintFontSizeRatio = 7;
private StringFormat _CenteredTextStringFormat;
private StringFormat _TopCenteredTextStringFormat;
private float _ScaleFactorX;
private float _ScaleFactorY;
private Font _KeyFont;
private Font _HintFont;
private Rectangle _KeysBounds;
private static VirtualKeyboardColorTable _DefaultColorTable = new VirtualKeyboardColorTable();
/// <summary>
/// Gets or sets whether anti-alias smoothing is used while painting. Default value is true.
/// </summary>
public bool ForceAntiAlias { get; set; }
/// <summary>
/// Starts rendering a new frame with the black style. This gives the renderer a chance to cash some resources.
/// </summary>
public override void BeginFrame(BeginFrameRendererEventArgs args)
{
_CenteredTextStringFormat = new StringFormat();
_CenteredTextStringFormat.Alignment = StringAlignment.Center;
_CenteredTextStringFormat.LineAlignment = StringAlignment.Center;
_TopCenteredTextStringFormat = new StringFormat();
_TopCenteredTextStringFormat.Alignment = StringAlignment.Center;
_TopCenteredTextStringFormat.LineAlignment = StringAlignment.Near;
// With this fx and fy we convert between logical units and pixels.
_ScaleFactorX = (float)args.Bounds.Width / args.Layout.LogicalWidth;
_ScaleFactorY = (float)args.Bounds.Height / args.Layout.LogicalHeight;
_KeysBounds = args.Bounds;
float min = Math.Min(_ScaleFactorX, _ScaleFactorY);
float keyFontSize = min * LinearKeyboardLayout.NormalKeySize / _KeyFontSizeRatio;
float hintFontSize = min * LinearKeyboardLayout.NormalKeySize / _HintFontSizeRatio;
if (keyFontSize < 1)
keyFontSize = 1;
if (hintFontSize < 1)
hintFontSize = 1;
_KeyFont = new Font(args.Font.FontFamily, keyFontSize);
_HintFont = new Font(args.Font.FontFamily, hintFontSize);
if (ForceAntiAlias)
args.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
}
/// <summary>
/// Ends rendering a new frame with the black style. This gives the renderer a chance to free resources used during the frame.
/// </summary>
public override void EndFrame()
{
if (_CenteredTextStringFormat != null)
_CenteredTextStringFormat.Dispose();
if (_TopCenteredTextStringFormat != null)
_TopCenteredTextStringFormat.Dispose();
if (_KeyFont != null)
_KeyFont.Dispose();
if (_HintFont != null)
_HintFont.Dispose();
}
/// <summary>
/// Creates a new renderer for the black style.
/// </summary>
public FlatStyleRenderer()
{
ColorTable = _DefaultColorTable;
}
/// <summary>
/// Draws the background of a VirtualKeyboard.
/// </summary>
/// <param name="args">Provides context information.</param>
public override void DrawBackground(BackgroundRendererEventArgs args)
{
if (ColorTable != null)
args.Graphics.FillRectangle(ColorTable.BackgroundBrush, args.ClipRectangle);
}
internal static void DrawBackspaceSign(Graphics g, Rectangle rect, Brush background, Brush foreground)
{
SmoothingMode osm = g.SmoothingMode; // old smoothing mode, to restore it at the end.
g.SmoothingMode = SmoothingMode.AntiAlias;
int unit = Math.Min(rect.Width, rect.Height);
Point[] points = new Point[]
{
new Point(-2 * unit, 0),
new Point(-1 * unit, -1 * unit),
new Point(2 * unit, -1 * unit),
new Point(2 * unit, 1 * unit),
new Point(-1 * unit, 1 * unit),
new Point(-2 * unit, 0)
};
g.TranslateTransform(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
g.ScaleTransform(0.125f, 0.125f);
g.FillPolygon(foreground, points);
g.ScaleTransform(8, 8);
g.ScaleTransform(0.125f, 0.125f);
g.TranslateTransform(unit / 2, 0);
using (Pen p = new Pen(background, unit * 8 / 20))
{
g.DrawLine(p, -unit / 2, -unit / 2, unit / 2, unit / 2);
g.DrawLine(p, -unit / 2, unit / 2, unit / 2, -unit / 2);
}
g.TranslateTransform(-unit / 2, 0);
g.ScaleTransform(8, 8);
g.TranslateTransform(-(rect.Left + rect.Width / 2), -(rect.Top + rect.Height / 2));
g.SmoothingMode = osm;
}
internal static void DrawSmileySign(Graphics g, Rectangle rect, Brush background, Brush foreground)
{
SmoothingMode osm = g.SmoothingMode; // old smoothing mode, to restore it at the end.
g.SmoothingMode = SmoothingMode.AntiAlias;
int unit = Math.Min(rect.Width, rect.Height) * 2 / 5;
float u = unit / 20f;
PointF[] points = new PointF[]
{
new PointF(-5, 0),
new PointF(-7, 1),
new PointF(-6, 5),
new PointF(-2, 8),
new PointF(2, 8),
new PointF(6, 5),
new PointF(7, 1),
new PointF(5, 0),
new PointF(0, 2)
};
for (int i = 0; i < points.Length; i++)
{
points[i].X *= u;
points[i].Y *= u;
}
g.TranslateTransform(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
g.FillEllipse(foreground, new Rectangle(-unit / 2, -unit / 2, unit, unit));
g.FillClosedCurve(background, points, System.Drawing.Drawing2D.FillMode.Winding, 0.5f);
g.FillEllipse(background, new Rectangle((int)(-7 * u), (int)(-7 * u), (int)(5 * u), (int)(5 * u)));
g.FillEllipse(background, new Rectangle((int)(2 * u), (int)(-7 * u), (int)(5 * u), (int)(5 * u)));
g.TranslateTransform(-(rect.Left + rect.Width / 2), -(rect.Top + rect.Height / 2));
g.SmoothingMode = osm;
}
internal static void DrawUpArrow(Graphics g, Rectangle rect, Brush background, Brush foreground)
{
SmoothingMode osm = g.SmoothingMode; // old smoothing mode, to restore it at the end.
g.SmoothingMode = SmoothingMode.AntiAlias;
int unit = Math.Min(rect.Width, rect.Height) / 2 / 4;
g.TranslateTransform(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
using (Pen p = new Pen(foreground, unit / 2f))
{
g.DrawLine(p, 0, -unit * 1.5f, 0, unit * 1.5f);
g.DrawLine(p, 0, -unit * 1.5f, -unit, 0);
g.DrawLine(p, 0, -unit * 1.5f, unit, 0);
}
g.TranslateTransform(-(rect.Left + rect.Width / 2), -(rect.Top + rect.Height / 2));
g.SmoothingMode = osm;
}
/// <summary>
/// Draws the key of a VirtualKeyboard.
/// </summary>
/// <param name="args">Provides context information.</param>
public override void DrawKey(KeyRendererEventArgs args)
{
Key key = args.Key;
if (ColorTable != null)
{
Rectangle rect = args.Bounds;
if (args.ClipRectangle.IntersectsWith(rect))
{
Brush keyBrush = ColorTable.KeysBrush;
if (key.Style == KeyStyle.Dark)
keyBrush = ColorTable.DarkKeysBrush;
else if (key.Style == KeyStyle.Light)
keyBrush = ColorTable.LightKeysBrush;
else if (key.Style == KeyStyle.Pressed)
keyBrush = ColorTable.PressedKeysBrush;
else if (key.Style == KeyStyle.Toggled)
keyBrush = ColorTable.KeysBrush;
if (args.IsDown)
keyBrush = ColorTable.DownKeysBrush;
Brush textBrush = ColorTable.TextBrush;
if (key.Style == KeyStyle.Toggled)
textBrush = ColorTable.ToggleTextBrush;
if (args.IsDown)
textBrush = ColorTable.DownTextBrush;
args.Graphics.FillRectangle(keyBrush, rect);
if (key.Info == "{BACKSPACE}")
{
DrawBackspaceSign(args.Graphics, rect, keyBrush, textBrush);
}
else if (key.Caption == ":-)")
{
DrawSmileySign(args.Graphics, rect, keyBrush, textBrush);
}
else if (key.Caption == "Shift")
{
DrawUpArrow(args.Graphics, rect, keyBrush, textBrush);
}
else
{
args.Graphics.DrawString(key.Caption, _KeyFont, textBrush, rect, _CenteredTextStringFormat);
if (key.Hint != null)
{
args.Graphics.DrawString(key.Hint, _HintFont, textBrush, rect, _TopCenteredTextStringFormat);
}
}
}
}
}
public override void DrawCloseButton(CloseButtonRendererEventArgs args)
{
Rectangle rect = args.Bounds;
rect.Inflate(-4, -4);
if (args.IsDown)
{
args.Graphics.FillRectangle(ColorTable.DownKeysBrush, args.Bounds);
using (Pen p = new Pen(ColorTable.DownTextBrush, 4))
{
args.Graphics.DrawLine(p, rect.Left, rect.Top, rect.Right, rect.Bottom);
args.Graphics.DrawLine(p, rect.Left, rect.Bottom, rect.Right, rect.Top);
}
}
else
{
//args.Graphics.FillRectangle(ColorTable.KeysBrush, args.Bounds);
using (Pen p = new Pen(ColorTable.TextBrush, 4))
{
args.Graphics.DrawLine(p, rect.Left, rect.Top, rect.Right, rect.Bottom);
args.Graphics.DrawLine(p, rect.Left, rect.Bottom, rect.Right, rect.Top);
}
}
}
public override void DrawTopBar(TopBarRendererEventArgs args)
{
args.Graphics.DrawString(args.Text, args.Font, ColorTable.TopBarTextBrush, args.Bounds);
}
}
/// <summary>
/// Provides data for Key rendering.
/// </summary>
public class KeyRendererEventArgs : EventArgs
{
/// <summary>
/// Gets a reference to the Key instance being rendered.
/// </summary>
public Key Key { get; private set; }
public Rectangle Bounds { get; private set; }
/// <summary>
/// Gets a reference to the Graphics object to be used for rendering.
/// </summary>
public Graphics Graphics { get; private set; }
/// <summary>
/// Gets a value indicating if this key is currently down.
/// </summary>
public bool IsDown { get; private set; }
/// <summary>
/// Gets the rectangle in which to paint.
/// </summary>
public Rectangle ClipRectangle { get; private set; }
/// <summary>
/// Creates a new instance and initializes it with provided values.
/// </summary>
/// <param name="graphics">The Graphics object to be used for rendering.</param>
/// <param name="key">The Key instance being rendered.</param>
/// <param name="isDown">Indicates if the key is currently hold down.</param>
/// <param name="clipRectangle">The rectangle in which to paint.</param>
public KeyRendererEventArgs(Graphics graphics, Key key, bool isDown, Rectangle clipRectangle, Rectangle bounds)
{
Key = key;
Graphics = graphics;
IsDown = isDown;
ClipRectangle = clipRectangle;
Bounds = bounds;
}
}
/// <summary>
/// Provides data for rendering the background of a VirtualKeyboard.
/// </summary>
public class BackgroundRendererEventArgs : EventArgs
{
public Rectangle Bounds { get; private set; }
/// <summary>
/// Gets a reference to the Graphics object to be used for rendering.
/// </summary>
public Graphics Graphics { get; private set; }
/// <summary>
/// Gets the rectangle in which to paint.
/// </summary>
public Rectangle ClipRectangle { get; private set; }
/// <summary>
/// Creates a new instance and initializes it with provided values.
/// </summary>
/// <param name="graphics">The Graphics object to be used for rendering.</param>
/// <param name="size">The area where the background should be drawn.</param>
public BackgroundRendererEventArgs(Graphics graphics, Rectangle clipRectangle, Rectangle bounds)
{
Graphics = graphics;
ClipRectangle = clipRectangle;
Bounds = bounds;
}
}
public class BeginFrameRendererEventArgs : EventArgs
{
/// <summary>
/// Gets a reference to the Graphics object to be used for rendering.
/// </summary>
public Graphics Graphics { get; private set; }
/// <summary>
/// Gets the rectangle in which to paint.
/// </summary>
public Rectangle ClipRectangle { get; private set; }
/// <summary>
/// Gets the size of the background area in which to render the keyboard.
/// </summary>
//public Size Size { get; private set; }
public Rectangle Bounds { get; private set; }
/// <summary>
/// Gets the font on the control.
/// </summary>
public Font Font { get; private set; }
/// <summary>
/// Gets the current KeyboardLayout which will be rendered in this frame.
/// </summary>
public KeyboardLayout Layout { get; private set; }
/// <summary>
/// Creates a new instance and initializes it with provided values.
/// </summary>
/// <param name="size">The size of the background area.</param>
/// <param name="font">The font of the control.</param>
/// <param name="layout">The current KeyboardLayout that will be rendered in this frame.</param>
public BeginFrameRendererEventArgs(Graphics graphics, Rectangle clipRectangle, Rectangle bounds, Font font, KeyboardLayout layout)
{
Graphics = graphics;
ClipRectangle = clipRectangle;
Bounds = bounds;
Font = font;
Layout = layout;
}
}
public class TopBarRendererEventArgs : EventArgs
{
public string Text { get; private set; }
public Rectangle Bounds { get; private set; }
/// <summary>
/// Gets a reference to the Graphics object to be used for rendering.
/// </summary>
public Graphics Graphics { get; private set; }
/// <summary>
/// Gets the rectangle in which to paint.
/// </summary>
public Rectangle ClipRectangle { get; private set; }
/// <summary>
/// Gets the font on the control.
/// </summary>
public Font Font { get; private set; }
public TopBarRendererEventArgs(Graphics graphics, Rectangle clipRectangle, Rectangle bounds, string text, Font font)
{
Graphics = graphics;
ClipRectangle = clipRectangle;
Bounds = bounds;
Text = text;
Font = font;
}
}
public class CloseButtonRendererEventArgs : EventArgs
{
public Rectangle Bounds { get; private set; }
/// <summary>
/// Gets a reference to the Key instance being rendered.
/// </summary>
public Graphics Graphics { get; private set; }
/// <summary>
/// Gets the area where background should be drawn.
/// </summary>
public Rectangle ClipRectangle { get; private set; }
/// <summary>
/// Gets a value indicating if this key is currently down.
/// </summary>
public bool IsDown { get; private set; }
public CloseButtonRendererEventArgs(Graphics graphics, bool isDown, Rectangle clipRectangle, Rectangle bounds)
{
Graphics = graphics;
ClipRectangle = clipRectangle;
Bounds = bounds;
IsDown = isDown;
}
}
}

View File

@@ -0,0 +1,916 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Data;
namespace DevComponents.DotNetBar.Touch
{
internal class TouchHandler
{
#region Events
public event EventHandler<GestureEventArgs> PanBegin;
/// <summary>
/// Raises PanBegin event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnPanBegin(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = PanBegin;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> PanEnd;
/// <summary>
/// Raises PanBegin event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnPanEnd(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = PanEnd;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> Pan;
/// <summary>
/// Raises PanBegin event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnPan(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = Pan;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> Begin;
/// <summary>
/// Raises Begin event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnBegin(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = Begin;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> End;
/// <summary>
/// Raises End event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnEnd(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = End;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> PressAndTap;
/// <summary>
/// Raises PressAndTap event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnPressAndTap(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = PressAndTap;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> RotateBegin;
/// <summary>
/// Raises RotateBegin event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnRotateBegin(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = RotateBegin;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> Rotate;
/// <summary>
/// Raises Rotate event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnRotate(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = Rotate;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> RotateEnd;
/// <summary>
/// Raises RotateEnd event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnRotateEnd(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = RotateEnd;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> TwoFingerTap;
/// <summary>
/// Raises TwoFingerTap event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnTwoFingerTap(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = TwoFingerTap;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> ZoomBegin;
/// <summary>
/// Raises ZoomBegin event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnZoomBegin(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = ZoomBegin;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> Zoom;
/// <summary>
/// Raises Zoom event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnZoom(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = Zoom;
if (handler != null)
handler(this, e);
}
public event EventHandler<GestureEventArgs> ZoomEnd;
/// <summary>
/// Raises ZoomEnd event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnZoomEnd(GestureEventArgs e)
{
EventHandler<GestureEventArgs> handler = ZoomEnd;
if (handler != null)
handler(this, e);
}
// Touch events
public event EventHandler<TouchEventArgs> TouchDown;
/// <summary>
/// Raises TouchDown event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnTouchDown(TouchEventArgs e)
{
EventHandler<TouchEventArgs> handler = TouchDown;
if (handler != null)
handler(this, e);
}
public event EventHandler<TouchEventArgs> TouchUp;
/// <summary>
/// Raises TouchDown event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnTouchUp(TouchEventArgs e)
{
EventHandler<TouchEventArgs> handler = TouchUp;
if (handler != null)
handler(this, e);
}
public event EventHandler<TouchEventArgs> TouchMove;
/// <summary>
/// Raises TouchDown event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnTouchMove(TouchEventArgs e)
{
EventHandler<TouchEventArgs> handler = TouchMove;
if (handler != null)
handler(this, e);
}
#endregion
#region Constructor
private Control _ParentControl = null;
private eTouchHandlerType _HandlerType = eTouchHandlerType.Gesture;
/// <summary>
/// Initializes a new instance of the TouchHandler class.
/// </summary>
/// <param name="parentControl"></param>
public TouchHandler(Control parentControl) : this(parentControl, eTouchHandlerType.Gesture) { }
/// <summary>
/// Initializes a new instance of the TouchHandler class.
/// </summary>
/// <param name="parentControl"></param>
public TouchHandler(Control parentControl, eTouchHandlerType handlerType)
{
_ParentControl = parentControl;
_HandlerType = handlerType;
if (IsTouchEnabled)
{
if (_ParentControl.IsHandleCreated)
Initialize();
else
_ParentControl.HandleCreated += new EventHandler(ParentControlHandleCreated);
}
}
#endregion
#region Implementation
void ParentControlHandleCreated(object sender, EventArgs e)
{
Initialize();
}
private IntPtr _originalWindowProcId;
private WinApi.WindowProcDelegate _windowProcDelegate;
/// <summary>
/// Initializes handler
/// </summary>
private void Initialize()
{
if (!RegisterTouchWindow())
{
throw new NotSupportedException("Cannot register window");
}
_windowProcDelegate = WindowProc;
_originalWindowProcId = IntPtr.Size == 4 ?
WinApi.SubclassWindow(_ParentControl.Handle, WinApi.GWLP_WNDPROC, _windowProcDelegate) :
WinApi.SubclassWindow64(_ParentControl.Handle, WinApi.GWLP_WNDPROC, _windowProcDelegate);
//take the desktop DPI
using (Graphics graphics = Graphics.FromHwnd(_ParentControl.Handle))
{
DpiX = graphics.DpiX;
DpiY = graphics.DpiY;
}
}
public Control ParentControl
{
get { return _ParentControl; }
}
/// <summary>
/// The Windows message handler.
/// </summary>
private uint WindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)
{
if(msg == WinApi.WM_TOUCH && (_HandlerType & eTouchHandlerType.Touch)== eTouchHandlerType.Touch)
{
foreach (TouchEventArgs arg in DecodeMessage(hWnd, msg, wParam, lParam, DpiX, DpiY))
{
if (arg.IsTouchDown)
OnTouchDown(arg);
if (arg.IsTouchMove)
OnTouchMove(arg);
if (arg.IsTouchUp)
OnTouchUp(arg);
}
return 1;
}
// Handle only gesture message
if (msg != WinApi.WM_GESTURE)
{
return WinApi.CallWindowProc(_originalWindowProcId, hWnd, msg, wParam, lParam);
}
WinApi.GESTUREINFO gestureInfo = new WinApi.GESTUREINFO();
gestureInfo.cbSize = (uint)Marshal.SizeOf(typeof(WinApi.GESTUREINFO));
bool result = WinApi.GetGestureInfo(lParam, ref gestureInfo);
if (!result)
throw new Exception("Cannot retrieve gesture information");
//Decode the gesture info and get the message event argument
GestureEventArgs eventArgs = new GestureEventArgs(this, ref gestureInfo);
try
{
//Fire the event using the event map
uint gestureId = GetGestureEventId(gestureInfo.dwID, gestureInfo.dwFlags);
if (gestureId == GestureEventId.Begin)
OnBegin(eventArgs);
else if (gestureId == GestureEventId.End)
OnEnd(eventArgs);
else if (gestureId == GestureEventId.Pan)
OnPan(eventArgs);
else if (gestureId == GestureEventId.PanBegin)
OnPanBegin(eventArgs);
else if (gestureId == GestureEventId.PanEnd)
OnPanEnd(eventArgs);
else if (gestureId == GestureEventId.PressAndTap)
OnPressAndTap(eventArgs);
else if (gestureId == GestureEventId.Rotate)
OnRotate(eventArgs);
else if (gestureId == GestureEventId.RotateBegin)
OnRotateBegin(eventArgs);
else if (gestureId == GestureEventId.RotateEnd)
OnRotateEnd(eventArgs);
else if (gestureId == GestureEventId.TwoFingerTap)
OnTwoFingerTap(eventArgs);
else if (gestureId == GestureEventId.Zoom)
OnZoom(eventArgs);
else if (gestureId == GestureEventId.ZoomBegin)
OnZoomBegin(eventArgs);
else if (gestureId == GestureEventId.ZoomEnd)
OnZoomEnd(eventArgs);
}
catch (ArgumentOutOfRangeException) //In case future releases will introduce new event values
{
}
//Keep the last message for relative calculations
LastEventArgs = eventArgs;
//Keep the first message for relative calculations
if (eventArgs.IsBegin)
LastBeginEventArgs = eventArgs;
WinApi.CloseGestureInfoHandle(lParam);
return 1;
}
/// <summary>
/// Decode the message and create a collection of event arguments
/// </summary>
private IEnumerable<TouchEventArgs> DecodeMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, float dpiX, float dpiY)
{
// More than one touch input can be associated with a touch message
int inputCount = WinApi.LoWord(wParam.ToInt32()); // Number of touch inputs, actual per-contact messages
WinApi.TOUCHINPUT[] inputs; // Array of TOUCHINPUT structures
inputs = new WinApi.TOUCHINPUT[inputCount]; // Allocate the storage for the parameters of the per-contact messages
try
{
// Unpack message parameters into the array of TOUCHINPUT structures, each representing a message for one single contact.
if (!WinApi.GetTouchInputInfo(lParam, inputCount, inputs, Marshal.SizeOf(inputs[0])))
{
// Touch info failed.
throw new Exception("Error calling GetTouchInputInfo API");
}
// For each contact, dispatch the message to the appropriate message handler.
// For WM_TOUCHDOWN you can get down & move notifications and for WM_TOUCHUP you can get up & move notifications
// WM_TOUCHMOVE will only contain move notifications and up & down notifications will never come in the same message
for (int i = 0; i < inputCount; i++)
{
TouchEventArgs touchEventArgs = new TouchEventArgs(this, dpiX, dpiY, ref inputs[i]);
yield return touchEventArgs;
}
}
finally
{
WinApi.CloseTouchInputHandle(lParam);
}
}
private GestureEventArgs _LastBeginEventArgs;
/// <summary>
/// The event arguments that started the current gesture
/// </summary>
internal GestureEventArgs LastBeginEventArgs
{
get { return _LastBeginEventArgs; }
set { _LastBeginEventArgs = value; }
}
/// <summary>
/// The last event in the current gesture event sequence
/// </summary>
private GestureEventArgs _LastEventArgs;
internal GestureEventArgs LastEventArgs
{
get { return _LastEventArgs; }
set { _LastEventArgs = value; }
}
private static class GestureEventId
{
public static readonly uint Begin = GetGestureEventId(WinApi.GID_BEGIN, 0);
public static readonly uint End = GetGestureEventId(WinApi.GID_END, 0);
public static readonly uint PanBegin = GetGestureEventId(WinApi.GID_PAN, WinApi.GF_BEGIN);
public static readonly uint Pan = GetGestureEventId(WinApi.GID_PAN, 0);
public static readonly uint PanEnd = GetGestureEventId(WinApi.GID_PAN, WinApi.GF_END);
public static readonly uint PressAndTap = GetGestureEventId(WinApi.GID_PRESSANDTAP, 0);
public static readonly uint RotateBegin = GetGestureEventId(WinApi.GID_ROTATE, WinApi.GF_BEGIN);
public static readonly uint Rotate = GetGestureEventId(WinApi.GID_ROTATE, 0);
public static readonly uint RotateEnd = GetGestureEventId(WinApi.GID_ROTATE, WinApi.GF_END);
public static readonly uint TwoFingerTap = GetGestureEventId(WinApi.GID_TWOFINGERTAP, 0);
public static readonly uint ZoomBegin = GetGestureEventId(WinApi.GID_ZOOM, WinApi.GF_BEGIN);
public static readonly uint Zoom = GetGestureEventId(WinApi.GID_ZOOM, 0);
public static readonly uint ZoomEnd = GetGestureEventId(WinApi.GID_ZOOM, WinApi.GF_END);
}
private static uint GetGestureEventId(uint dwID, uint dwFlags)
{
return (dwID << 3) + (dwID == WinApi.GID_TWOFINGERTAP || dwID == WinApi.GID_PRESSANDTAP
|| dwID == WinApi.GID_BEGIN || dwID == WinApi.GID_END ?
0 : dwFlags & 5);
}
/// <summary>
/// Register for touch event
/// </summary>
/// <returns>true if succeeded</returns>
private bool RegisterTouchWindow()
{
bool result = false;
if ((_HandlerType & eTouchHandlerType.Gesture) == eTouchHandlerType.Gesture)
{
WinApi.GESTURECONFIG[] gestureConfig = new WinApi.GESTURECONFIG[] { new WinApi.GESTURECONFIG(0, WinApi.GC_ALLGESTURES, 0) };
result = WinApi.SetGestureConfig(_ParentControl.Handle, 0, 1, gestureConfig, (uint)Marshal.SizeOf(typeof(WinApi.GESTURECONFIG)));
}
if ((_HandlerType & eTouchHandlerType.Touch) == eTouchHandlerType.Touch)
{
result |= WinApi.RegisterTouchWindow(_ParentControl.Handle, _DisablePalmRejection ? WinApi.TouchWindowFlag.WantPalm : 0);
}
return result;
}
private bool _DisablePalmRejection;
/// <summary>
/// Gets or sets whether palm rejection is enabled.
/// </summary>
public bool DisablePalmRejection
{
get
{
return _DisablePalmRejection;
}
set
{
if (_DisablePalmRejection == value)
return;
_DisablePalmRejection = value;
if (_ParentControl.IsHandleCreated)
{
WinApi.UnregisterTouchWindow(_ParentControl.Handle);
RegisterTouchWindow();
}
}
}
private float _DpiX;
public float DpiX
{
get { return _DpiX; }
set { _DpiX = value; }
}
private float _DpiY;
public float DpiY
{
get { return _DpiY; }
set { _DpiY = value; }
}
/// <summary>
/// Check if Multi-touch support device is ready
/// </summary>
public static bool IsTouchEnabled
{
get
{
return (WinApi.GetDigitizerStatus() & (WinApi.DigitizerStatus.StackReady | WinApi.DigitizerStatus.MultiInput)) != 0;
}
}
#endregion
}
[Flags]
internal enum eTouchHandlerType : short
{
Gesture = 1,
Touch = 2
}
internal class GestureEventArgs : EventArgs
{
private readonly uint _Flags;
/// <summary>
/// Create new gesture event instance and decode the gesture info structure
/// </summary>
/// <param name="handler">The gesture handler</param>
/// <param name="gestureInfo">The gesture information</param>
internal GestureEventArgs(TouchHandler handler, ref WinApi.GESTUREINFO gestureInfo)
{
_Flags = gestureInfo.dwFlags;
GestureId = gestureInfo.dwID;
GestureArguments = gestureInfo.ullArguments;
//Get the last event from the handler
LastEvent = handler.LastEventArgs;
//Get the last begin event from the handler
LastBeginEvent = handler.LastBeginEventArgs;
ParseGesture(handler.ParentControl, ref gestureInfo);
//new gesture, clear last and first event fields
if (IsBegin)
{
LastBeginEvent = null;
LastEvent = null;
}
}
//Decode the gesture
private void ParseGesture(Control parentControl, ref WinApi.GESTUREINFO gestureInfo)
{
Location = parentControl.PointToClient(new Point(gestureInfo.ptsLocation.x, gestureInfo.ptsLocation.y));
Center = Location;
switch (GestureId)
{
case WinApi.GID_ROTATE:
ushort lastArguments = (ushort)(IsBegin ? 0 : LastEvent.GestureArguments);
RotateAngle = WinApi.GID_ROTATE_ANGLE_FROM_ARGUMENT((ushort)(gestureInfo.ullArguments - lastArguments));
break;
case WinApi.GID_ZOOM:
Point first = IsBegin ? Location : LastBeginEvent.Location;
Center = new Point((Location.X + first.X) / 2, (Location.Y + first.Y) / 2);
ZoomFactor = IsBegin ? 1 : (double)gestureInfo.ullArguments / LastEvent.GestureArguments;
//DistanceBetweenFingers = WinApi.LoDWord(gestureInfo.ullArguments);
break;
case WinApi.GID_PAN:
PanTranslation = IsBegin ? new Size(0, 0) :
new Size(Location.X - LastEvent.Location.X, Location.Y - LastEvent.Location.Y);
int panVelocity = WinApi.HiDWord((long)(gestureInfo.ullArguments));
PanVelocity = new Size(WinApi.LoWord(panVelocity), WinApi.HiWord(panVelocity));
//DistanceBetweenFingers = WinApi.LoDWord(gestureInfo.ullArguments);
break;
}
}
private uint _GestureId;
public uint GestureId
{
get { return _GestureId; }
private set { _GestureId = value; }
}
private ulong _GestureArguments;
public ulong GestureArguments
{
get { return _GestureArguments; }
private set { _GestureArguments = value; }
}
private Point _Location;
/// <summary>
/// The client location of gesture.
/// </summary>
public Point Location
{
get { return _Location; }
private set { _Location = value; }
}
/// <summary>
/// Is this the first event of a gesture.
/// </summary>
public bool IsBegin
{
get
{
return (_Flags & WinApi.GF_BEGIN) != 0;
}
}
/// <summary>
/// It this last event of a gesture.
/// </summary>
public bool IsEnd
{
get
{
return (_Flags & WinApi.GF_END) != 0;
}
}
/// <summary>
/// Has gesture triggered inertia.
/// </summary>
public bool IsInertia
{
get
{
return (_Flags & WinApi.GF_INERTIA) != 0;
}
}
/// <summary>
/// Gesture relative rotation angle for Rotate event.
/// </summary>
private double _RotateAngle;
public double RotateAngle
{
get { return _RotateAngle; }
private set { _RotateAngle = value; }
}
/// <summary>
/// Indicates calculated gesture center.
/// </summary>
private Point _Center;
public Point Center
{
get { return _Center; }
private set { _Center = value; }
}
/// <summary>
/// Gesture zoom factor for Zoom event.
/// </summary>
private double _ZoomFactor;
public double ZoomFactor
{
get { return _ZoomFactor; }
private set { _ZoomFactor = value; }
}
/// <summary>
/// Gesture relative panning translation for Pan event.
/// </summary>
private Size _PanTranslation;
public Size PanTranslation
{
get { return _PanTranslation; }
set { _PanTranslation = value; }
}
/// <summary>
/// Gesture velocity vector of the pan gesture for custom inertia implementations.
/// </summary>
private Size _PanVelocity;
public Size PanVelocity
{
get { return _PanVelocity; }
private set { _PanVelocity = value; }
}
private GestureEventArgs _LastBeginEvent;
/// <summary>
/// The first touch arguments in this gesture event sequence.
/// </summary>
public GestureEventArgs LastBeginEvent
{
get { return _LastBeginEvent; }
internal set { _LastBeginEvent = value; }
}
/// <summary>
/// The last touch arguments in this gesture event sequence.
/// </summary>
private GestureEventArgs _LastEvent;
public GestureEventArgs LastEvent
{
get { return _LastEvent; }
internal set { _LastEvent = value; }
}
}
/// <summary>
/// EventArgs passed to Touch handlers
/// </summary>
internal class TouchEventArgs : EventArgs
{
private readonly TouchHandler _ParentHandler;
private readonly float _dpiXFactor;
private readonly float _dpiYFactor;
/// <summary>
/// Create new touch event argument instance
/// </summary>
/// <param name="hWndWrapper">The target control</param>
/// <param name="touchInput">one of the inner touch input in the message</param>
internal TouchEventArgs(TouchHandler parentHandler, float dpiX, float dpiY, ref WinApi.TOUCHINPUT touchInput)
{
_ParentHandler = parentHandler;
_dpiXFactor = 96F / dpiX;
_dpiYFactor = 96F / dpiY;
DecodeTouch(ref touchInput);
}
private bool CheckFlag(int value)
{
return (Flags & value) != 0;
}
// Decodes and handles WM_TOUCH* messages.
private void DecodeTouch(ref WinApi.TOUCHINPUT touchInput)
{
// TOUCHINFO point coordinates and contact size is in 1/100 of a pixel; convert it to pixels.
// Also convert screen to client coordinates.
if ((touchInput.dwMask & WinApi.TOUCHINPUTMASKF_CONTACTAREA) != 0)
ContactSize = new Size(AdjustDpiX(touchInput.cyContact / 100), AdjustDpiY(touchInput.cyContact / 100));
Id = touchInput.dwID;
Point p = _ParentHandler.ParentControl.PointToClient(new Point(touchInput.x / 100, touchInput.y / 100));
Location = p; // new Point(AdjustDpiX(p.X), AdjustDpiY(p.Y));
Time = touchInput.dwTime;
TimeSpan ellapse = TimeSpan.FromMilliseconds(Environment.TickCount - touchInput.dwTime);
AbsoluteTime = DateTime.Now - ellapse;
Mask = touchInput.dwMask;
Flags = touchInput.dwFlags;
}
private int AdjustDpiX(int value)
{
return (int)(value * _dpiXFactor);
}
private int AdjustDpiY(int value)
{
return (int)(value * _dpiYFactor);
}
/// <summary>
/// Touch client coordinate in pixels
/// </summary>
private Point _Location;
public Point Location
{
get { return _Location; }
private set
{
_Location = value;
}
}
/// <summary>
/// A touch point identifier that distinguishes a particular touch input
/// </summary>
private int _Id;
public int Id
{
get { return _Id; }
private set
{
_Id = value;
}
}
/// <summary>
/// A set of bit flags that specify various aspects of touch point
/// press, release, and motion.
/// </summary>
private int _Flags;
public int Flags
{
get { return _Flags; }
private set
{
_Flags = value;
}
}
/// <summary>
/// mask which fields in the structure are valid
/// </summary>
private int _Mask;
public int Mask
{
get { return _Mask; }
private set
{
_Mask = value;
}
}
/// <summary>
/// touch event time
/// </summary>
private DateTime _AbsoluteTime;
public DateTime AbsoluteTime
{
get { return _AbsoluteTime; }
private set { _AbsoluteTime = value; }
}
/// <summary>
/// touch event time from system up
/// </summary>
private int _Time;
public int Time
{
get { return _Time; }
private set
{
_Time = value;
}
}
/// <summary>
/// the size of the contact area in pixels
/// </summary>
private Size? _ContactSize;
public Size? ContactSize
{
get { return _ContactSize; }
private set { _ContactSize = value; }
}
/// <summary>
/// Is Primary Contact (The first touch sequence)
/// </summary>
public bool IsPrimaryContact
{
get { return (Flags & WinApi.TOUCHEVENTF_PRIMARY) != 0; }
}
/// <summary>
/// Specifies that movement occurred
/// </summary>
public bool IsTouchMove
{
get { return CheckFlag(WinApi.TOUCHEVENTF_MOVE); }
}
/// <summary>
/// Specifies that the corresponding touch point was established through a new contact
/// </summary>
public bool IsTouchDown
{
get { return CheckFlag(WinApi.TOUCHEVENTF_DOWN); }
}
/// <summary>
/// Specifies that a touch point was removed
/// </summary>
public bool IsTouchUp
{
get { return CheckFlag(WinApi.TOUCHEVENTF_UP); }
}
/// <summary>
/// Specifies that a touch point is in range
/// </summary>
public bool IsTouchInRange
{
get { return CheckFlag(WinApi.TOUCHEVENTF_INRANGE); }
}
/// <summary>
/// specifies that this input was not coalesced.
/// </summary>
public bool IsTouchNoCoalesce
{
get { return CheckFlag(WinApi.TOUCHEVENTF_NOCOALESCE); }
}
/// <summary>
/// Specifies that the touch point is associated with a pen contact
/// </summary>
public bool IsTouchPen
{
get { return CheckFlag(WinApi.TOUCHEVENTF_PEN); }
}
/// <summary>
/// The touch event came from the user's palm
/// </summary>
/// <remarks>Set <see cref="DisablePalmRejection"/> to true</remarks>
public bool IsTouchPalm
{
get { return CheckFlag(WinApi.TOUCHEVENTF_PALM); }
}
}
}

View File

@@ -0,0 +1,290 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DevComponents.DotNetBar.Touch
{
internal class WinApi
{
#region Functions
[DllImport("user32")]
public static extern bool SetGestureConfig(
IntPtr hwnd, // window for which configuration is specified
uint dwReserved, // reserved, must be 0
uint cIDs, // count of GESTURECONFIG structures
GESTURECONFIG[] pGestureConfig, // array of GESTURECONFIG structures, dwIDs will be processed in the
// order specified and repeated occurances will overwrite previous ones
uint cbSize); // sizeof(GESTURECONFIG)
[DllImport("user32")]
public static extern bool RegisterTouchWindow(System.IntPtr hWnd, TouchWindowFlag flags);
[DllImport("user32")]
public static extern bool UnregisterTouchWindow(System.IntPtr hWnd);
[DllImport("user32")]
public static extern bool IsTouchWindow(System.IntPtr hWnd, out uint ulFlags);
[DllImport("user32")]
public static extern bool GetTouchInputInfo(System.IntPtr hTouchInput, int cInputs, [In, Out] TOUCHINPUT[] pInputs, int cbSize);
[DllImport("user32")]
public static extern void CloseTouchInputHandle(System.IntPtr lParam);
[DllImport("user32")]
public static extern bool SetProp(IntPtr hWnd, string lpString, IntPtr hData);
//Touch
[DllImport("user32", EntryPoint = "GetSystemMetrics")]
public static extern int GetDigitizerCapabilities(DigitizerIndex index);
[DllImport("user32")]
public static extern bool GetGestureInfo(IntPtr hGestureInfo, ref GESTUREINFO pGestureInfo);
[DllImport("user32")]
public static extern bool CloseGestureInfoHandle(IntPtr hGestureInfo);
[DllImport("user32", EntryPoint = "SetWindowLongPtr")]
public static extern IntPtr SubclassWindow64(IntPtr hWnd, int nIndex, WindowProcDelegate dwNewLong);
[DllImport("user32", EntryPoint = "SetWindowLong")]
public static extern IntPtr SubclassWindow(IntPtr hWnd, int nIndex, WindowProcDelegate dwNewLong);
[DllImport("user32")]
public static extern uint CallWindowProc(IntPtr prevWndFunc, IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam);
public delegate uint WindowProcDelegate(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam);
/// <summary>
/// Get the current Digitizer Status
/// </summary>
public static DigitizerStatus GetDigitizerStatus()
{
return (DigitizerStatus)GetDigitizerCapabilities(DigitizerIndex.SM_DIGITIZER);
}
#endregion
#region Structures & Constants
[StructLayout(LayoutKind.Sequential)]
public struct GESTURECONFIG
{
public uint dwID; // gesture ID
public uint dwWant; // settings related to gesture ID that are to be turned on
public uint dwBlock; // settings related to gesture ID that are to be turned off
/// <summary>
/// Initializes a new instance of the GESTURECONFIG structure.
/// </summary>
/// <param name="dwID"></param>
/// <param name="dwWant"></param>
/// <param name="dwBlock"></param>
public GESTURECONFIG(uint dwID, uint dwWant, uint dwBlock)
{
this.dwID = dwID;
this.dwWant = dwWant;
this.dwBlock = dwBlock;
}
}
/// <summary>
/// Specifies available digitizer capabilities
/// </summary>
[Flags]
public enum DigitizerStatus : byte
{
IntegratedTouch = 0x01,
ExternalTouch = 0x02,
IntegratedPan = 0x04,
ExternalPan = 0x08,
MultiInput = 0x40,
StackReady = 0x80
}
public enum DigitizerIndex
{
SM_DIGITIZER = 94,
SM_MAXIMUMTOUCHES = 95
}
public const int GWLP_WNDPROC = -4;
// Gesture argument helpers
// - Angle should be a double in the range of -2pi to +2pi
// - Argument should be an unsigned 16-bit value
//
public static ushort GID_ROTATE_ANGLE_TO_ARGUMENT(ushort arg) { return ((ushort)(((arg + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65535.0)); }
public static double GID_ROTATE_ANGLE_FROM_ARGUMENT(ushort arg) { return ((((double)arg / 65535.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265); }
//Gesture flags - GESTUREINFO.dwFlags
public const uint GF_BEGIN = 0x00000001;
public const uint GF_INERTIA = 0x00000002;
public const uint GF_END = 0x00000004;
//Gesture IDs
public const uint GID_BEGIN = 1;
public const uint GID_END = 2;
public const uint GID_ZOOM = 3;
public const uint GID_PAN = 4;
public const uint GID_ROTATE = 5;
public const uint GID_TWOFINGERTAP = 6;
public const uint GID_PRESSANDTAP = 7;
public const uint GC_ALLGESTURES = 0x00000001;
public const uint WM_GESTURE = 0x0119;
public const uint WM_GESTURENOTIFY = 0x011A;
// Touch event window message constants [winuser.h]
public const int WM_TOUCH = 0x0240;
// Touch input mask values (TOUCHINPUT.dwMask) [winuser.h]
public const int TOUCHINPUTMASKF_TIMEFROMSYSTEM = 0x0001; // the dwTime field contains a system generated value
public const int TOUCHINPUTMASKF_EXTRAINFO = 0x0002; // the dwExtraInfo field is valid
public const int TOUCHINPUTMASKF_CONTACTAREA = 0x0004; // the cxContact and cyContact fields are valid
// Touch event flags ((TOUCHINPUT.dwFlags) [winuser.h]
public const int TOUCHEVENTF_MOVE = 0x0001;
public const int TOUCHEVENTF_DOWN = 0x0002;
public const int TOUCHEVENTF_UP = 0x0004;
public const int TOUCHEVENTF_INRANGE = 0x0008;
public const int TOUCHEVENTF_PRIMARY = 0x0010;
public const int TOUCHEVENTF_NOCOALESCE = 0x0020;
public const int TOUCHEVENTF_PEN = 0x0040;
public const int TOUCHEVENTF_PALM = 0x0080;
public enum TouchWindowFlag : uint
{
FineTouch = 0x1,
WantPalm = 0x2
}
/// <summary>
/// Gesture Info Interop Structure
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct GESTUREINFO
{
public uint cbSize; // size, in bytes, of this structure (including variable length Args field)
public uint dwFlags; // see GF_* flags
public uint dwID; // gesture ID, see GID_* defines
public IntPtr hwndTarget; // handle to window targeted by this gesture
public POINTS ptsLocation; // current location of this gesture
public uint dwInstanceID; // internally used
public uint dwSequenceID; // internally used
public ulong ullArguments; // arguments for gestures whose arguments fit in 8 BYTES
public uint cbExtraArgs; // size, in bytes, of extra arguments, if any, that accompany this gesture
}
/// <summary>
/// A Simple POINTS Interop structure
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct POINTS
{
public short x;
public short y;
}
/// <summary>
/// A Simple POINT Interop structure
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
/// <summary>
/// Touch API defined structures [winuser.h]
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TOUCHINPUT
{
public int x;
public int y;
public System.IntPtr hSource;
public int dwID;
public int dwFlags;
public int dwMask;
public int dwTime;
public System.IntPtr dwExtraInfo;
public int cxContact;
public int cyContact;
}
// Extracts lower 16-bit word from an 32-bit int.
// in:
// number int
// returns:
// lower word
public static ushort LoWord(uint number)
{
return (ushort)(number & 0xffff);
}
// Extracts higher 16-bit word from an 32-bit int.
// in:
// number uint
// returns:
// lower word
public static ushort HiWord(uint number)
{
return (ushort)((number >> 16) & 0xffff);
}
// Extracts lower 32-bit word from an 64-bit int.
// in:
// number ulong
// returns:
// lower word
public static uint LoDWord(ulong number)
{
return (uint)(number & 0xffffffff);
}
// Extracts higher 32-bit word from an 64-bit int.
// in:
// number ulong
// returns:
// lower word
public static uint HiDWord(ulong number)
{
return (uint)((number >> 32) & 0xffffffff);
}
// Extracts lower 16-bit word from an 32-bit int.
// in:
// number int
// returns:
// lower word
public static short LoWord(int number)
{
return (short)number;
}
// Extracts higher 16-bit word from an 32-bit int.
// in:
// number int
// returns:
// lower word
public static short HiWord(int number)
{
return (short)(number >> 16);
}
// Extracts lower 32-bit word from an 64-bit int.
// in:
// number long
// returns:
// lower word
public static int LoDWord(long number)
{
return (int)(number);
}
// Extracts higher 32-bit word from an 64-bit int.
// in:
// number long
// returns:
// lower word
public static int HiDWord(long number)
{
return (int)((number >> 32));
}
#endregion
}
}

View File

@@ -0,0 +1,801 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace DevComponents.DotNetBar.Keyboard
{
[ToolboxItem(true), ProvideProperty("ShowTouchKeyboard", typeof(Control))]
public class TouchKeyboard : Component, IExtenderProvider
{
private List<Control> _Targets = new List<Control>();
private Control _CurrentTarget;
private PopupVirtualKeyboard _PopupKeyboard;
private KeyboardControl _VirtualKeyboard;
public TouchKeyboard()
{
_PopupKeyboard = new PopupVirtualKeyboard();
_VirtualKeyboard = new KeyboardControl();
//_PopupKeyboard.Size = Dpi.Size(new Size(KeyboardControl.DefaultWidth, KeyboardControl.DefaultHeight));
// Track floating keyboard location and size changed. The user can change this at runtime with the mouse.
//_PopupKeyboard.SizeChanged += new EventHandler(PopupKeyboard_SizeChanged);
_PopupKeyboard.ResizeEnd += PopupKeyboard_ResizeEnd;
_PopupKeyboard.LocationChanged += new EventHandler(PopupKeyboard_LocationChanged);
// Track changes when the keyboard is inline.
_VirtualKeyboard.SizeChanged += new EventHandler(VirtualKeyboard_SizeChanged);
_VirtualKeyboard.LocationChanged += new EventHandler(VirtualKeyboard_LocationChanged);
_VirtualKeyboard.DockChanged += new EventHandler(VirtualKeyboard_DockChanged);
_VirtualKeyboard.SendingKey += new KeyCancelEventHandler(VirtualKeyboardSendingKey);
_VirtualKeyboard.KeySent += new KeyEventHandler(VirtualKeyboardKeySent);
}
#region Handle Changed events.
/// <summary>
/// Occurs before the key pressed on keyboard is sent to target control and allows cancellation of the message
/// </summary>
[Description("Occurs before the key pressed on keyboard is sent to target control and allows cancellation of the message.")]
public event KeyCancelEventHandler SendingKey;
/// <summary>
/// Raises SendingKey event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnSendingKey(KeyboardKeyCancelEventArgs e)
{
KeyCancelEventHandler handler = SendingKey;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs after the key is sent to target control.
/// </summary>
[Description("Occurs after the key is sent to target control.")]
public event KeyEventHandler KeySent;
/// <summary>
/// Raises KeySent event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeySent(KeyboardKeyEventArgs e)
{
KeyEventHandler handler = KeySent;
if (handler != null)
handler(this, e);
}
private void VirtualKeyboardKeySent(object sender, KeyboardKeyEventArgs e)
{
OnKeySent(e);
}
private void VirtualKeyboardSendingKey(object sender, KeyboardKeyCancelEventArgs e)
{
OnSendingKey(e);
}
void PopupKeyboard_ResizeEnd(object sender, EventArgs e)
{
_FloatingSize = _PopupKeyboard.Size;
OnFloatingSizeChanged();
}
//void PopupKeyboard_SizeChanged(object sender, EventArgs e)
//{
// _FloatingSize = _PopupKeyboard.Size;
// OnFloatingSizeChanged();
//}
void PopupKeyboard_LocationChanged(object sender, EventArgs e)
{
OnFloatingLocationChanged();
}
void VirtualKeyboard_LocationChanged(object sender, EventArgs e)
{
if (_VirtualKeyboard.FindForm() != _PopupKeyboard)
{
OnLocationChanged();
}
}
void VirtualKeyboard_SizeChanged(object sender, EventArgs e)
{
if (_VirtualKeyboard.FindForm() != _PopupKeyboard)
{
_Size = _VirtualKeyboard.Size;
OnSizeChanged();
}
}
void VirtualKeyboard_DockChanged(object sender, EventArgs e)
{
if (_VirtualKeyboard.FindForm() != _PopupKeyboard)
{
OnDockChanged();
}
}
#endregion
/// <summary>
/// Gets the reference to internal keyboard control that is used to provide Keyboard visual.
/// </summary>
[Browsable(false)]
public KeyboardControl KeyboardControl
{
get
{
return _VirtualKeyboard;
}
}
/// <summary>
/// Attaches the Keyboard to the specified control. The keyboard will automatically appear when the control receives input focus.
/// </summary>
/// <param name="control">The control to which the Keyboard will be attached.</param>
private void AttachTo(Control control)
{
control.GotFocus += new EventHandler(control_GotFocus);
control.LostFocus += new EventHandler(control_LostFocus);
_Targets.Add(control);
}
/// <summary>
/// Detaches the Keyboard from the specified control.
/// </summary>
/// <param name="control">The control from which the Keyboard will be detached.</param>
private void DetachFrom(Control control)
{
if (_Targets.Contains(control))
{
control.GotFocus -= new EventHandler(control_GotFocus);
control.LostFocus -= new EventHandler(control_LostFocus);
_Targets.Remove(control);
}
}
/// <summary>
/// Occurs before keyboard is shown and allows canceling of opening.
/// </summary>
[Description("Occurs before keyboard is shown and allows canceling of opening.")]
public event CancelKeyboardEventHandler KeyboardOpening;
/// <summary>
/// Raises KeyboardOpening event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeyboardOpening(CancelKeyboardEventArgs e)
{
CancelKeyboardEventHandler handler = KeyboardOpening;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs after keyboard is shown.
/// </summary>
[Description("Occurs after keyboard is shown.")]
public event EventHandler KeyboardOpened;
/// <summary>
/// Raises KeyboardOpened event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeyboardOpened(EventArgs e)
{
EventHandler handler = KeyboardOpened;
if (handler != null)
handler(this, e);
}
private bool _ShowingFloatingKeyboard = false;
public void ShowKeyboard(Control control, TouchKeyboardStyle style)
{
CancelKeyboardEventArgs ce = new CancelKeyboardEventArgs(control, style);
OnKeyboardOpening(ce);
if (ce.Cancel) return;
_CurrentTarget = ce.TargetControl;
style = ce.Style;
_PopupKeyboard.CurrentControl = _CurrentTarget;
_VirtualKeyboard.UnlockCapsLock();
if (_CurrentTarget != null)
{
if (style == TouchKeyboardStyle.Floating)
{
try
{
if (_FloatingSize.IsEmpty)
_PopupKeyboard.Size = Dpi.Size(new Size(KeyboardControl.DefaultWidth, KeyboardControl.DefaultHeight));
else
_PopupKeyboard.Size = _FloatingSize;
_ShowingFloatingKeyboard = true;
_PopupKeyboard.Owner = _CurrentTarget.FindForm();
_PopupKeyboard.Controls.Add(_VirtualKeyboard);
_VirtualKeyboard.Dock = DockStyle.Fill;
_VirtualKeyboard.Visible = true;
_PopupKeyboard.Show();
// When floating, don't show the top bar. The information on the top bar are on the window's title bar.
_VirtualKeyboard.IsTopBarVisible = false;
}
finally
{
_ShowingFloatingKeyboard = false;
}
}
else if (style == TouchKeyboardStyle.Inline)
{
Form owner = _CurrentTarget.FindForm();
if (_Size.IsEmpty)
_VirtualKeyboard.Size = Dpi.Size(new Size(KeyboardControl.DefaultWidth, KeyboardControl.DefaultHeight));
else
_VirtualKeyboard.Size = _Size;
_VirtualKeyboard.Dock = Dock;
owner.Controls.Add(_VirtualKeyboard);
_VirtualKeyboard.BringToFront();
_VirtualKeyboard.Visible = true;
// When inline, show the top bar.
_VirtualKeyboard.IsTopBarVisible = true;
}
}
OnKeyboardOpened(EventArgs.Empty);
}
/// <summary>
/// Gets keyboard target control.
/// </summary>
[Browsable(false)]
public Control CurrentKeyboardTarget
{
get { return _CurrentTarget; }
}
/// <summary>
/// Occurs before the keyboard is closed and allows canceling of keyboard closing.
/// </summary>
[Description("Occurs before the keyboard is closed and allows canceling of keyboard closing.")]
public event CancelEventHandler KeyboardClosing;
/// <summary>
/// Raises KeyboardClosing event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeyboardClosing(CancelEventArgs e)
{
CancelEventHandler handler = KeyboardClosing;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs after keyboard is closed.
/// </summary>
[Description("Occurs after keyboard is closed.")]
public event EventHandler KeyboardClosed;
/// <summary>
/// Raises KeyboardClosed event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnKeyboardClosed(EventArgs e)
{
EventHandler handler = KeyboardClosed;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Hides the keyboard.
/// </summary>
public void HideKeyboard()
{
CancelEventArgs ce = new CancelEventArgs();
OnKeyboardClosing(ce);
if (ce.Cancel) return;
_PopupKeyboard.Hide();
Form form = _VirtualKeyboard.FindForm();
if (form != null && !(form is PopupVirtualKeyboard))
{
form.Controls.Remove(_VirtualKeyboard);
}
OnKeyboardClosed(EventArgs.Empty);
}
/// <summary>
/// Gets reference to the form which hosts popup keyboard.
/// </summary>
public Form FloatingKeyboardForm
{
get { return _PopupKeyboard; }
}
void control_GotFocus(object sender, EventArgs e)
{
Control control = sender as Control;
if (control != null)
{
TouchKeyboardStyle style = TouchKeyboardStyle.No;
TouchKeyboardStyle formStyle = GetShowTouchKeyboard(control.FindForm());
// If the form specifies a mode to show the keyboard, then use that mode. If we want for the control to have the last
// word about how to show the keyboard, the following two if instructions should be inverted.
if (_ExtendedControls.ContainsKey(control))
style = _ExtendedControls[control];
if (formStyle != TouchKeyboardStyle.No)
style = formStyle;
if (style != TouchKeyboardStyle.No)
{
ShowKeyboard(control, style);
}
}
}
private bool IsPopupKeyboardActivated
{
get
{
if (_PopupKeyboard == null) return false;
return Form.ActiveForm == _PopupKeyboard;
}
}
void control_LostFocus(object sender, EventArgs e)
{
if (!_ShowingFloatingKeyboard && !IsPopupKeyboardActivated)
{
_CurrentTarget = null;
HideKeyboard();
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_VirtualKeyboard != null)
_VirtualKeyboard.Dispose();
if (_PopupKeyboard != null)
_PopupKeyboard.Dispose();
}
base.Dispose(disposing);
}
bool IExtenderProvider.CanExtend(object extendee)
{
if (extendee is Control && !(extendee is KeyboardControl))
return true;
else
return false;
}
Dictionary<Control, TouchKeyboardStyle> _ExtendedControls = new Dictionary<Control, TouchKeyboardStyle>();
/// <summary>
/// Retursn the way the keyboard will be shown when controls receive focus.
/// </summary>
/// <param name="extendee">The control for which to retrieve the value.</param>
/// <returns>A TouchKeyboardStyle value defining the way the keyboard appears.</returns>
[Description("Shows an on screen touch keyboard when the control is focused.")]
[Category("Touch Keyboard")]
[DefaultValue(TouchKeyboardStyle.No)]
public TouchKeyboardStyle GetShowTouchKeyboard(Control extendee)
{
if (extendee == null)
return TouchKeyboardStyle.No;
if (_ExtendedControls.ContainsKey(extendee))
return _ExtendedControls[extendee];
else
return TouchKeyboardStyle.No;
}
/// <summary>
/// Sets the way the keyboard will be shown when controls receive focus. If the control is a Form,
/// all controls on the Form will support this way of displaying the touch keyboard.
/// </summary>
/// <param name="extendee">The control for which this value is specified.</param>
/// <param name="value">A TouchKeyboardStyle value defining the way the keyboard appears.</param>
public void SetShowTouchKeyboard(Control extendee, TouchKeyboardStyle value)
{
if (extendee is Form)
{
if (value != TouchKeyboardStyle.No)
{
foreach (Control c in extendee.Controls)
{
AttachTo(c);
}
// If other controls are added to the form, attach to those controls also.
extendee.ControlAdded += new ControlEventHandler(form_ControlAdded);
// If controls are removed from the form, dettach from them, we don't want to keep a reference to them.
extendee.ControlRemoved += new ControlEventHandler(form_ControlRemoved);
}
}
if (!_ExtendedControls.ContainsKey(extendee))
_ExtendedControls.Add(extendee, value);
else
_ExtendedControls[extendee] = value;
if (value == TouchKeyboardStyle.No)
DetachFrom(extendee);
else
AttachTo(extendee);
}
void form_ControlAdded(object sender, ControlEventArgs e)
{
if (sender is KeyboardControl)
return;
AttachTo(e.Control);
}
void form_ControlRemoved(object sender, ControlEventArgs e)
{
if (sender is KeyboardControl)
return;
DetachFrom(e.Control);
}
/// <summary>
/// Gets or set the ColorTable used to draw the keyboard.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public VirtualKeyboardColorTable ColorTable
{
get { return _VirtualKeyboard.ColorTable; }
set { _VirtualKeyboard.ColorTable = value; }
}
/// <summary>
/// Gets or set the Renderer used to draw the keyboard.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Renderer Renderer
{
get { return _VirtualKeyboard.Renderer; }
set { _VirtualKeyboard.Renderer = value; }
}
private Size _Size = Size.Empty; //new Size(KeyboardControl.DefaultWidth, KeyboardControl.DefaultHeight);
/// <summary>
/// Gets or sets the size of the keyboard, when shown inline.
/// </summary>
[Category("Inline Layout")]
[Description("Gets or sets the size of the keyboard, when the keyboard is shown inline.")]
[Browsable(true)]
public Size Size
{
get { return _Size; }
set
{
if (_Size != value)
{
_Size = value;
OnSizeChanged();
}
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeSize()
{
return !_Size.IsEmpty;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetSize()
{
Size = Size.Empty;
}
private void OnSizeChanged()
{
Size newSize = Size;
if (newSize.IsEmpty)
newSize = Dpi.Size(new Size(KeyboardControl.DefaultWidth, KeyboardControl.DefaultHeight));
_VirtualKeyboard.Size = newSize;
if (SizeChanged != null)
SizeChanged(this, EventArgs.Empty);
}
/// <summary>
/// Gets or sets the coordinates of the upper-left corner of the keyboard when shown inline, relative to the form.
/// </summary>
[Category("Inline Layout")]
[Description("The coordinates of the upper-left corner of the keyboard, when the keyboard is shown inline, relative to the form.")]
[Browsable(true)]
public Point Location
{
get { return _VirtualKeyboard.Location; }
set
{
if (_VirtualKeyboard.Location != value)
{
_VirtualKeyboard.Location = value;
OnLocationChanged();
}
}
}
private void OnLocationChanged()
{
if (LocationChanged != null)
LocationChanged(this, EventArgs.Empty);
}
private DockStyle _Dock = DockStyle.Bottom;
/// <summary>
/// Defines which borders of the keyboard are bound to the container.
/// </summary>
[Category("Inline Layout")]
[Description("Defines which border of the keyboard are bound to the form, when the keyboard is shown inline. Default value is DockStyle.Bottom.")]
[DefaultValue(DockStyle.Bottom)]
[Browsable(true)]
public DockStyle Dock
{
get { return _Dock; }
set
{
if (_Dock != value)
{
_Dock = value;
OnDockChanged();
}
}
}
private void OnDockChanged()
{
// When keybaord style is Floating, dock is always fill (to fill to popup window).
if (_PopupKeyboard.Controls.Contains(_VirtualKeyboard))
_VirtualKeyboard.Dock = DockStyle.Fill;
else
_VirtualKeyboard.Dock = _Dock;
if (DockChanged != null)
DockChanged(this, EventArgs.Empty);
}
/// <summary>
/// Gets or sets the coordinates of the upper-left corner of the keyboard when shown floating, relative to the screen.
/// </summary>
[Category("Floating Layout")]
[Description("The coordinates of the upper-left corner of the keyboard, when the keyboard is shown floating, relative to the screen.")]
[Browsable(true)]
public Point FloatingLocation
{
get { return _PopupKeyboard.Location; }
set
{
if (_PopupKeyboard.Location != value)
{
_PopupKeyboard.Location = value;
OnFloatingLocationChanged();
}
}
}
private void OnFloatingLocationChanged()
{
if (FloatingLocationChanged != null)
FloatingLocationChanged(this, EventArgs.Empty);
}
/// <summary>
/// Indicates whether touch support is enabled when provided by hardware.
/// </summary>
[DefaultValue(true), Category("Behavior"), Description("Indicates whether touch support is enabled when provided by hardware.")]
public bool TouchEnabled
{
get { return _VirtualKeyboard.TouchEnabled; }
set
{
_VirtualKeyboard.TouchEnabled = value;
}
}
private Size _FloatingSize = System.Drawing.Size.Empty;
/// <summary>
/// Gets or sets the size of the keyboard, when shown floating.
/// </summary>
[Category("Floating Layout")]
[Description("Gets or sets the size of the keyboard, when the keyboard is shown floating.")]
[Browsable(true)]
public Size FloatingSize
{
get { return _FloatingSize; }
set
{
if (_FloatingSize != value)
{
_FloatingSize = value;
OnFloatingSizeChanged();
}
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeFloatingSize()
{
return !_FloatingSize.IsEmpty;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetFloatingSize()
{
FloatingSize = Size.Empty;
}
private void OnFloatingSizeChanged()
{
Size newSize = FloatingSize;
if (newSize.IsEmpty)
newSize = Dpi.Size(new Size(KeyboardControl.DefaultWidth, KeyboardControl.DefaultHeight));
_PopupKeyboard.Size = newSize;
if (FloatingSizeChanged != null)
FloatingSizeChanged(this, EventArgs.Empty);
}
/// <summary>
/// Gets or sets a text associated with this control.
/// </summary>
[Category("Appearance")]
[Description("The text associated with this control.")]
[Browsable(true)]
public string Text
{
get { return _VirtualKeyboard.Text; }
set
{
_VirtualKeyboard.Text = value;
_PopupKeyboard.Text = value;
OnTextChanged();
}
}
/// <summary>
/// Raises the TextChanged event.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected void OnTextChanged()
{
if (TextChanged != null)
TextChanged(this, EventArgs.Empty);
}
/// <summary>
/// Occurs when the Text property has changed.
/// </summary>
[Category("PropertyChanged")]
[Description("Event raised when the Text property has changed.")]
public event EventHandler TextChanged;
/// <summary>
/// Occurs when the Size property has changed.
/// </summary>
[Category("Inline Layout")]
[Description("Event raised when the Size property has changed.")]
public event EventHandler SizeChanged;
/// <summary>
/// Occurs when the Location property has changed.
/// </summary>
[Category("Inline Layout")]
[Description("Event raised when the Location property has changed.")]
public event EventHandler LocationChanged;
/// <summary>
/// Occurs when the Dock property has changed.
/// </summary>
[Category("Inline Layout")]
[Description("Event raised when the Dock property has changed.")]
public event EventHandler DockChanged;
/// <summary>
/// Occurs when the FloatingSize property has changed.
/// </summary>
[Category("Floating Layout")]
[Description("Event raised when the FloatingSize property has changed.")]
public event EventHandler FloatingSizeChanged;
/// <summary>
/// Occurs when the FloatingLocation property has changed.
/// </summary>
[Category("Floating Layout")]
[Description("Event raised when the FloatingLocation property has changed.")]
public event EventHandler FloatingLocationChanged;
}
/// <summary>
/// Defines the way the touch keyboard will appear when attached to controls.
/// </summary>
public enum TouchKeyboardStyle
{
/// <summary>
/// Touch keyboard will not be visible.
/// </summary>
No,
/// <summary>
/// Touch keyboard will appear inline in the form.
/// </summary>
Inline,
/// <summary>
/// Touch keyboard will appear floating on the screen.
/// </summary>
Floating
}
/// <summary>
/// Defines delegate for keyboard events.
/// </summary>
public delegate void CancelKeyboardEventHandler(object sender, CancelKeyboardEventArgs e);
/// <summary>
/// Defines event arguments for keyboard based events.
/// </summary>
public class CancelKeyboardEventArgs : CancelEventArgs
{
/// <summary>
/// Initializes a new instance of the CancelKeyboardEventArgs class.
/// </summary>
/// <param name="targetControl"></param>
/// <param name="style"></param>
public CancelKeyboardEventArgs(Control targetControl, TouchKeyboardStyle style)
{
TargetControl = targetControl;
Style = style;
}
/// <summary>
/// Gets or sets the keyboard target control.
/// </summary>
public Control TargetControl;
/// <summary>
/// Gets or sets the keyboard style.
/// </summary>
public TouchKeyboardStyle Style;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace DevComponents.DotNetBar.Keyboard
{
/// <summary>
/// Defines the VirtualKeyboard colors.
/// </summary>
/// <remarks>
/// This class maintains internally a Brush for each Color. These Brush objects are disposed internally when not needed anymore.
/// A Brush of a certain color is obtained by setting the same Color property to that color.
/// Maintaining the brushes here helps to have less GDI handles created / destroyed on each drawing of the keyboard.
/// </remarks>
public sealed class VirtualKeyboardColorTable : IDisposable
{
/// <summary>
/// Creates a new color table for the VirtualKeyoard.
/// </summary>
public VirtualKeyboardColorTable()
{
_BackgroundBrush = new SolidBrush(BackgroundColor);
_KeysBrush = new SolidBrush(KeysColor);
_LightKeysBrush = new SolidBrush(LightKeysColor);
_DarkKeysBrush = new SolidBrush(DarkKeysColor);
_PressedKeysBrush = new SolidBrush(PressedKeysColor);
_TextBrush = new SolidBrush(TextColor);
_DownKeysBrush = new SolidBrush(DownKeysColor);
_DownTextBrush = new SolidBrush(DownTextColor);
_TopBarTextBrush = new SolidBrush(TopBarTextColor);
_ToggleTextBrush = new SolidBrush(ToggleTextColor);
}
private static void ReCreateBrush(ref Brush brush, Color color)
{
if (brush != null)
brush.Dispose();
brush = new SolidBrush(color);
}
private Color _BackgroundColor = Color.Black;
/// <summary>
/// Gets or sets the color used to draw the background of the keyboard.
/// </summary>
public Color BackgroundColor
{
get { return _BackgroundColor; }
set { _BackgroundColor = value; ReCreateBrush(ref _BackgroundBrush, _BackgroundColor); }
}
private Brush _BackgroundBrush;
/// <summary>
/// Gets a brush used for drawing the background of the keyboard.
/// </summary>
public Brush BackgroundBrush
{
get { return _BackgroundBrush; }
}
private Color _KeysColor = Color.FromArgb(0x30, 0x2f, 0x37);
/// <summary>
/// Gets or sets the color used for drawing normal keys.
/// </summary>
public Color KeysColor
{
get { return _KeysColor; }
set { _KeysColor = value; ReCreateBrush(ref _KeysBrush, _KeysColor); }
}
private Brush _KeysBrush;
/// <summary>
/// Gets a brush used for drawing normal keys.
/// </summary>
public Brush KeysBrush
{
get { return _KeysBrush; }
}
private Color _LightKeysColor = Color.FromArgb(0x45, 0x44, 0x4c);
/// <summary>
/// Gets or sets the color used for drawing light keys.
/// </summary>
public Color LightKeysColor
{
get { return _LightKeysColor; }
set { _LightKeysColor = value; ReCreateBrush(ref _LightKeysBrush, _LightKeysColor); }
}
private Brush _LightKeysBrush;
/// <summary>
/// Gets a brush used for drawing light keys.
/// </summary>
public Brush LightKeysBrush
{
get { return _LightKeysBrush; }
}
private Color _DarkKeysColor = Color.FromArgb(0x1d, 0x1c, 0x21);
/// <summary>
/// Gets or sets the color used for drawing dark keys.
/// </summary>
public Color DarkKeysColor
{
get { return _DarkKeysColor; }
set { _DarkKeysColor = value; ReCreateBrush(ref _DarkKeysBrush, _DarkKeysColor); }
}
private Brush _DarkKeysBrush;
/// <summary>
/// Gets a brush used for drawing dark keys.
/// </summary>
public Brush DarkKeysBrush
{
get { return _DarkKeysBrush; }
}
private Color _PressedKeysColor = Color.FromArgb(0x10, 0xa1, 0x51);
/// <summary>
/// Gets or sets a brush used for drawing pressed keys.
/// </summary>
public Color PressedKeysColor
{
get { return _PressedKeysColor; }
set { _PressedKeysColor = value; ReCreateBrush(ref _PressedKeysBrush, _PressedKeysColor); }
}
private Brush _PressedKeysBrush;
/// <summary>
/// Gets a brush used for drawing pressed keys.
/// </summary>
public Brush PressedKeysBrush
{
get { return _PressedKeysBrush; }
}
private Color _DownKeysColor = Color.White;
/// <summary>
/// Gets or sets a brush used for drawing pressed key when the key is down.
/// </summary>
public Color DownKeysColor
{
get { return _DownKeysColor; }
set { _DownKeysColor = value; ReCreateBrush(ref _DownKeysBrush, _DownKeysColor); }
}
private Brush _DownKeysBrush;
/// <summary>
/// Gets a brush used for drawing pressed key when the key is down.
/// </summary>
public Brush DownKeysBrush
{
get { return _DownKeysBrush; }
}
private Color _TextColor = Color.White;
/// <summary>
/// Gets or sets a color used for drawing the text on the keys.
/// </summary>
public Color TextColor
{
get { return _TextColor; }
set { _TextColor = value; ReCreateBrush(ref _TextBrush, _TextColor); }
}
private Brush _TextBrush;
/// <summary>
/// Gets a brush used for drawing the text on the keys.
/// </summary>
public Brush TextBrush
{
get { return _TextBrush; }
}
private Color _DownTextColor = Color.FromArgb(0x20, 0x20, 0x20);
/// <summary>
/// Gets or sets a color used for drawing the text on a key when the key is down.
/// </summary>
public Color DownTextColor
{
get { return _DownTextColor; }
set { _DownTextColor = value; ReCreateBrush(ref _DownTextBrush, _DownTextColor); }
}
private Brush _DownTextBrush;
/// <summary>
/// Gets a brush used for drawing the text on a key when the key is down.
/// </summary>
public Brush DownTextBrush
{
get { return _DownTextBrush; }
}
private Color _TopBarTextColor = Color.White;
/// <summary>
/// Gets or sets a color used for drawing the text on the top bar.
/// </summary>
public Color TopBarTextColor
{
get { return _TopBarTextColor; }
set { _TopBarTextColor = value; ReCreateBrush(ref _TopBarTextBrush, _TopBarTextColor); }
}
private Brush _TopBarTextBrush;
/// <summary>
/// Gets a brush used for drawing the text on the top bar.
/// </summary>
public Brush TopBarTextBrush
{
get { return _TopBarTextBrush; }
}
private Color _ToggleTextColor = Color.Green;
/// <summary>
/// Gets or sets a color used for drawing the text on a key when the key is in its toggled state.
/// </summary>
public Color ToggleTextColor
{
get { return _ToggleTextColor; }
set { _ToggleTextColor = value; ReCreateBrush(ref _ToggleTextBrush, _ToggleTextColor); }
}
private Brush _ToggleTextBrush;
/// <summary>
/// Gets a brush used for drawing the text on a key when the key is in its toggled state.
/// </summary>
public Brush ToggleTextBrush
{
get { return _ToggleTextBrush; }
}
public void Dispose()
{
if (_BackgroundBrush != null)
_BackgroundBrush.Dispose();
if (_KeysBrush != null)
_KeysBrush.Dispose();
if (_LightKeysBrush != null)
_LightKeysBrush.Dispose();
if (_DarkKeysBrush != null)
_DarkKeysBrush.Dispose();
if (_PressedKeysBrush != null)
_PressedKeysBrush.Dispose();
if (_TextBrush != null)
_TextBrush.Dispose();
if (_DownTextBrush != null)
_DownTextBrush.Dispose();
if (_DownKeysBrush != null)
_DownKeysBrush.Dispose();
if (_TopBarTextBrush != null)
_TopBarTextBrush.Dispose();
if (_ToggleTextBrush != null)
_ToggleTextBrush.Dispose();
}
}
}