diff --git a/README.md b/README.md
index cdd97043..a00fe919 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,26 @@ Step 4:enjoy coding
## Latest examples
+### ImageBlock
+
+
+
+
+
+### Magnifier
+
+
+
+### Card
+
+
+
+### ButtonGroup
+
+
+
+## History publication
+
### Grid

@@ -83,8 +103,6 @@ Step 4:enjoy coding

-## History publication
-
### Badge

diff --git a/Resources/ButtonGroup.png b/Resources/ButtonGroup.png
new file mode 100644
index 00000000..25041947
Binary files /dev/null and b/Resources/ButtonGroup.png differ
diff --git a/Resources/Card.png b/Resources/Card.png
new file mode 100644
index 00000000..df4358b2
Binary files /dev/null and b/Resources/Card.png differ
diff --git a/Resources/ContextMenu.png b/Resources/ContextMenu.png
index 5cab4b46..4afeeb86 100644
Binary files a/Resources/ContextMenu.png and b/Resources/ContextMenu.png differ
diff --git a/Resources/ImageBlock.gif b/Resources/ImageBlock.gif
new file mode 100644
index 00000000..d64e99d5
Binary files /dev/null and b/Resources/ImageBlock.gif differ
diff --git a/Resources/ImageBlock.png b/Resources/ImageBlock.png
new file mode 100644
index 00000000..4157f8a2
Binary files /dev/null and b/Resources/ImageBlock.png differ
diff --git a/Resources/Magnifier.png b/Resources/Magnifier.png
new file mode 100644
index 00000000..929ae0c9
Binary files /dev/null and b/Resources/Magnifier.png differ
diff --git a/Resources/RadioButton.png b/Resources/RadioButton.png
index 4641a6f8..4f1308e5 100644
Binary files a/Resources/RadioButton.png and b/Resources/RadioButton.png differ
diff --git a/doc/source/_posts/home.md b/doc/source/_posts/home.md
index 34ebe0d8..cec7679d 100644
--- a/doc/source/_posts/home.md
+++ b/doc/source/_posts/home.md
@@ -4,8 +4,6 @@ title: 欢迎来到HandyOrg
HandyOrg的宗旨是为用户提供最简单的API。
-目前组织成员只有一人。
-
我们一直期待着有更多的同学加入。
我们的入坑要求:
diff --git a/doc/source/handycontrol/native_controls/comboBox/index.md b/doc/source/handycontrol/native_controls/comboBox/index.md
index 588fe39d..635b0a84 100644
--- a/doc/source/handycontrol/native_controls/comboBox/index.md
+++ b/doc/source/handycontrol/native_controls/comboBox/index.md
@@ -29,7 +29,13 @@ title: ComboBox 组合框
{% note warning %}
标题在左时,为了多个输入框左侧对齐,需要设置标题宽度,标题宽度无需逐个设置,可在外部容器上统一设置。
{% endnote %}
-
+{% note warning %}
+常见问题:
+Combobox的字体比原有默认字体大,同时设定标题在左,标题因字体过大显示不全
+
+解决方案:
+在该Combobox中添加附加属性`hc:InfoElement.ContentHeight`,默认值为30,默认字体号为12,变更后可根据新的字体大小设定该附加属性的数值,如上图,字体大小为18,则设定`hc:InfoElement.ContentHeight`为38,结果如下:
+{% endnote %}
- 标题在上,带有水印
``

diff --git a/doc/source/handycontrol/native_controls/images/ComboBoxExtend_2_Error1.png b/doc/source/handycontrol/native_controls/images/ComboBoxExtend_2_Error1.png
new file mode 100644
index 00000000..c824361f
Binary files /dev/null and b/doc/source/handycontrol/native_controls/images/ComboBoxExtend_2_Error1.png differ
diff --git a/doc/source/handycontrol/native_controls/images/ComboBoxExtend_2_Ok1.png b/doc/source/handycontrol/native_controls/images/ComboBoxExtend_2_Ok1.png
new file mode 100644
index 00000000..3711d140
Binary files /dev/null and b/doc/source/handycontrol/native_controls/images/ComboBoxExtend_2_Ok1.png differ
diff --git a/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj b/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj
index 3a6182e6..036f5423 100644
--- a/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj
+++ b/src/Core_30/HandyControlDemo_Core_30/HandyControlDemo_Core30.csproj
@@ -5,12 +5,13 @@
true
HandyControlDemo
HandyControlDemo
- 2.0.0
+ 2.1.0
..\..\Shared\HandyControlDemo_Shared\Resources\Img\icon.ico
Debug;Release
Copyright © HandyOrg 2018-2019
- 2.0.0.0
- 2.0.0.0
+ 2.1.0.0
+ 2.1.0.0
+ latest
TRACE;Core
@@ -352,6 +353,18 @@
Resources\Img\LeftMainContent\brackets_Square_16xLG.png
+
+ Resources\Img\LeftMainContent\ButtonGroup_16x.png
+
+
+ Resources\Img\LeftMainContent\VSO_Card_16x.png
+
+
+ Resources\Img\LeftMainContent\ImageStack_16x.png
+
+
+ Resources\Img\Dance.png
+
diff --git a/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj b/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj
index f5711c96..0bd1c286 100644
--- a/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj
+++ b/src/Core_30/HandyControl_Core_30/HandyControl_Core_30.csproj
@@ -4,13 +4,14 @@
true
HandyControl
HandyControl
- 2.0.0
- 2.0.0.0
+ 2.1.0
+ 2.1.0.0
false
false
Copyright © HandyOrg 2018-2019
Contains some commonly used simple WPF controls
Debug;Release
+ latest
TRACE;Core
diff --git a/src/Core_30/HandyControl_Core_30/Themes/Styles/Base/ComboBoxBaseStyle.xaml b/src/Core_30/HandyControl_Core_30/Themes/Styles/Base/ComboBoxBaseStyle.xaml
index 29c6a7cd..d8f26026 100644
--- a/src/Core_30/HandyControl_Core_30/Themes/Styles/Base/ComboBoxBaseStyle.xaml
+++ b/src/Core_30/HandyControl_Core_30/Themes/Styles/Base/ComboBoxBaseStyle.xaml
@@ -258,7 +258,7 @@
-
+
@@ -467,11 +467,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/RadioGroupBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ButtonGroupBaseStyle.xaml
similarity index 71%
rename from src/Shared/HandyControl_Shared/Themes/Styles/Base/RadioGroupBaseStyle.xaml
rename to src/Shared/HandyControl_Shared/Themes/Styles/Base/ButtonGroupBaseStyle.xaml
index 4d702304..10084ad6 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/RadioGroupBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ButtonGroupBaseStyle.xaml
@@ -2,24 +2,25 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
-
+
-
+
-
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/CardBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/CardBaseStyle.xaml
new file mode 100644
index 00000000..a8c49d39
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/CardBaseStyle.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/CheckBoxBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/CheckBoxBaseStyle.xaml
index 93b0c69e..b2da6bd3 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/CheckBoxBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/CheckBoxBaseStyle.xaml
@@ -4,6 +4,7 @@
+
-
-
-
-
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/GotoTopBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/GotoTopBaseStyle.xaml
index a4ab4e5b..a922ecc5 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/GotoTopBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/GotoTopBaseStyle.xaml
@@ -5,6 +5,7 @@
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/MenuBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/MenuBaseStyle.xaml
new file mode 100644
index 00000000..bd7b0652
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/MenuBaseStyle.xaml
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/NumericUpDownBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/NumericUpDownBaseStyle.xaml
index d0050b47..b01ad9fd 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/NumericUpDownBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/NumericUpDownBaseStyle.xaml
@@ -21,7 +21,7 @@
-
+
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/PasswordBoxBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/PasswordBoxBaseStyle.xaml
index d79a4f45..6028041e 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/PasswordBoxBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/PasswordBoxBaseStyle.xaml
@@ -24,7 +24,7 @@
-
+
@@ -116,9 +116,8 @@
-
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/RepeatButtonBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/RepeatButtonBaseStyle.xaml
index 19b9f5a9..96f99f0a 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/RepeatButtonBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/RepeatButtonBaseStyle.xaml
@@ -8,7 +8,7 @@
+
@@ -199,12 +205,6 @@
-
-
-
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToggleButtonBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToggleButtonBaseStyle.xaml
index 7aa084cf..138ffd03 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToggleButtonBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToggleButtonBaseStyle.xaml
@@ -1,14 +1,16 @@
+ xmlns:controls="clr-namespace:HandyControl.Controls"
+ xmlns:system="clr-namespace:System;assembly=mscorlib">
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToolBarBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToolBarBaseStyle.xaml
index ecdd240d..479c6959 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToolBarBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/ToolBarBaseStyle.xaml
@@ -9,7 +9,7 @@
-
+
-
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Button.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Button.xaml
index 238edc28..7b0acfa1 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Button.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Button.xaml
@@ -4,6 +4,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/RadioGroup.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/ButtonGroup.xaml
similarity index 70%
rename from src/Shared/HandyControl_Shared/Themes/Styles/RadioGroup.xaml
rename to src/Shared/HandyControl_Shared/Themes/Styles/ButtonGroup.xaml
index 3a6d2a00..9db91779 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/RadioGroup.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/ButtonGroup.xaml
@@ -3,12 +3,12 @@
xmlns:controls="clr-namespace:HandyControl.Controls">
-
+
-
+
-
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Gravatar.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Gravatar.xaml
index 7c400cdb..a3e88424 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Gravatar.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Gravatar.xaml
@@ -14,7 +14,7 @@
-
+
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/ListBox.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/ListBox.xaml
index caff1067..4d8dcae9 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/ListBox.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/ListBox.xaml
@@ -26,13 +26,13 @@
-
-
+
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/RichTextBox.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/RichTextBox.xaml
index 068f3069..ad0f3ce7 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/RichTextBox.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/RichTextBox.xaml
@@ -2,13 +2,17 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Style.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Style.xaml
index 41c62ccd..bd4bbbf4 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Style.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Style.xaml
@@ -18,6 +18,7 @@
+
@@ -49,7 +50,7 @@
-
+
@@ -65,6 +66,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml
index 5da521e4..dc715ab0 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml
@@ -122,7 +122,7 @@
-
+
@@ -249,7 +249,7 @@
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/ToggleButton.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/ToggleButton.xaml
index 9204464a..2c7e5ded 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/ToggleButton.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/ToggleButton.xaml
@@ -91,7 +91,7 @@
-
+
@@ -178,7 +178,7 @@
-
+
@@ -186,7 +186,7 @@
-
+
@@ -264,4 +264,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/TransitioningContentControl.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/TransitioningContentControl.xaml
index dac6c0a9..81fb9f6a 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/TransitioningContentControl.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/TransitioningContentControl.xaml
@@ -87,7 +87,7 @@
-
+
diff --git a/src/Shared/HandyControl_Shared/Tools/Converter/BorderCircularClipConverter.cs b/src/Shared/HandyControl_Shared/Tools/Converter/BorderCircularClipConverter.cs
new file mode 100644
index 00000000..65a27532
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/Converter/BorderCircularClipConverter.cs
@@ -0,0 +1,36 @@
+//referenced from https://stackoverflow.com/a/5650367/9639378
+
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace HandyControl.Tools.Converter
+{
+ public class BorderCircularClipConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values.Length == 3 && values[0] is double width && values[1] is double height && values[2] is CornerRadius radius)
+ {
+ if (width < double.Epsilon || height < double.Epsilon)
+ {
+ return Geometry.Empty;
+ }
+
+ var clip = new RectangleGeometry(new Rect(0, 0, width, height), radius.TopLeft, radius.TopLeft);
+ clip.Freeze();
+
+ return clip;
+ }
+
+ return DependencyProperty.UnsetValue;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/Converter/BorderClipConverter.cs b/src/Shared/HandyControl_Shared/Tools/Converter/BorderClipConverter.cs
index 4b17a7f7..e55cfb71 100644
--- a/src/Shared/HandyControl_Shared/Tools/Converter/BorderClipConverter.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Converter/BorderClipConverter.cs
@@ -1,6 +1,4 @@
-//referenced from https://stackoverflow.com/a/5650367/9639378
-
-using System;
+using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
@@ -19,7 +17,23 @@ namespace HandyControl.Tools.Converter
return Geometry.Empty;
}
- var clip = new RectangleGeometry(new Rect(0, 0, width, height), radius.TopLeft, radius.TopLeft);
+ var clip = new PathGeometry
+ {
+ Figures = new PathFigureCollection
+ {
+ new PathFigure(new Point(radius.TopLeft, 0), new PathSegment[]
+ {
+ new LineSegment(new Point(width - radius.TopRight, 0), false),
+ new ArcSegment(new Point(width, radius.TopRight), new Size(radius.TopRight, radius.TopRight), 90, false, SweepDirection.Clockwise, false),
+ new LineSegment(new Point(width, height - radius.BottomRight), false),
+ new ArcSegment(new Point(width - radius.BottomRight, height), new Size(radius.BottomRight, radius.BottomRight), 90, false, SweepDirection.Clockwise, false),
+ new LineSegment(new Point(radius.BottomLeft, height), false),
+ new ArcSegment(new Point(0, height - radius.BottomLeft), new Size(radius.BottomLeft, radius.BottomLeft), 90, false, SweepDirection.Clockwise, false),
+ new LineSegment(new Point(0, radius.TopLeft), false),
+ new ArcSegment(new Point(radius.TopLeft, 0), new Size(radius.TopLeft, radius.TopLeft), 90, false, SweepDirection.Clockwise, false),
+ }, false)
+ }
+ };
clip.Freeze();
return clip;
diff --git a/src/Shared/HandyControl_Shared/Tools/Converter/NameReferenceConverter.cs b/src/Shared/HandyControl_Shared/Tools/Converter/NameReferenceConverter.cs
deleted file mode 100644
index 29a6924c..00000000
--- a/src/Shared/HandyControl_Shared/Tools/Converter/NameReferenceConverter.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Globalization;
-// ReSharper disable ConditionIsAlwaysTrueOrFalse
-// ReSharper disable HeuristicUnreachableCode
-
-namespace HandyControl.Tools.Converter
-{
- public class NameReferenceConverter : System.Windows.Markup.NameReferenceConverter
- {
- public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
- => context == null ? null : base.ConvertFrom(context, culture, value);
-
- public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
- => context == null ? null : base.ConvertTo(context, culture, value, destinationType);
- }
-}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/Converter/Number2PercentageConverter.cs b/src/Shared/HandyControl_Shared/Tools/Converter/Number2PercentageConverter.cs
new file mode 100644
index 00000000..08ebef73
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/Converter/Number2PercentageConverter.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using HandyControl.Expression.Drawing;
+using HandyControl.Tools.Extension;
+
+namespace HandyControl.Tools.Converter
+{
+ public class Number2PercentageConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values == null || values.Length != 2) return .0;
+
+ var obj1 = values[0];
+ var obj2 = values[1];
+
+ if (obj1 == null || obj2 == null) return .0;
+
+ var str1 = values[0].ToString();
+ var str2 = values[1].ToString();
+
+ var v1 = str1.Value();
+ var v2 = str2.Value();
+
+ if (MathHelper.IsVerySmall(v2)) return 100.0;
+
+ return v1 / v2 * 100;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Shared/HandyControl_Shared/Tools/Converter/RectangleCircularConverter.cs b/src/Shared/HandyControl_Shared/Tools/Converter/RectangleCircularConverter.cs
new file mode 100644
index 00000000..5e2e818d
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/Converter/RectangleCircularConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace HandyControl.Tools.Converter
+{
+ public class RectangleCircularConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values.Length == 2 && values[0] is double width && values[1] is double height)
+ {
+ if (width < double.Epsilon || height < double.Epsilon)
+ {
+ return .0;
+ }
+
+ var min = Math.Min(width, height);
+ return min / 2;
+ }
+
+ return DependencyProperty.UnsetValue;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/src/Shared/HandyControl_Shared/Tools/Extension/DialogExtension.cs b/src/Shared/HandyControl_Shared/Tools/Extension/DialogExtension.cs
index 5dca7c1e..aae15918 100644
--- a/src/Shared/HandyControl_Shared/Tools/Extension/DialogExtension.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Extension/DialogExtension.cs
@@ -9,7 +9,7 @@ namespace HandyControl.Tools.Extension
{
T Result { get; set; }
- Action CloseAction { get; set; }
+ Action CloseAction { get; set; }
}
public static class DialogExtension
diff --git a/src/Shared/HandyControl_Shared/Tools/Extension/ValueExtension.cs b/src/Shared/HandyControl_Shared/Tools/Extension/ValueExtension.cs
new file mode 100644
index 00000000..c4606424
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/Extension/ValueExtension.cs
@@ -0,0 +1,9 @@
+using System.Windows;
+
+namespace HandyControl.Tools.Extension
+{
+ public static class ValueExtension
+ {
+ public static Thickness Add(this Thickness a, Thickness b) => new Thickness(a.Left + b.Left, a.Top + b.Top, a.Right + b.Right, a.Bottom + b.Bottom);
+ }
+}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/GlobalShortcut.cs b/src/Shared/HandyControl_Shared/Tools/GlobalShortcut.cs
index ce248ba5..3946d575 100644
--- a/src/Shared/HandyControl_Shared/Tools/GlobalShortcut.cs
+++ b/src/Shared/HandyControl_Shared/Tools/GlobalShortcut.cs
@@ -1,4 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
using System.Windows;
using System.Windows.Input;
using HandyControl.Data;
@@ -7,15 +10,18 @@ namespace HandyControl.Tools
{
public class GlobalShortcut
{
+ private static ObservableCollection KeyBindingCollection;
+
private static readonly Dictionary CommandDic = new Dictionary();
+ private static void KeyboardHook_KeyDown(object sender, KeyboardHookEventArgs e) => HitTest(e.Key);
+
static GlobalShortcut()
{
+
KeyboardHook.KeyDown += KeyboardHook_KeyDown;
}
- private static void KeyboardHook_KeyDown(object sender, KeyboardHookEventArgs e) => HitTest(e.Key);
-
private static void HitTest(Key key)
{
if (IsModifierKey(key)) return;
@@ -45,21 +51,26 @@ namespace HandyControl.Tools
key == Key.RightCtrl || key == Key.RightAlt || key == Key.RightShift || key == Key.RWin;
}
+ [Obsolete("pls use Host attach property instead of Init method")]
public static void Init(DependencyObject host)
{
CommandDic.Clear();
if (host == null) return;
- var keyBindings = GetKeyBindings(host);
- if (keyBindings == null || keyBindings.Count == 0) return;
+ KeyBindingCollection = GetKeyBindings(host);
+ if (KeyBindingCollection == null || KeyBindingCollection.Count == 0) return;
- foreach (KeyBinding item in keyBindings)
+ AddKeyBindings(KeyBindingCollection);
+
+ KeyboardHook.Start();
+ }
+
+ private static void AddKeyBindings(IEnumerable keyBindings)
+ {
+ foreach (var item in keyBindings)
{
- if (item.Key == Key.None)
- {
- continue;
- }
+ if (item.Key == Key.None) continue;
if (item.Modifiers == ModifierKeys.None)
{
@@ -71,17 +82,45 @@ namespace HandyControl.Tools
CommandDic[keyStr] = item;
}
}
+ }
+ public static readonly DependencyProperty HostProperty = DependencyProperty.RegisterAttached(
+ "Host", typeof(bool), typeof(GlobalShortcut), new PropertyMetadata(ValueBoxes.FalseBox, OnHostChanged));
+
+ private static void OnHostChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (DesignerHelper.IsInDesignMode) return;
+
+ if (KeyBindingCollection != null)
+ {
+ KeyBindingCollection.CollectionChanged -= KeyBindingCollection_CollectionChanged;
+ }
+ KeyBindingCollection = GetKeyBindings(d);
+ if (KeyBindingCollection != null)
+ {
+ KeyBindingCollection.CollectionChanged += KeyBindingCollection_CollectionChanged;
+ }
+ }
+
+ private static void KeyBindingCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ AddKeyBindings(KeyBindingCollection);
KeyboardHook.Start();
}
- public static readonly DependencyProperty KeyBindingsProperty = DependencyProperty.RegisterAttached(
- "KeyBindings", typeof(InputBindingCollection), typeof(GlobalShortcut), new PropertyMetadata(new InputBindingCollection()));
+ public static void SetHost(DependencyObject element, bool value)
+ => element.SetValue(HostProperty, value);
- public static void SetKeyBindings(DependencyObject element, InputBindingCollection value)
+ public static bool GetHost(DependencyObject element)
+ => (bool) element.GetValue(HostProperty);
+
+ public static readonly DependencyProperty KeyBindingsProperty = DependencyProperty.RegisterAttached(
+ "KeyBindings", typeof(ObservableCollection), typeof(GlobalShortcut), new PropertyMetadata(new ObservableCollection()));
+
+ public static void SetKeyBindings(DependencyObject element, ObservableCollection value)
=> element.SetValue(KeyBindingsProperty, value);
- public static InputBindingCollection GetKeyBindings(DependencyObject element)
- => (InputBindingCollection) element.GetValue(KeyBindingsProperty);
+ public static ObservableCollection GetKeyBindings(DependencyObject element)
+ => (ObservableCollection) element.GetValue(KeyBindingsProperty);
}
}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/DpiHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/DpiHelper.cs
new file mode 100644
index 00000000..76134f6a
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/Helper/DpiHelper.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+
+namespace HandyControl.Tools
+{
+ internal class DpiHelper
+ {
+ [ThreadStatic]
+ private static Matrix _transformToDip;
+
+ public static Point DevicePixelsToLogical(Point devicePoint, double dpiScaleX, double dpiScaleY)
+ {
+ _transformToDip = Matrix.Identity;
+ _transformToDip.Scale(1d / dpiScaleX, 1d / dpiScaleY);
+ return _transformToDip.Transform(devicePoint);
+ }
+
+ public static Size DeviceSizeToLogical(Size deviceSize, double dpiScaleX, double dpiScaleY)
+ {
+ Point pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height), dpiScaleX, dpiScaleY);
+
+ return new Size(pt.X, pt.Y);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/VisualHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/VisualHelper.cs
index 4600f471..715e02ca 100644
--- a/src/Shared/HandyControl_Shared/Tools/Helper/VisualHelper.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Helper/VisualHelper.cs
@@ -1,6 +1,13 @@
-using System.Linq;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security;
using System.Windows;
using System.Windows.Media;
+using HandyControl.Tools.Interop;
+using HandyControl.Tools.Extension;
namespace HandyControl.Tools
{
@@ -50,5 +57,131 @@ namespace HandyControl.Tools
///
///
public static Window GetActiveWindow() => Application.Current.Windows.OfType().SingleOrDefault(x => x.IsActive);
+
+ private static readonly BitArray _cacheValid = new BitArray((int)CacheSlot.NumSlots);
+
+ private static bool _setDpiX = true;
+
+ private static bool _dpiInitialized;
+
+ private static readonly object _dpiLock = new object();
+
+ private static int _dpi;
+
+ internal static int Dpi
+ {
+ [SecurityCritical, SecuritySafeCritical]
+ get
+ {
+ if (!_dpiInitialized)
+ {
+ lock (_dpiLock)
+ {
+ if (!_dpiInitialized)
+ {
+ var desktopWnd = new HandleRef(null, IntPtr.Zero);
+
+ // Win32Exception will get the Win32 error code so we don't have to
+ var dc = UnsafeNativeMethods.GetDC(desktopWnd);
+
+ // Detecting error case from unmanaged call, required by PREsharp to throw a Win32Exception
+ if (dc == IntPtr.Zero)
+ {
+ throw new Win32Exception();
+ }
+
+ try
+ {
+ _dpi = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), NativeMethods.LOGPIXELSY);
+ _dpiInitialized = true;
+ }
+ finally
+ {
+ UnsafeNativeMethods.ReleaseDC(desktopWnd, new HandleRef(null, dc));
+ }
+ }
+ }
+ }
+ return _dpi;
+ }
+ }
+
+ private static int _dpiX;
+
+ internal static int DpiX
+ {
+ [SecurityCritical, SecuritySafeCritical]
+ get
+ {
+ if (_setDpiX)
+ {
+ lock (_cacheValid)
+ {
+ if (_setDpiX)
+ {
+ _setDpiX = false;
+ var desktopWnd = new HandleRef(null, IntPtr.Zero);
+ var dc = UnsafeNativeMethods.GetDC(desktopWnd);
+ if (dc == IntPtr.Zero)
+ {
+ throw new Win32Exception();
+ }
+ try
+ {
+ _dpiX = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), NativeMethods.LOGPIXELSX);
+ _cacheValid[(int)CacheSlot.DpiX] = true;
+ }
+ finally
+ {
+ UnsafeNativeMethods.ReleaseDC(desktopWnd, new HandleRef(null, dc));
+ }
+ }
+ }
+ }
+
+ return _dpiX;
+ }
+ }
+
+ private static Thickness _windowResizeBorderThickness;
+
+ internal static Thickness WindowResizeBorderThickness
+ {
+ [SecurityCritical]
+ get
+ {
+ lock (_cacheValid)
+ {
+ while (!_cacheValid[(int)CacheSlot.WindowResizeBorderThickness])
+ {
+ _cacheValid[(int)CacheSlot.WindowResizeBorderThickness] = true;
+
+ var frameSize = new Size(NativeMethods.GetSystemMetrics(SM.CXSIZEFRAME), NativeMethods.GetSystemMetrics(SM.CYSIZEFRAME));
+ var frameSizeInDips = DpiHelper.DeviceSizeToLogical(frameSize, DpiX / 96.0, Dpi / 96.0);
+
+ _windowResizeBorderThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height, frameSizeInDips.Width, frameSizeInDips.Height);
+ }
+ }
+
+ return _windowResizeBorderThickness;
+ }
+ }
+
+ public static Thickness WindowMaximizedPadding
+ {
+ get
+ {
+#if netle40
+ return WindowResizeBorderThickness;
+#elif Core
+ var hdc = UnsafeNativeMethods.GetDC(IntPtr.Zero);
+ var scale = UnsafeNativeMethods.GetDeviceCaps(hdc, NativeMethods.DESKTOPVERTRES) / (float)UnsafeNativeMethods.GetDeviceCaps(hdc, NativeMethods.VERTRES);
+ UnsafeNativeMethods.ReleaseDC(IntPtr.Zero, hdc);
+ return WindowResizeBorderThickness.Add(new Thickness(4 * scale));
+#else
+ return WindowResizeBorderThickness.Add(new Thickness(4));
+#endif
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/Interop/NativeMethods.cs b/src/Shared/HandyControl_Shared/Tools/Interop/NativeMethods.cs
index 66c17772..e41d4e26 100644
--- a/src/Shared/HandyControl_Shared/Tools/Interop/NativeMethods.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Interop/NativeMethods.cs
@@ -2,6 +2,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
+using System.Security;
namespace HandyControl.Tools.Interop
{
@@ -55,7 +56,15 @@ namespace HandyControl.Tools.Interop
MEM_COMMIT = 0x1000,
MEM_RELEASE = 0x8000,
PAGE_READWRITE = 0x04,
- TBSTATE_HIDDEN = 0x08;
+ TBSTATE_HIDDEN = 0x08,
+ VERTRES = 10,
+ HORZRES = 8,
+ DESKTOPVERTRES = 117,
+ DESKTOPHORZRES = 118,
+ LOGPIXELSX = 88,
+ LOGPIXELSY = 90,
+ CXFRAME = 32,
+ CXSIZEFRAME = CXFRAME;
[Flags]
public enum ProcessAccess
@@ -205,5 +214,10 @@ namespace HandyControl.Tools.Interop
[DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
public static extern bool GetCursorPos(out POINT pt);
+
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ [DllImport(ExternDll.User32)]
+ public static extern int GetSystemMetrics(SM nIndex);
}
}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/Interop/NativeValues.cs b/src/Shared/HandyControl_Shared/Tools/Interop/NativeValues.cs
index 2aef2758..94c1e09b 100644
--- a/src/Shared/HandyControl_Shared/Tools/Interop/NativeValues.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Interop/NativeValues.cs
@@ -87,7 +87,142 @@ namespace HandyControl.Tools.Interop
TABLETPC = 86,
MEDIACENTER = 87,
REMOTESESSION = 0x1000,
- REMOTECONTROL = 0x2001,
+ REMOTECONTROL = 0x2001
+ }
+
+ internal enum CacheSlot
+ {
+ DpiX,
+
+ FocusBorderWidth,
+ FocusBorderHeight,
+ HighContrast,
+ MouseVanish,
+
+ DropShadow,
+ FlatMenu,
+ WorkAreaInternal,
+ WorkArea,
+
+ IconMetrics,
+
+ KeyboardCues,
+ KeyboardDelay,
+ KeyboardPreference,
+ KeyboardSpeed,
+ SnapToDefaultButton,
+ WheelScrollLines,
+ MouseHoverTime,
+ MouseHoverHeight,
+ MouseHoverWidth,
+
+ MenuDropAlignment,
+ MenuFade,
+ MenuShowDelay,
+
+ ComboBoxAnimation,
+ ClientAreaAnimation,
+ CursorShadow,
+ GradientCaptions,
+ HotTracking,
+ ListBoxSmoothScrolling,
+ MenuAnimation,
+ SelectionFade,
+ StylusHotTracking,
+ ToolTipAnimation,
+ ToolTipFade,
+ UIEffects,
+
+ MinimizeAnimation,
+ Border,
+ CaretWidth,
+ ForegroundFlashCount,
+ DragFullWindows,
+ NonClientMetrics,
+
+ ThinHorizontalBorderHeight,
+ ThinVerticalBorderWidth,
+ CursorWidth,
+ CursorHeight,
+ ThickHorizontalBorderHeight,
+ ThickVerticalBorderWidth,
+ MinimumHorizontalDragDistance,
+ MinimumVerticalDragDistance,
+ FixedFrameHorizontalBorderHeight,
+ FixedFrameVerticalBorderWidth,
+ FocusHorizontalBorderHeight,
+ FocusVerticalBorderWidth,
+ FullPrimaryScreenWidth,
+ FullPrimaryScreenHeight,
+ HorizontalScrollBarButtonWidth,
+ HorizontalScrollBarHeight,
+ HorizontalScrollBarThumbWidth,
+ IconWidth,
+ IconHeight,
+ IconGridWidth,
+ IconGridHeight,
+ MaximizedPrimaryScreenWidth,
+ MaximizedPrimaryScreenHeight,
+ MaximumWindowTrackWidth,
+ MaximumWindowTrackHeight,
+ MenuCheckmarkWidth,
+ MenuCheckmarkHeight,
+ MenuButtonWidth,
+ MenuButtonHeight,
+ MinimumWindowWidth,
+ MinimumWindowHeight,
+ MinimizedWindowWidth,
+ MinimizedWindowHeight,
+ MinimizedGridWidth,
+ MinimizedGridHeight,
+ MinimumWindowTrackWidth,
+ MinimumWindowTrackHeight,
+ PrimaryScreenWidth,
+ PrimaryScreenHeight,
+ WindowCaptionButtonWidth,
+ WindowCaptionButtonHeight,
+ ResizeFrameHorizontalBorderHeight,
+ ResizeFrameVerticalBorderWidth,
+ SmallIconWidth,
+ SmallIconHeight,
+ SmallWindowCaptionButtonWidth,
+ SmallWindowCaptionButtonHeight,
+ VirtualScreenWidth,
+ VirtualScreenHeight,
+ VerticalScrollBarWidth,
+ VerticalScrollBarButtonHeight,
+ WindowCaptionHeight,
+ KanjiWindowHeight,
+ MenuBarHeight,
+ VerticalScrollBarThumbHeight,
+ IsImmEnabled,
+ IsMediaCenter,
+ IsMenuDropRightAligned,
+ IsMiddleEastEnabled,
+ IsMousePresent,
+ IsMouseWheelPresent,
+ IsPenWindows,
+ IsRemotelyControlled,
+ IsRemoteSession,
+ ShowSounds,
+ IsSlowMachine,
+ SwapButtons,
+ IsTabletPC,
+ VirtualScreenLeft,
+ VirtualScreenTop,
+
+ PowerLineStatus,
+
+ IsGlassEnabled,
+ UxThemeName,
+ UxThemeColor,
+ WindowCornerRadius,
+ WindowGlassColor,
+ WindowGlassBrush,
+ WindowNonClientFrameThickness,
+ WindowResizeBorderThickness,
+
+ NumSlots
}
internal static class Win32Constant
diff --git a/src/Shared/HandyControl_Shared/Tools/Interop/UnsafeNativeMethods.cs b/src/Shared/HandyControl_Shared/Tools/Interop/UnsafeNativeMethods.cs
index 2e4d1908..378eab05 100644
--- a/src/Shared/HandyControl_Shared/Tools/Interop/UnsafeNativeMethods.cs
+++ b/src/Shared/HandyControl_Shared/Tools/Interop/UnsafeNativeMethods.cs
@@ -215,5 +215,11 @@ namespace HandyControl.Tools.Interop
[DllImport(ExternDll.User32, SetLastError = true)]
public static extern int ReleaseDC(IntPtr window, IntPtr dc);
+
+ [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
+ public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
+
+ [DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
+ public static extern IntPtr GetDC(IntPtr ptr);
}
}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/Tools/StyleSelector/ButtonGroupItemStyleSelector.cs b/src/Shared/HandyControl_Shared/Tools/StyleSelector/ButtonGroupItemStyleSelector.cs
new file mode 100644
index 00000000..5edb7597
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Tools/StyleSelector/ButtonGroupItemStyleSelector.cs
@@ -0,0 +1,87 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using HandyControl.Controls;
+using HandyControl.Data;
+
+namespace HandyControl.Tools
+{
+ public class ButtonGroupItemStyleSelector : StyleSelector
+ {
+ public override Style SelectStyle(object item, DependencyObject container)
+ {
+ if (container is ButtonGroup buttonGroup && item is ButtonBase buttonBase)
+ {
+ var count = buttonGroup.Items.Count;
+
+ switch (buttonBase)
+ {
+ case RadioButton _:
+ {
+ if (count == 1)
+ {
+ return ResourceHelper.GetResource