mirror of
https://github.com/Kopano-dev/kopano-ol-extension.git
synced 2023-10-10 13:37:40 +02:00
Added edit and button portion of custom combo box.
This commit is contained in:
parent
74d2d5857c
commit
833cb6e4d3
@ -220,6 +220,9 @@
|
||||
<DependentUpon>KBusyIndicator.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KCheckManager.cs" />
|
||||
<Compile Include="Controls\KComboBox.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KCopyLabel.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
@ -251,6 +254,8 @@
|
||||
<Compile Include="Controls\KTreeRendererVisualStyles.cs" />
|
||||
<Compile Include="Controls\KUITask.cs" />
|
||||
<Compile Include="Controls\KUIUtil.cs" />
|
||||
<Compile Include="Controls\KVisualStateTracker.cs" />
|
||||
<Compile Include="Controls\KVisualStyle.cs" />
|
||||
<Compile Include="DebugOptions.cs" />
|
||||
<Compile Include="Features\BCC\FeatureBCC.cs" />
|
||||
<Compile Include="Features\DeliveryReceipts\FeatureDeliveryReceipts.cs" />
|
||||
@ -319,6 +324,7 @@
|
||||
<Compile Include="Native\MAPI\Property.cs" />
|
||||
<Compile Include="Native\MAPI\Restriction.cs" />
|
||||
<Compile Include="Native\MAPI\RestrictionEncoder.cs" />
|
||||
<Compile Include="Native\UXTheme.cs" />
|
||||
<Compile Include="OutlookConstants.cs" />
|
||||
<Compile Include="SearchQuery.cs" />
|
||||
<Compile Include="Stubs\Enums.cs" />
|
||||
@ -403,7 +409,7 @@
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="UI\GABLookupControl.cs">
|
||||
<SubType>Component</SubType>
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="UI\GABLookupControl.Designer.cs">
|
||||
<DependentUpon>GABLookupControl.cs</DependentUpon>
|
||||
|
168
src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
Normal file
168
src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
Normal file
@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Acacia.Controls
|
||||
{
|
||||
public class KComboBox : UserControl
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public ComboBoxStyle DropDownStyle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string DisplayMember
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Components
|
||||
|
||||
private TextBox _edit;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
|
||||
public KComboBox()
|
||||
{
|
||||
SetupRenderer();
|
||||
|
||||
_edit = new TextBox();
|
||||
_edit.BorderStyle = BorderStyle.None;
|
||||
Controls.Add(_edit);
|
||||
_state.AddControl(_edit);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Drop down
|
||||
|
||||
private void Button_Clicked()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rendering
|
||||
|
||||
private enum State
|
||||
{
|
||||
// Values match those defined in vsstyles.h so no conversion is needed.
|
||||
Normal = 1, Hot = 2, Pressed = 3, Disabled = 4
|
||||
}
|
||||
|
||||
private KVisualStyle<COMBOBOXPARTS, State> _style = new KVisualStyle<COMBOBOXPARTS, State>("COMBOBOX");
|
||||
|
||||
// Enum from vsstyles.h
|
||||
enum COMBOBOXPARTS
|
||||
{
|
||||
CP_DROPDOWNBUTTON = 1,
|
||||
CP_BACKGROUND = 2,
|
||||
CP_TRANSPARENTBACKGROUND = 3,
|
||||
CP_BORDER = 4,
|
||||
CP_READONLY = 5,
|
||||
CP_DROPDOWNBUTTONRIGHT = 6,
|
||||
CP_DROPDOWNBUTTONLEFT = 7,
|
||||
CP_CUEBANNER = 8,
|
||||
};
|
||||
|
||||
private KVisualStateTracker<State> _state;
|
||||
private KVisualStateTracker<State>.Part _stateButton;
|
||||
|
||||
public void SetupRenderer(bool enableVisualStyles = true)
|
||||
{
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.ContainerControl, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
SetStyle(ControlStyles.Selectable, true);
|
||||
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
SetStyle(ControlStyles.UserMouse, true);
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.Selectable, true);
|
||||
|
||||
_style[COMBOBOXPARTS.CP_DROPDOWNBUTTON].SetPadding(COMBOBOXPARTS.CP_DROPDOWNBUTTONLEFT,
|
||||
COMBOBOXPARTS.CP_DROPDOWNBUTTONRIGHT);
|
||||
|
||||
_state = new KVisualStateTracker<State>(this, State.Normal, State.Disabled);
|
||||
_state.Root.WithHot(State.Hot);
|
||||
_state.Root.WithFocus(State.Hot);
|
||||
|
||||
_stateButton = _state.Root.AddPart().WithPressed(State.Pressed);
|
||||
_stateButton.Clicked += Button_Clicked;
|
||||
|
||||
// TODO if (enableVisualStyles && Application.RenderWithVisualStyles)
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
_style[COMBOBOXPARTS.CP_BORDER]?.DrawBackground(e.Graphics, _state.Root.State, ClientRectangle);
|
||||
_style[COMBOBOXPARTS.CP_DROPDOWNBUTTON]?.DrawBackground(e.Graphics, _stateButton.State, _stateButton.Rectangle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Layout
|
||||
|
||||
protected override void OnLayout(LayoutEventArgs e)
|
||||
{
|
||||
base.OnLayout(e);
|
||||
|
||||
using (Graphics graphics = CreateGraphics())
|
||||
{
|
||||
// Determine the border insets
|
||||
Padding insets = _style[COMBOBOXPARTS.CP_BORDER]?.GetMargins(graphics, _state.Root.State) ?? new Padding();
|
||||
|
||||
// Determine the button size
|
||||
Size? buttonSize = _style[COMBOBOXPARTS.CP_DROPDOWNBUTTON]?.GetPartSize(graphics, _state.Root.State);
|
||||
if (!buttonSize.HasValue)
|
||||
buttonSize = new Size(ClientRectangle.Height, ClientRectangle.Height);
|
||||
|
||||
Rectangle buttonRect = new Rectangle();
|
||||
buttonRect.X = ClientRectangle.Width - buttonSize.Value.Width;
|
||||
buttonRect.Width = buttonSize.Value.Width;
|
||||
buttonRect.Y = 0;
|
||||
buttonRect.Height = ClientRectangle.Height;
|
||||
_stateButton.Rectangle = buttonRect;
|
||||
|
||||
// Set the edit control
|
||||
Rectangle editRect = new Rectangle(insets.Left, insets.Top, buttonRect.X - insets.Left,
|
||||
ClientRectangle.Height - insets.Vertical);
|
||||
editRect = editRect.CenterVertically(new Size(editRect.Width, _edit.PreferredHeight));
|
||||
_edit.SetBounds(editRect.X, editRect.Y, editRect.Width, editRect.Height);
|
||||
}
|
||||
}
|
||||
|
||||
public override Size GetPreferredSize(Size proposedSize)
|
||||
{
|
||||
// TODO: cache sizes?
|
||||
using (Graphics graphics = CreateGraphics())
|
||||
{
|
||||
Size editSize = _edit.GetPreferredSize(proposedSize);
|
||||
Padding insets = _style[COMBOBOXPARTS.CP_BORDER]?.GetMargins(graphics, _state.Root.State) ?? new Padding();
|
||||
|
||||
Size prefSize = editSize.Expand(insets);
|
||||
|
||||
Size? buttonSize = _style[COMBOBOXPARTS.CP_DROPDOWNBUTTON]?.GetPartSize(graphics, _state.Root.State);
|
||||
if (!buttonSize.HasValue)
|
||||
buttonSize = new Size(prefSize.Height, prefSize.Height);
|
||||
|
||||
return new Size(prefSize.Width + buttonSize.Value.Width, Math.Max(prefSize.Height, buttonSize.Value.Height));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -35,6 +35,12 @@ namespace Acacia.Controls
|
||||
return new Rectangle(x, y, size.Width, size.Height);
|
||||
}
|
||||
|
||||
public static Rectangle CenterVertically(this Rectangle _this, Size size)
|
||||
{
|
||||
int y = _this.Y + (_this.Height - size.Height) / 2;
|
||||
return new Rectangle(_this.X, y, size.Width, size.Height);
|
||||
}
|
||||
|
||||
public static Rectangle Expand(this Rectangle _this, Padding padding)
|
||||
{
|
||||
Rectangle r = _this;
|
||||
@ -75,6 +81,51 @@ namespace Acacia.Controls
|
||||
return new Size((int)(_this.Width * graphics.DpiX / 96), (int)(_this.Height * graphics.DpiY / 96));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the sizes horizontally. The height is the maximum of any of the elements' height.
|
||||
/// Any of the heights may be null.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The added sizes. Null is returned only if all sizes are null.
|
||||
/// </returns>
|
||||
public static Size? AddHorizontally(this Size? _this, params Size?[] add)
|
||||
{
|
||||
Size? s = _this;
|
||||
|
||||
foreach(Size? s2 in add)
|
||||
{
|
||||
if (s2.HasValue)
|
||||
{
|
||||
if (!s.HasValue)
|
||||
s = s2;
|
||||
else
|
||||
s = new Size(s.Value.Width + s2.Value.Width, Math.Max(s.Value.Height, s2.Value.Height));
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
public static Size? AddHorizontally(this Size _this, params Size?[] add)
|
||||
{
|
||||
return AddHorizontally((Size?)_this, add);
|
||||
}
|
||||
|
||||
public static Size Expand(this Size _this, Padding padding)
|
||||
{
|
||||
Size r = _this;
|
||||
r.Width += padding.Horizontal;
|
||||
r.Height += padding.Vertical;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Size Shrink(this Size _this, Padding padding)
|
||||
{
|
||||
Size r = _this;
|
||||
r.Width -= padding.Horizontal;
|
||||
r.Height -= padding.Vertical;
|
||||
return r;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,299 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Acacia.Controls
|
||||
{
|
||||
internal class KVisualStateTracker<StateTypeId>
|
||||
where StateTypeId: struct, IConvertible
|
||||
{
|
||||
public class Part
|
||||
{
|
||||
private KVisualStateTracker<StateTypeId> _tracker;
|
||||
private readonly StateTypeId? _normalState;
|
||||
private readonly StateTypeId? _disabledState;
|
||||
private StateTypeId? _hotState;
|
||||
private StateTypeId? _pressedState;
|
||||
private StateTypeId? _focusState;
|
||||
private bool _mouseOver;
|
||||
private bool _mousePressed;
|
||||
private bool _focused;
|
||||
private readonly Part _parent;
|
||||
private readonly List<Part> _children = new List<Part>();
|
||||
private Rectangle? _rectangle;
|
||||
|
||||
public Action Clicked { get; set; }
|
||||
|
||||
public Part(KVisualStateTracker<StateTypeId> tracker, StateTypeId? normalState, StateTypeId? disabledState)
|
||||
{
|
||||
this._tracker = tracker;
|
||||
this._normalState = normalState;
|
||||
this._disabledState = disabledState;
|
||||
}
|
||||
|
||||
public Part(KVisualStateTracker<StateTypeId> tracker, Part parent)
|
||||
{
|
||||
this._tracker = parent._tracker;
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
public StateTypeId State
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_parent != null && !_mouseOver)
|
||||
{
|
||||
return _parent.State;
|
||||
}
|
||||
|
||||
if (!_tracker._control.Enabled)
|
||||
{
|
||||
return DisabledState;
|
||||
}
|
||||
|
||||
if (_focused && FocusedState.HasValue)
|
||||
return FocusedState.Value;
|
||||
|
||||
if (_mouseOver && _mousePressed)
|
||||
return _pressedState.Value;
|
||||
|
||||
if (_mouseOver && HotState.HasValue)
|
||||
return HotState.Value;
|
||||
|
||||
return NormalState;
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Rectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_rectangle.HasValue)
|
||||
return _rectangle.Value;
|
||||
|
||||
return _tracker._control.ClientRectangle;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_parent == null)
|
||||
throw new InvalidOperationException("Cannot set rectangle on root element");
|
||||
_rectangle = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private StateTypeId DisabledState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_disabledState.HasValue)
|
||||
return _disabledState.Value;
|
||||
return _parent.DisabledState;
|
||||
}
|
||||
}
|
||||
|
||||
private StateTypeId NormalState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_normalState.HasValue)
|
||||
return _normalState.Value;
|
||||
return _parent.NormalState;
|
||||
}
|
||||
}
|
||||
|
||||
private StateTypeId? HotState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_hotState.HasValue)
|
||||
return _hotState.Value;
|
||||
return _parent.HotState;
|
||||
}
|
||||
}
|
||||
|
||||
private StateTypeId? FocusedState
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_focusState.HasValue)
|
||||
return _focusState.Value;
|
||||
return _parent.FocusedState;
|
||||
}
|
||||
}
|
||||
|
||||
private bool MouseOver
|
||||
{
|
||||
get { return _mouseOver; }
|
||||
set
|
||||
{
|
||||
if (_mouseOver != value)
|
||||
{
|
||||
_mouseOver = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool MousePressed
|
||||
{
|
||||
get { return _mousePressed; }
|
||||
set
|
||||
{
|
||||
if (_mousePressed != value)
|
||||
{
|
||||
_mousePressed = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool Focused
|
||||
{
|
||||
get { return _focused; }
|
||||
set
|
||||
{
|
||||
if (_focused != value)
|
||||
{
|
||||
_focused = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Invalidate()
|
||||
{
|
||||
_tracker.Invalidate();
|
||||
}
|
||||
|
||||
internal void GotFocus(object sender, EventArgs e)
|
||||
{
|
||||
Focused = true;
|
||||
}
|
||||
|
||||
internal void LostFocus(object sender, EventArgs e)
|
||||
{
|
||||
Focused = false;
|
||||
}
|
||||
|
||||
internal void MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_pressedState != null && e.Button.HasFlag(MouseButtons.Left))
|
||||
{
|
||||
MousePressed = Rectangle.Contains(e.Location);
|
||||
}
|
||||
|
||||
foreach (Part child in _children)
|
||||
{
|
||||
child.MouseDown(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
internal void MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
foreach (Part child in _children)
|
||||
{
|
||||
child.MouseUp(sender, e);
|
||||
}
|
||||
|
||||
if (e.Button.HasFlag(MouseButtons.Left))
|
||||
{
|
||||
if (_pressedState != null)
|
||||
{
|
||||
MousePressed = false;
|
||||
}
|
||||
|
||||
if (MouseOver && Clicked != null)
|
||||
{
|
||||
Clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseOver = Rectangle.Contains(e.Location);
|
||||
|
||||
foreach(Part child in _children)
|
||||
{
|
||||
child.MouseMove(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
internal void MouseLeave(object sender, EventArgs e)
|
||||
{
|
||||
MouseOver = false;
|
||||
foreach (Part child in _children)
|
||||
{
|
||||
child.MouseLeave(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Part AddPart()
|
||||
{
|
||||
Part child = new Part(_tracker, this);
|
||||
_children.Add(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
public Part WithPressed(StateTypeId? pressedState)
|
||||
{
|
||||
this._pressedState = pressedState;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Part WithHot(StateTypeId? hotState)
|
||||
{
|
||||
this._hotState = hotState;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Part WithFocus(StateTypeId? focusState)
|
||||
{
|
||||
this._focusState = focusState;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Control _control;
|
||||
private readonly List<Control> _additionalControls = new List<Control>();
|
||||
public readonly Part Root;
|
||||
|
||||
public KVisualStateTracker(Control control, StateTypeId normalState, StateTypeId disabledState)
|
||||
{
|
||||
this._control = control;
|
||||
Root = new Part(this, normalState, disabledState);
|
||||
AddControl(_control);
|
||||
_control.EnabledChanged += Control_EnabledChanged;
|
||||
}
|
||||
|
||||
public void AddControl(Control child)
|
||||
{
|
||||
if (child != _control)
|
||||
{
|
||||
_additionalControls.Add(child);
|
||||
}
|
||||
child.MouseLeave += Root.MouseLeave;
|
||||
child.MouseMove += Root.MouseMove;
|
||||
child.MouseDown += Root.MouseDown;
|
||||
child.MouseUp += Root.MouseUp;
|
||||
child.GotFocus += Root.GotFocus;
|
||||
child.LostFocus += Root.LostFocus;
|
||||
}
|
||||
|
||||
private void Control_EnabledChanged(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private void Invalidate()
|
||||
{
|
||||
_control.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
141
src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KVisualStyle.cs
Normal file
141
src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KVisualStyle.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using Acacia.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Forms.VisualStyles;
|
||||
|
||||
namespace Acacia.Controls
|
||||
{
|
||||
internal class KVisualStyle<PartTypeId, StateTypeId>
|
||||
where PartTypeId : struct, IConvertible
|
||||
where StateTypeId : struct, IConvertible
|
||||
{
|
||||
public class Part
|
||||
{
|
||||
private readonly KVisualStyle<PartTypeId, StateTypeId> _style;
|
||||
private readonly PartTypeId _partId;
|
||||
private Dictionary<StateTypeId, VisualStyleRenderer> _renderers;
|
||||
private Part _paddingLeft;
|
||||
private Part _paddingRight;
|
||||
|
||||
public Part(KVisualStyle<PartTypeId, StateTypeId> style, PartTypeId id)
|
||||
{
|
||||
this._style = style;
|
||||
this._partId = id;
|
||||
}
|
||||
|
||||
public void DrawBackground(Graphics graphics, StateTypeId state, Rectangle rect)
|
||||
{
|
||||
VisualStyleRenderer r = GetRenderer(state);
|
||||
if (r != null)
|
||||
{
|
||||
r.DrawBackground(graphics, rect);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawText(Graphics graphics, StateTypeId state, Rectangle rect, string text)
|
||||
{
|
||||
VisualStyleRenderer r = GetRenderer(state);
|
||||
if (r != null)
|
||||
{
|
||||
r.DrawText(graphics, rect, text); // TODO: disabled
|
||||
}
|
||||
}
|
||||
|
||||
private VisualStyleRenderer GetRenderer(StateTypeId state)
|
||||
{
|
||||
InitRenderers();
|
||||
VisualStyleRenderer renderer;
|
||||
_renderers.TryGetValue(state, out renderer);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
private void InitRenderers()
|
||||
{
|
||||
if (_renderers == null)
|
||||
{
|
||||
_renderers = new Dictionary<StateTypeId, VisualStyleRenderer>();
|
||||
foreach (StateTypeId entry in Enum.GetValues(typeof(StateTypeId)))
|
||||
{
|
||||
try
|
||||
{
|
||||
int id = _partId.ToInt32(null);
|
||||
int entryId = entry.ToInt32(null);
|
||||
_renderers.Add(entry, new VisualStyleRenderer(_style.ClassName, id, entryId));
|
||||
}
|
||||
catch (Exception e) { Logger.Instance.Trace(this, "Renderer not supported: {0}", e); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Size? GetPartSize(Graphics graphics, StateTypeId state)
|
||||
{
|
||||
VisualStyleRenderer renderer = GetRenderer(state);
|
||||
if (renderer == null)
|
||||
return null;
|
||||
|
||||
Size size = renderer.GetPartSize(graphics, ThemeSizeType.True);
|
||||
return size.AddHorizontally(_paddingLeft?.GetPartSize(graphics, state),
|
||||
_paddingRight?.GetPartSize(graphics, state));
|
||||
}
|
||||
|
||||
public Padding? GetMargins(Graphics graphics, StateTypeId state)
|
||||
{
|
||||
VisualStyleRenderer renderer = GetRenderer(state);
|
||||
if (renderer == null)
|
||||
return null;
|
||||
|
||||
|
||||
// VisualStyleRenderer.GetMargins always throws an exception, make an explicit API call
|
||||
int stateId = state.ToInt32(null);
|
||||
UXTheme.MARGINS margins;
|
||||
IntPtr hdc = graphics.GetHdc();
|
||||
try
|
||||
{
|
||||
UXTheme.GetThemeMargins(renderer.Handle, hdc, this._partId.ToInt32(null), stateId,
|
||||
(int)MarginProperty.SizingMargins, IntPtr.Zero, out margins);
|
||||
// TODO: include padding
|
||||
return new Padding(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight);
|
||||
}
|
||||
finally
|
||||
{
|
||||
graphics.ReleaseHdc(hdc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetPadding(PartTypeId paddingLeft, PartTypeId paddingRight)
|
||||
{
|
||||
this._paddingLeft = _style[paddingLeft];
|
||||
this._paddingRight = _style[paddingRight];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private readonly string ClassName;
|
||||
private readonly Dictionary<PartTypeId, Part> _parts = new Dictionary<PartTypeId, Part>();
|
||||
|
||||
public KVisualStyle(string name)
|
||||
{
|
||||
this.ClassName = name;
|
||||
}
|
||||
|
||||
public Part this[PartTypeId index]
|
||||
{
|
||||
get
|
||||
{
|
||||
Part part;
|
||||
if (!_parts.TryGetValue(index, out part))
|
||||
{
|
||||
part = new Part(this, index);
|
||||
_parts.Add(index, part);
|
||||
}
|
||||
return part;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -111,7 +111,6 @@
|
||||
//
|
||||
this.gabLookup.DisplayMember = "DisplayName";
|
||||
resources.ApplyResources(this.gabLookup, "gabLookup");
|
||||
this.gabLookup.FormattingEnabled = true;
|
||||
this.gabLookup.GAB = null;
|
||||
this.gabLookup.Name = "gabLookup";
|
||||
this.gabLookup.SelectedUserChanged += new Acacia.UI.GABLookupControl.SelectedUserEventHandler(this.gabLookup_SelectedUserChanged);
|
||||
|
24
src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/UXTheme.cs
Normal file
24
src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/UXTheme.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Acacia.Native
|
||||
{
|
||||
public static class UXTheme
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct MARGINS
|
||||
{
|
||||
public int cxLeftWidth;
|
||||
public int cxRightWidth;
|
||||
public int cyTopHeight;
|
||||
public int cyBottomHeight;
|
||||
}
|
||||
|
||||
[DllImport("uxtheme.dll")]
|
||||
public static extern int GetThemeMargins(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, int iPropId, IntPtr prc, out MARGINS pMargins);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user