using System; using System.Drawing; using System.Windows.Forms; using FastReport.Utils; namespace FastReport.Forms { /// /// Base class for all forms. /// public partial class BaseForm : Form { private FormStorageService storage; private bool canSaveRestoreState; private int oldDpi; protected int NewDpi { get; private set; } /// /// Gets the form's storage service. /// public FormStorageService Storage { get { if (storage == null) storage = new FormStorageService(this); return storage; } } /// /// Gets or sets value indicating that the form can save/restore the state such as location and size. /// public bool CanSaveRestoreState { get => canSaveRestoreState; set => canSaveRestoreState = value; } /// /// The event occurs on form's dpi change. /// public event EventHandler DpiChanged; #region Dpi convenience methods /// /// Convenience method returns an image with specified index for this form's dpi. /// /// Image index. /// The image. public Bitmap GetImage(int index) { return Res.GetImage(index, this.Dpi()); } /// /// Convenience method returns an image with specified name for this form's dpi. /// /// Image resource name. /// The image. public Bitmap GetImage(string resource) { return Res.GetImage(resource, this.Dpi()); } /// /// Convenience method returns an imagelist for this form's dpi. /// /// The imagelist. public ImageList GetImages() { return Res.GetImages(this.Dpi()); } #endregion /// /// Localizes the dialog controls. /// /// /// Use this method to set control's captions specific to the current locale. /// public virtual void Localize() { } /// /// Saves the form's state. /// protected virtual void SaveState() { if (CanSaveRestoreState) Storage.SaveFormState(); } /// /// Restores the form's state. /// protected virtual void RestoreState() { if (CanSaveRestoreState) Storage.RestoreFormState(); } /// protected override void OnFormClosed(FormClosedEventArgs e) { SaveState(); base.OnFormClosed(e); } /// protected override void OnLoad(EventArgs e) { RestoreState(); base.OnLoad(e); } #if !MONO /// protected override void WndProc(ref Message m) { const int WM_DPICHANGED = 0x02E0; if (m.Msg == WM_DPICHANGED) { // these properties if set to non-zero will lead to weird scaling on dpi change. // if you need them set them in the UpdateDpiDependencies method. MinimumSize = new Size(0, 0); MaximumSize = new Size(0, 0); } base.WndProc(ref m); if (m.Msg == WM_DPICHANGED) { NewDpi = this.Dpi(); if (NewDpi != oldDpi) { UpdateDpiDependencies(); if (DpiChanged != null) DpiChanged(this, EventArgs.Empty); oldDpi = NewDpi; } } } #elif (WPF || AVALONIA) /// protected override void OnDpiChanged(object sender, EventArgs e) { base.OnDpiChanged(sender, e); NewDpi = this.Dpi(); UpdateDpiDependencies(); if (DpiChanged != null) DpiChanged(this, EventArgs.Empty); } #endif private void FixCheckBoxesAndRadioButtons(Control parent) { foreach (Control c in parent.Controls) { ButtonBase b = c as ButtonBase; if (b != null && b.AutoSize) { // it fixes the problem with AutoSize set incorrectly during autoscale if (b.Text != "" && !b.Text.EndsWith(" ")) b.Text += " "; b.Width++; b.Width--; } FixCheckBoxesAndRadioButtons(c); } } /// /// Update controls on dpi change. /// /// This method is called when the form's dpi is changed. Write custom logic to update /// some controls (such as ListBox.ItemHeight) here. /// public virtual void UpdateDpiDependencies() { #if !MONO // Checkboxes and radiobuttons need special care. Sometimes they are not scaled properly // when a form moved to another monitor. FixCheckBoxesAndRadioButtons(this); #endif } /// /// Initializes a new instance of the class. /// public BaseForm() { InitializeComponent(); this.Font = DrawUtils.DefaultFont; } } }