BaseForm.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System;
  2. using System.Drawing;
  3. using System.Windows.Forms;
  4. using FastReport.Utils;
  5. namespace FastReport.Forms
  6. {
  7. /// <summary>
  8. /// Base class for all forms.
  9. /// </summary>
  10. public partial class BaseForm : Form
  11. {
  12. private FormStorageService storage;
  13. private bool canSaveRestoreState;
  14. private int oldDpi;
  15. protected int NewDpi { get; private set; }
  16. /// <summary>
  17. /// Gets the form's storage service.
  18. /// </summary>
  19. public FormStorageService Storage
  20. {
  21. get
  22. {
  23. if (storage == null)
  24. storage = new FormStorageService(this);
  25. return storage;
  26. }
  27. }
  28. /// <summary>
  29. /// Gets or sets value indicating that the form can save/restore the state such as location and size.
  30. /// </summary>
  31. public bool CanSaveRestoreState
  32. {
  33. get => canSaveRestoreState;
  34. set => canSaveRestoreState = value;
  35. }
  36. /// <summary>
  37. /// The event occurs on form's dpi change.
  38. /// </summary>
  39. public event EventHandler DpiChanged;
  40. #region Dpi convenience methods
  41. /// <summary>
  42. /// Convenience method returns an image with specified index for this form's dpi.
  43. /// </summary>
  44. /// <param name="index">Image index.</param>
  45. /// <returns>The image.</returns>
  46. public Bitmap GetImage(int index)
  47. {
  48. return Res.GetImage(index, this.Dpi());
  49. }
  50. /// <summary>
  51. /// Convenience method returns an image with specified name for this form's dpi.
  52. /// </summary>
  53. /// <param name="resource">Image resource name.</param>
  54. /// <returns>The image.</returns>
  55. public Bitmap GetImage(string resource)
  56. {
  57. return Res.GetImage(resource, this.Dpi());
  58. }
  59. /// <summary>
  60. /// Convenience method returns an imagelist for this form's dpi.
  61. /// </summary>
  62. /// <returns>The imagelist.</returns>
  63. public ImageList GetImages()
  64. {
  65. return Res.GetImages(this.Dpi());
  66. }
  67. #endregion
  68. /// <summary>
  69. /// Localizes the dialog controls.
  70. /// </summary>
  71. /// <remarks>
  72. /// Use this method to set control's captions specific to the current locale.
  73. /// </remarks>
  74. public virtual void Localize()
  75. {
  76. }
  77. /// <summary>
  78. /// Saves the form's state.
  79. /// </summary>
  80. protected virtual void SaveState()
  81. {
  82. if (CanSaveRestoreState)
  83. Storage.SaveFormState();
  84. }
  85. /// <summary>
  86. /// Restores the form's state.
  87. /// </summary>
  88. protected virtual void RestoreState()
  89. {
  90. if (CanSaveRestoreState)
  91. Storage.RestoreFormState();
  92. }
  93. /// <inheritdoc/>
  94. protected override void OnFormClosed(FormClosedEventArgs e)
  95. {
  96. SaveState();
  97. base.OnFormClosed(e);
  98. }
  99. /// <inheritdoc/>
  100. protected override void OnLoad(EventArgs e)
  101. {
  102. RestoreState();
  103. base.OnLoad(e);
  104. }
  105. #if !MONO
  106. /// <inheritdoc/>
  107. protected override void WndProc(ref Message m)
  108. {
  109. const int WM_DPICHANGED = 0x02E0;
  110. if (m.Msg == WM_DPICHANGED)
  111. {
  112. // these properties if set to non-zero will lead to weird scaling on dpi change.
  113. // if you need them set them in the UpdateDpiDependencies method.
  114. MinimumSize = new Size(0, 0);
  115. MaximumSize = new Size(0, 0);
  116. }
  117. base.WndProc(ref m);
  118. if (m.Msg == WM_DPICHANGED)
  119. {
  120. NewDpi = this.Dpi();
  121. if (NewDpi != oldDpi)
  122. {
  123. UpdateDpiDependencies();
  124. if (DpiChanged != null)
  125. DpiChanged(this, EventArgs.Empty);
  126. oldDpi = NewDpi;
  127. }
  128. }
  129. }
  130. #elif (WPF || AVALONIA)
  131. /// <inheritdoc/>
  132. protected override void OnDpiChanged(object sender, EventArgs e)
  133. {
  134. base.OnDpiChanged(sender, e);
  135. NewDpi = this.Dpi();
  136. UpdateDpiDependencies();
  137. if (DpiChanged != null)
  138. DpiChanged(this, EventArgs.Empty);
  139. }
  140. #endif
  141. private void FixCheckBoxesAndRadioButtons(Control parent)
  142. {
  143. foreach (Control c in parent.Controls)
  144. {
  145. ButtonBase b = c as ButtonBase;
  146. if (b != null && b.AutoSize)
  147. {
  148. // it fixes the problem with AutoSize set incorrectly during autoscale
  149. if (b.Text != "" && !b.Text.EndsWith(" "))
  150. b.Text += " ";
  151. b.Width++;
  152. b.Width--;
  153. }
  154. FixCheckBoxesAndRadioButtons(c);
  155. }
  156. }
  157. /// <summary>
  158. /// Update controls on dpi change.
  159. /// </summary>
  160. /// <remarks>This method is called when the form's dpi is changed. Write custom logic to update
  161. /// some controls (such as ListBox.ItemHeight) here.
  162. /// </remarks>
  163. public virtual void UpdateDpiDependencies()
  164. {
  165. #if !MONO
  166. // Checkboxes and radiobuttons need special care. Sometimes they are not scaled properly
  167. // when a form moved to another monitor.
  168. FixCheckBoxesAndRadioButtons(this);
  169. #endif
  170. }
  171. /// <summary>
  172. /// Initializes a new instance of the <see cref="BaseForm"/> class.
  173. /// </summary>
  174. public BaseForm()
  175. {
  176. InitializeComponent();
  177. this.Font = DrawUtils.DefaultFont;
  178. }
  179. }
  180. }