diff --git a/src/Eto.WinForms/Eto.WinForms.csproj b/src/Eto.WinForms/Eto.WinForms.csproj
index 0ee8c7f1f1..d400687dff 100755
--- a/src/Eto.WinForms/Eto.WinForms.csproj
+++ b/src/Eto.WinForms/Eto.WinForms.csproj
@@ -16,6 +16,7 @@
$(DefineConstants);WINFORMS
MSB4011;$(NoWarn)
true
+ True
@@ -118,9 +119,24 @@ You do not need to use any of the classes of this assembly (unless customizing t
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
diff --git a/src/Eto.WinForms/Forms/Controls/SearchBoxHandler.cs b/src/Eto.WinForms/Forms/Controls/SearchBoxHandler.cs
old mode 100644
new mode 100755
index 41ed11db83..6e65b64a28
--- a/src/Eto.WinForms/Forms/Controls/SearchBoxHandler.cs
+++ b/src/Eto.WinForms/Forms/Controls/SearchBoxHandler.cs
@@ -1,10 +1,110 @@
-using SD = System.Drawing;
-using SWF = System.Windows.Forms;
+using sd = System.Drawing;
+using swf = System.Windows.Forms;
using Eto.Forms;
+using Eto.WinForms.CustomControls;
+using System;
namespace Eto.WinForms.Forms.Controls
{
- public class SearchBoxHandler : TextBoxHandler, SearchBox.IHandler
+ public class EtoSearchTextBox : EtoTextBox
{
+ private readonly swf.PictureBox searchImage;
+
+ private readonly swf.Button clearSearchButton;
+
+ public EtoSearchTextBox()
+ {
+ clearSearchButton = new swf.Button
+ {
+ Dock = swf.DockStyle.Right,
+ Size = new sd.Size(16, 16),
+ TabStop = false,
+ FlatStyle = swf.FlatStyle.Flat,
+ Cursor = swf.Cursors.Arrow,
+ ImageAlign = sd.ContentAlignment.MiddleCenter,
+ Image = Resources.Clear
+ };
+ clearSearchButton.FlatAppearance.BorderSize = 0;
+ clearSearchButton.Click += Clear_Click;
+
+ searchImage = new swf.PictureBox
+ {
+ Dock = swf.DockStyle.Left,
+ Size = new sd.Size(16, 16),
+ TabIndex = 0,
+ SizeMode = swf.PictureBoxSizeMode.CenterImage,
+ Image = Resources.Search
+ };
+
+
+ Controls.Add(clearSearchButton);
+ Controls.Add(searchImage);
+
+ UpdateClearButton();
+ }
+
+
+ protected override void OnResize(EventArgs e)
+ {
+ base.OnResize(e);
+ SetRounded();
+ }
+
+ protected override void OnCreateControl()
+ {
+ base.OnCreateControl();
+ SetRounded();
+ }
+
+ private void SetRounded()
+ {
+ Region = sd.Region.FromHrgn(Win32.CreateRoundRectRgn(1, 1, Width, Height, Height * 2 / 3, Height * 2 / 3));
+ Win32.SendMessage(Handle, Win32.WM.EM_SETMARGINS, (IntPtr)3, (IntPtr)((16 << 16) + 16));
+ }
+
+ private void Clear_Click(object sender, EventArgs e)
+ {
+ Text = string.Empty;
+ Focus();
+ }
+
+ protected override void OnTextChanged(EventArgs e)
+ {
+ base.OnTextChanged(e);
+ UpdateClearButton();
+ }
+
+ private void UpdateClearButton()
+ {
+ var showClearButton = !string.IsNullOrEmpty(Text);
+ if (clearSearchButton.Visible != showClearButton)
+ {
+ clearSearchButton.Visible = showClearButton;
+ }
+ }
+
+ public sd.Image SearchImage
+ {
+ set => searchImage.Image = value;
+ get => searchImage.Image;
+ }
+
+ public sd.Image CancelSearchImage
+ {
+ set => clearSearchButton.Image = value;
+ get => clearSearchButton.Image;
+ }
+ }
+
+ public class SearchBoxHandler : TextBoxHandler, SearchBox.IHandler
+ {
+ public override swf.TextBox SwfTextBox => Control;
+
+ public override EtoTextBox EtoTextBox => Control;
+
+ public SearchBoxHandler()
+ {
+ Control = new EtoSearchTextBox();
+ }
}
}
diff --git a/src/Eto.WinForms/Resources.Designer.cs b/src/Eto.WinForms/Resources.Designer.cs
new file mode 100755
index 0000000000..5854b455ca
--- /dev/null
+++ b/src/Eto.WinForms/Resources.Designer.cs
@@ -0,0 +1,83 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Eto.WinForms {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Eto.WinForms.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap Clear {
+ get {
+ object obj = ResourceManager.GetObject("Clear", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap Search {
+ get {
+ object obj = ResourceManager.GetObject("Search", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/src/Eto.WinForms/Resources.resx b/src/Eto.WinForms/Resources.resx
new file mode 100755
index 0000000000..2d6a719c4b
--- /dev/null
+++ b/src/Eto.WinForms/Resources.resx
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ Resources\Clear.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Resources\Search.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/src/Eto.WinForms/Resources/Clear.png b/src/Eto.WinForms/Resources/Clear.png
new file mode 100644
index 0000000000..bcc8034f1e
Binary files /dev/null and b/src/Eto.WinForms/Resources/Clear.png differ
diff --git a/src/Eto.WinForms/Resources/Search.png b/src/Eto.WinForms/Resources/Search.png
new file mode 100644
index 0000000000..8dbef3ed55
Binary files /dev/null and b/src/Eto.WinForms/Resources/Search.png differ
diff --git a/src/Eto.WinForms/Win32.cs b/src/Eto.WinForms/Win32.cs
old mode 100644
new mode 100755
index f42122b30e..a38ecc01ac
--- a/src/Eto.WinForms/Win32.cs
+++ b/src/Eto.WinForms/Win32.cs
@@ -182,6 +182,7 @@ public enum WM
ECM_FIRST = 0x1500,
EM_SETCUEBANNER = ECM_FIRST + 1,
+ EM_SETMARGINS = 0xd3,
DPICHANGED = 0x02E0,
NCCREATE = 0x0081,
@@ -500,6 +501,10 @@ public static IntPtr GetThreadFocusWindow(uint? threadId = null)
[DllImport("gdi32.dll")]
public static extern bool OffsetWindowOrgEx(IntPtr hdc, int nXOffset, int nYOffset, ref POINT lpPoint);
+ [DllImport("gdi32.dll")]
+ public static extern IntPtr CreateRoundRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nheightRect, int nweightRect);
+
+
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(POINT lpPoint);
diff --git a/src/Eto.Wpf/Forms/Controls/SearchBoxHandler.cs b/src/Eto.Wpf/Forms/Controls/SearchBoxHandler.cs
old mode 100644
new mode 100755
index 65960c7a15..a6a307a24d
--- a/src/Eto.Wpf/Forms/Controls/SearchBoxHandler.cs
+++ b/src/Eto.Wpf/Forms/Controls/SearchBoxHandler.cs
@@ -1,8 +1,59 @@
using Eto.Forms;
+using Xceed.Wpf.Toolkit;
+using static Eto.Win32;
+using mwc = Xceed.Wpf.Toolkit;
+using swc = System.Windows.Controls;
+using sw = System.Windows;
+using System.Windows.Input;
+using System;
namespace Eto.Wpf.Forms.Controls
{
- public class SearchBoxHandler : TextBoxHandler, SearchBox.IHandler
+ public class EtoSearchTextBox : EtoWatermarkTextBox
{
+ static readonly sw.DependencyPropertyKey IsEmptyPropertyKey =
+ sw.DependencyProperty.RegisterReadOnly("IsEmpty", typeof(bool), typeof(EtoSearchTextBox), new sw.PropertyMetadata(true));
+
+ public static readonly sw.DependencyProperty IsEmptyProperty = IsEmptyPropertyKey.DependencyProperty;
+
+
+ public static readonly sw.DependencyProperty ClearCommandProperty = sw.DependencyProperty.Register("ClearCommand", typeof(ICommand), typeof(EtoSearchTextBox));
+
+ public bool IsEmpty => (bool)GetValue(IsEmptyProperty);
+
+ protected override void OnTextChanged(swc.TextChangedEventArgs e)
+ {
+ base.OnTextChanged(e);
+ SetValue(IsEmptyPropertyKey, string.IsNullOrEmpty(Text));
+ }
+
+ public EtoSearchTextBox()
+ {
+ ClearCommand = new RelayCommand(Clear);
+ }
+
+ public ICommand ClearCommand
+ {
+ get => (ICommand)GetValue(ClearCommandProperty);
+ set => SetValue(ClearCommandProperty, value);
+ }
+
+ }
+
+ public class SearchBoxHandler : TextBoxHandler, SearchBox.IHandler
+ {
+ internal static object CurrentText_Key = new object();
+ internal static object CurrentSelection_Key = new object();
+ internal static object DisableTextChanged_Key = new object();
+
+ protected override swc.TextBox TextBox => Control;
+
+ protected override WatermarkTextBox CreateControl() => new EtoSearchTextBox { Handler = this, KeepWatermarkOnGotFocus = true };
+
+ public override string PlaceholderText
+ {
+ get => Control.Watermark as string;
+ set => Control.Watermark = value;
+ }
}
}
diff --git a/src/Eto.Wpf/themes/aero.normalcolor.xaml b/src/Eto.Wpf/themes/aero.normalcolor.xaml
deleted file mode 100644
index 8c06311633..0000000000
--- a/src/Eto.Wpf/themes/aero.normalcolor.xaml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/aero2.normalcolor.xaml b/src/Eto.Wpf/themes/aero2.normalcolor.xaml
deleted file mode 100644
index ad6f8dae4a..0000000000
--- a/src/Eto.Wpf/themes/aero2.normalcolor.xaml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/classic.xaml b/src/Eto.Wpf/themes/classic.xaml
deleted file mode 100644
index f91389e91e..0000000000
--- a/src/Eto.Wpf/themes/classic.xaml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/controls/SearchTextBox.xaml b/src/Eto.Wpf/themes/controls/SearchTextBox.xaml
new file mode 100755
index 0000000000..436ecf7bcc
--- /dev/null
+++ b/src/Eto.Wpf/themes/controls/SearchTextBox.xaml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/controls/ToggleButton.xaml b/src/Eto.Wpf/themes/controls/ToggleButton.xaml
new file mode 100755
index 0000000000..acf9173dd7
--- /dev/null
+++ b/src/Eto.Wpf/themes/controls/ToggleButton.xaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/controls/WatermarkTextBox.xaml b/src/Eto.Wpf/themes/controls/WatermarkTextBox.xaml
new file mode 100755
index 0000000000..83d4955a68
--- /dev/null
+++ b/src/Eto.Wpf/themes/controls/WatermarkTextBox.xaml
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/generic.xaml b/src/Eto.Wpf/themes/generic.xaml
index a88e9e5bb3..fcbc3a362e 100755
--- a/src/Eto.Wpf/themes/generic.xaml
+++ b/src/Eto.Wpf/themes/generic.xaml
@@ -7,6 +7,8 @@
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/luna.homestead.xaml b/src/Eto.Wpf/themes/luna.homestead.xaml
deleted file mode 100644
index cc6e75f546..0000000000
--- a/src/Eto.Wpf/themes/luna.homestead.xaml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/luna.metallic.xaml b/src/Eto.Wpf/themes/luna.metallic.xaml
deleted file mode 100644
index cc6e75f546..0000000000
--- a/src/Eto.Wpf/themes/luna.metallic.xaml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/luna.normalcolor.xaml b/src/Eto.Wpf/themes/luna.normalcolor.xaml
deleted file mode 100644
index cc6e75f546..0000000000
--- a/src/Eto.Wpf/themes/luna.normalcolor.xaml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Eto.Wpf/themes/royale.normalcolor.xaml b/src/Eto.Wpf/themes/royale.normalcolor.xaml
deleted file mode 100644
index cc6e75f546..0000000000
--- a/src/Eto.Wpf/themes/royale.normalcolor.xaml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
\ No newline at end of file