123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- using System;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Reflection;
- namespace FastReport.Utils
- {
- /// <summary>
- /// A static class that contains methods to auto-convert rtl layout.
- /// </summary>
- public static class UIUtils
- {
- #region RTL support methods
- /// <summary>
- /// Changes control's layout to rtl.
- /// </summary>
- /// <param name="parent"></param>
- public static void CheckRTL(Control parent)
- {
- if (!Config.RightToLeft)
- return;
-
- parent.RightToLeft = RightToLeft.Yes;
- parent.SuspendLayout();
- foreach (Control item in parent.Controls)
- {
- try
- {
- AnchorStyles anchor = AnchorStyles.None;
- if ((item.Anchor & AnchorStyles.Left) != 0)
- anchor |= AnchorStyles.Right;
- if ((item.Anchor & AnchorStyles.Right) != 0)
- anchor |= AnchorStyles.Left;
- if ((item.Anchor & AnchorStyles.Top) != 0)
- anchor |= AnchorStyles.Top;
- if ((item.Anchor & AnchorStyles.Bottom) != 0)
- anchor |= AnchorStyles.Bottom;
-
- DockStyle dock = item.Dock;
- if (item.Dock == DockStyle.Left)
- dock = DockStyle.Right;
- if (item.Dock == DockStyle.Right)
- dock = DockStyle.Left;
-
- int width = parent is Form ? (parent as Form).ClientSize.Width : parent.Width;
- if (!(item is SplitterPanel))
- {
- item.Location = new Point(width - item.Size.Width - item.Location.X, item.Location.Y);
- item.Anchor = anchor;
- item.Dock = dock;
- }
- if (item is TreeView)
- {
- (item as TreeView).RightToLeftLayout = true;
- }
- CheckRTL(item);
- }
- catch
- {
- }
- }
- parent.ResumeLayout();
- }
- #endregion
- #region Draw extension methods
- /// <summary>
- /// Draws an image and a text.
- /// </summary>
- /// <param name="control">The control which is used to determine RTL and DPI settings.</param>
- /// <param name="e">The draw event args.</param>
- /// <param name="img">The image.</param>
- /// <param name="text">The text.</param>
- /// <remarks>This method is used to draw items in an owner-drawn listboxes and comboboxes. It respects RTL and DPI settings of a control.</remarks>
- public static void DrawImageAndText(this Control control, DrawItemEventArgs e, Image img, string text)
- {
- Graphics g = e.Graphics;
- int offsX = 2;
- if (img != null)
- {
- Rectangle imgRect = new Rectangle(
- control.RightToLeft == RightToLeft.Yes ? e.Bounds.Right - img.Width - control.LogicalToDevice(4) : e.Bounds.X + control.LogicalToDevice(4),
- e.Bounds.Y + (e.Bounds.Height - img.Height) / 2,
- img.Width,
- img.Height);
- g.DrawImage(img, imgRect);
- offsX = img.Width + control.LogicalToDevice(8);
- }
- Rectangle textRect = new Rectangle(
- control.RightToLeft == RightToLeft.Yes ? e.Bounds.X : e.Bounds.X + offsX,
- e.Bounds.Y,
- e.Bounds.Width - offsX,
- e.Bounds.Height);
- TextFormatFlags flags = TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis;
- if (control.RightToLeft == RightToLeft.Yes)
- flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
- TextRenderer.DrawText(g, text, e.Font, textRect, e.ForeColor, flags);
- }
- #endregion
- #region DPI Extension methods
- // Per-monitor DPI support extension methods.
- // In .Net 4.7 MS introduced new properties and methods such as Control.DeviceDpi and Control.LogicalToDeviceUnits.
- // Since we are targeting .Net 4.0, emulate these methods in earlier versions of fw (also on Mono),
- // and use reflection to call these methods if they exist.
- /// <summary>
- /// Gets current dpi value for the control.
- /// </summary>
- /// <param name="control">The control.</param>
- /// <returns>The dpi value.</returns>
- public static int Dpi(this Control control)
- {
- try
- {
- // the reason why we use a form instead of a control: the control may not be updated yet
- // if we call this code from WM_DPICHANGED handler
- Form form = control.FindForm();
- if (form != null)
- control = form;
- // introduced in .Net 4.7
- PropertyInfo p = control.GetType().GetProperty("DeviceDpi");
- if (p != null)
- return (int)(p.GetValue(control, null));
- }
- catch
- { }
-
- return DrawUtils.ScreenDpi;
- }
- /// <summary>
- /// Gets current dpi multiplier for the control (1.0 for 96dpi).
- /// </summary>
- /// <param name="control">The control.</param>
- /// <returns>The dpi multiplier.</returns>
- public static float DpiMultiplier(this Control control)
- {
- return control.Dpi() / 96f;
- }
- /// <summary>
- /// Gets current font dpi multiplier for the control (1.0 for 96dpi).
- /// </summary>
- /// <remarks>The return value depends on the base resolution of the main screen.</remarks>
- /// <param name="control">The control.</param>
- /// <returns>The font dpi multiplier.</returns>
- public static float FontDpiMultiplier(this Control control)
- {
- return (float)control.Dpi() / DrawUtils.ScreenDpi;
- }
- /// <summary>
- /// Converts logical units to device units (pixels).
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="value">Logical units.</param>
- /// <returns>Device units.</returns>
- public static int LogicalToDevice(this Control control, int value)
- {
- return (int)(value * control.DpiMultiplier());
- }
- /// <summary>
- /// Converts logical units to device units (pixels).
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="value">Logical units.</param>
- /// <returns>Device units.</returns>
- public static float LogicalToDevice(this Control control, float value)
- {
- return value * control.DpiMultiplier();
- }
- /// <summary>
- /// Converts logical units to device units (pixels).
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="value">Logical units.</param>
- /// <returns>Device units.</returns>
- public static Rectangle LogicalToDevice(this Control control, Rectangle value)
- {
- return new Rectangle(
- control.LogicalToDevice(value.Left),
- control.LogicalToDevice(value.Top),
- control.LogicalToDevice(value.Width),
- control.LogicalToDevice(value.Height));
- }
- /// <summary>
- /// Converts logical units to device units (pixels).
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="value">Logical units.</param>
- /// <returns>Device units.</returns>
- public static Point LogicalToDevice(this Control control, Point value)
- {
- return new Point(
- control.LogicalToDevice(value.X),
- control.LogicalToDevice(value.Y));
- }
- /// <summary>
- /// Converts logical units to device units (pixels).
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="value">Logical units.</param>
- /// <returns>Device units.</returns>
- public static Size LogicalToDevice(this Control control, Size value)
- {
- return new Size(
- control.LogicalToDevice(value.Width),
- control.LogicalToDevice(value.Height));
- }
- /// <summary>
- /// Converts logical font to device font.
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="value">Logical font.</param>
- /// <param name="disposeOriginal">Determines whether to dispose the original font or not.</param>
- /// <returns>Device font.</returns>
- public static Font LogicalToDevice(this Control control, Font value, bool disposeOriginal = false)
- {
- float mult = (float)control.Dpi() / DrawUtils.ScreenDpi;
- Font result = new Font(value.Name, value.Size * mult, value.Style);
- if (disposeOriginal)
- value.Dispose();
- return result;
- }
- #endregion
- #region Image helper extension methods
- /// <summary>
- /// Returns an image from resources using control's dpi value.
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="index">Image index.</param>
- /// <returns>An image with specified index from "buttons.png" resource.</returns>
- public static Image GetImage(this Control control, int index)
- {
- return Res.GetImage(index, control.Dpi());
- }
- /// <summary>
- /// Returns an image from resources using control's dpi value.
- /// </summary>
- /// <param name="control">The control.</param>
- /// <param name="name">Image name.</param>
- /// <returns>An image with specified index from "buttons.png" resource.</returns>
- public static Image GetImage(this Control control, string name)
- {
- return Res.GetImage(name, control.Dpi());
- }
- /// <summary>
- /// Returns an imagelist from resources using control's dpi value.
- /// </summary>
- /// <param name="control">The control.</param>
- /// <returns>An imagelist from "buttons.png" resource.</returns>
- public static ImageList GetImages(this Control control)
- {
- return Res.GetImages(control.Dpi());
- }
- #endregion
- }
- }
|