Form.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2004 Novell, Inc.
  21. //
  22. // Authors:
  23. // Peter Bartok [email protected]
  24. //
  25. // NOT COMPLETE
  26. using System;
  27. using System.Drawing;
  28. using System.ComponentModel;
  29. using System.Collections;
  30. using System.Runtime.InteropServices;
  31. using System.Threading;
  32. namespace System.Windows.Forms {
  33. public class Form : ContainerControl {
  34. #region Local Variables
  35. internal bool closing;
  36. [Flags]
  37. enum Flags {
  38. ShowInTaskbar = 0x0001,
  39. MaximizeBox = 0x0002,
  40. MinimizeBox = 0x0004,
  41. TopMost = 0x0008
  42. }
  43. Flags flags = Flags.ShowInTaskbar | Flags.MaximizeBox | Flags.MinimizeBox;
  44. FormBorderStyle formBorderStyle = FormBorderStyle.Sizable;
  45. private static bool autoscale;
  46. private static Size autoscale_base_size;
  47. private bool is_modal;
  48. internal bool end_modal; // This var is being monitored by the application modal loop
  49. private IButtonControl accept_button;
  50. private IButtonControl cancel_button;
  51. private DialogResult dialog_result;
  52. private FormStartPosition start_position;
  53. private Form owner;
  54. private Form.ControlCollection owned_forms;
  55. private bool key_preview;
  56. private MainMenu menu;
  57. internal FormParentWindow form_parent_window;
  58. #endregion // Local Variables
  59. #region Private Classes
  60. // This class will take over for the client area
  61. internal class FormParentWindow : Control {
  62. #region FormParentWindow Class Local Variables
  63. internal Form owner;
  64. #endregion // FormParentWindow Class Local Variables
  65. #region FormParentWindow Class Constructor
  66. internal FormParentWindow(Form owner) : base() {
  67. this.owner = owner;
  68. this.Width = 250;
  69. this.Height = 250;
  70. BackColor = owner.BackColor;
  71. Text = "FormParent";
  72. this.Location = new Point(0, 0);
  73. this.Dock = DockStyle.Fill;
  74. MouseDown += new MouseEventHandler (OnMouseDownForm);
  75. MouseMove += new MouseEventHandler (OnMouseMoveForm);
  76. owner.TextChanged += new EventHandler(OnFormTextChanged);
  77. }
  78. #endregion // FormParentWindow Class Constructor
  79. #region FormParentWindow Class Protected Instance Methods
  80. protected override CreateParams CreateParams {
  81. get {
  82. CreateParams cp;
  83. cp = base.CreateParams;
  84. cp.Style = (int)(WindowStyles.WS_OVERLAPPEDWINDOW |
  85. WindowStyles.WS_VISIBLE |
  86. WindowStyles.WS_CLIPSIBLINGS |
  87. WindowStyles.WS_CLIPCHILDREN);
  88. cp.Width = 250;
  89. cp.Height = 250;
  90. #if later
  91. if (this.IsHandleCreated) {
  92. int x;
  93. int y;
  94. int width;
  95. int height;
  96. int cwidth;
  97. int cheight;
  98. XplatUI.GetWindowPos(this.window.Handle, out x, out y, out width, out height, out cwidth, out cheight);
  99. UpdateBounds(x, y, width, height);
  100. owner.UpdateBounds(x, y, width, height);
  101. }
  102. #endif
  103. return cp;
  104. }
  105. }
  106. protected override void OnResize(EventArgs e) {
  107. base.OnResize(e);
  108. //owner.SetBoundsCore(owner.Bounds.X, owner.Bounds.Y, ClientSize.Width, ClientSize.Height, BoundsSpecified.All);
  109. if (owner.menu == null) {
  110. owner.SetBoundsCore(0, 0, ClientSize.Width, ClientSize.Height, BoundsSpecified.All);
  111. } else {
  112. int menu_height;
  113. menu_height = MenuAPI.MenuBarCalcSize(DeviceContext, owner.Menu.menu_handle, ClientSize.Width);
  114. Invalidate (new Rectangle (0, 0, ClientSize.Width, menu_height));
  115. owner.SetBoundsCore(0, menu_height, ClientSize.Width, ClientSize.Height-menu_height, BoundsSpecified.All);
  116. }
  117. }
  118. protected override void OnPaint(PaintEventArgs pevent) {
  119. OnDrawMenu (pevent.Graphics);
  120. }
  121. protected override void WndProc(ref Message m) {
  122. switch((Msg)m.Msg) {
  123. case Msg.WM_CLOSE: {
  124. CancelEventArgs args = new CancelEventArgs();
  125. owner.OnClosing(args);
  126. if (!args.Cancel) {
  127. owner.OnClosed(EventArgs.Empty);
  128. owner.closing = true;
  129. base.WndProc(ref m);
  130. break;
  131. }
  132. break;
  133. }
  134. default: {
  135. base.WndProc (ref m);
  136. break;
  137. }
  138. }
  139. }
  140. #endregion // FormParentWindow Class Protected Instance Methods
  141. #region FormParentWindow Class Private Methods
  142. private void OnMouseDownForm (object sender, MouseEventArgs e) {
  143. if (owner.menu != null)
  144. owner.menu.OnMouseDown (owner, e);
  145. }
  146. private void OnMouseMoveForm (object sender, MouseEventArgs e) {
  147. if (owner.menu != null)
  148. owner.menu.OnMouseMove (owner, e);
  149. }
  150. private void OnDrawMenu (Graphics dc) {
  151. if (owner.menu != null) {
  152. Rectangle rect = new Rectangle (0,0, Width, 0);
  153. MenuAPI.DrawMenuBar (dc, owner.menu.Handle, rect);
  154. }
  155. }
  156. private void OnFormTextChanged(object sender, EventArgs e) {
  157. this.Text = ((Control)sender).Text;
  158. }
  159. #endregion // FormParentWindow Class Private Methods
  160. }
  161. #endregion // Private Classes
  162. #region Public Classes
  163. public class ControlCollection : Control.ControlCollection {
  164. Form form_owner;
  165. public ControlCollection(Form owner) : base(owner) {
  166. this.form_owner = owner;
  167. }
  168. public override void Add(Control value) {
  169. for (int i=0; i<list.Count; i++) {
  170. if (list[i]==value) {
  171. // Do we need to do anything here?
  172. return;
  173. }
  174. }
  175. list.Add(value);
  176. ((Form)value).owner=(Form)owner;
  177. }
  178. public override void Remove(Control value) {
  179. ((Form)value).owner = null;
  180. base.Remove (value);
  181. }
  182. }
  183. #endregion // Public Classes
  184. #region Public Constructor & Destructor
  185. public Form() {
  186. closing = false;
  187. is_modal = false;
  188. end_modal = false;
  189. dialog_result = DialogResult.None;
  190. start_position = FormStartPosition.WindowsDefaultLocation;
  191. key_preview = false;
  192. menu = null;
  193. owned_forms = new Form.ControlCollection(this);
  194. }
  195. #endregion // Public Constructor & Destructor
  196. #region Public Static Properties
  197. public static Form ActiveForm {
  198. get {
  199. //FIXME: create next driver call
  200. return null;
  201. }
  202. }
  203. #endregion // Public Static Properties
  204. #region Public Instance Properties
  205. public IButtonControl AcceptButton {
  206. get {
  207. return accept_button;
  208. }
  209. set {
  210. accept_button = value;
  211. }
  212. }
  213. public bool AutoScale {
  214. get {
  215. return autoscale;
  216. }
  217. set {
  218. autoscale=value;
  219. }
  220. }
  221. public virtual Size AutoScaleBaseSize {
  222. get {
  223. return autoscale_base_size;
  224. }
  225. set {
  226. autoscale_base_size=value;
  227. }
  228. }
  229. public IButtonControl CancelButton {
  230. get {
  231. return cancel_button;
  232. }
  233. set {
  234. cancel_button = value;
  235. }
  236. }
  237. public DialogResult DialogResult {
  238. get {
  239. return dialog_result;
  240. }
  241. set {
  242. dialog_result = value;
  243. if (is_modal && (dialog_result != DialogResult.None)) {
  244. end_modal = true;
  245. }
  246. }
  247. }
  248. public FormBorderStyle FormBorderStyle {
  249. get {
  250. return formBorderStyle;
  251. }
  252. set {
  253. formBorderStyle = value;
  254. Invalidate ();
  255. }
  256. }
  257. public bool KeyPreview {
  258. get {
  259. return key_preview;
  260. }
  261. set {
  262. key_preview = value;
  263. }
  264. }
  265. public bool MaximizeBox {
  266. get {
  267. return (flags & Flags.MaximizeBox) != 0;
  268. }
  269. set {
  270. if (value)
  271. flags &= ~Flags.MaximizeBox;
  272. else
  273. flags |= Flags.MaximizeBox;
  274. }
  275. }
  276. public MainMenu Menu {
  277. get {
  278. return menu;
  279. }
  280. set {
  281. if (menu != value) {
  282. if (value == null) {
  283. form_parent_window.Width = form_parent_window.Width; // Trigger a resize
  284. }
  285. menu = value;
  286. // To simulate the non-client are for menus we create a
  287. // new control as the 'client area' of our form. This
  288. // way, the origin stays 0,0 and we don't have to fiddle with
  289. // coordinates. The menu area is part of the original container
  290. if (menu != null) {
  291. form_parent_window.Width = form_parent_window.Width; // Trigger a resize
  292. }
  293. menu.SetForm (this);
  294. MenuAPI.SetMenuBarWindow (menu.Handle, form_parent_window);
  295. }
  296. }
  297. }
  298. public bool MinimizeBox {
  299. get {
  300. return (flags & Flags.MinimizeBox) != 0;
  301. }
  302. set {
  303. if (value)
  304. flags &= ~Flags.MinimizeBox;
  305. else
  306. flags |= Flags.MinimizeBox;
  307. }
  308. }
  309. public bool Modal {
  310. get {
  311. return is_modal;
  312. }
  313. }
  314. public Form[] OwnedForms {
  315. get {
  316. Form[] form_list;
  317. form_list = new Form[owned_forms.Count];
  318. for (int i=0; i<owned_forms.Count; i++) {
  319. form_list[i] = (Form)owned_forms[i];
  320. }
  321. return form_list;
  322. }
  323. }
  324. public Form Owner {
  325. get {
  326. return owner;
  327. }
  328. set {
  329. if (owner != value) {
  330. if (owner != null) {
  331. owner.RemoveOwnedForm(this);
  332. }
  333. owner = value;
  334. owner.AddOwnedForm(this);
  335. if (owner != null) {
  336. XplatUI.SetTopmost(this.window.Handle, owner.window.Handle, true);
  337. } else {
  338. XplatUI.SetTopmost(this.window.Handle, IntPtr.Zero, false);
  339. }
  340. }
  341. }
  342. }
  343. public bool ShowInTaskbar {
  344. get {
  345. return (flags & Flags.ShowInTaskbar) != 0;
  346. }
  347. set {
  348. if (value)
  349. flags &= ~Flags.ShowInTaskbar;
  350. else
  351. flags |= Flags.ShowInTaskbar;
  352. }
  353. }
  354. public FormStartPosition StartPosition {
  355. get {
  356. return start_position;
  357. }
  358. set {
  359. if (start_position == FormStartPosition.WindowsDefaultLocation) { // Only do this if it's not set yet
  360. start_position = value;
  361. if (form_parent_window.IsHandleCreated) {
  362. switch(start_position) {
  363. case FormStartPosition.CenterParent: {
  364. if (Parent!=null && Width>0 && Height>0) {
  365. this.Location = new Point(Parent.Size.Width/2-Width/2, Parent.Size.Height/2-Height/2);
  366. }
  367. break;
  368. }
  369. case FormStartPosition.CenterScreen: {
  370. if (Width>0 && Height>0) {
  371. Size DisplaySize;
  372. XplatUI.GetDisplaySize(out DisplaySize);
  373. this.Location = new Point(DisplaySize.Width/2-Width/2, DisplaySize.Height/2-Height/2);
  374. }
  375. break;
  376. }
  377. default: {
  378. break;
  379. }
  380. }
  381. }
  382. }
  383. }
  384. }
  385. public bool TopMost {
  386. get {
  387. return (flags & Flags.TopMost) != 0;
  388. }
  389. set {
  390. if (TopMost == value)
  391. return;
  392. if (value)
  393. flags &= ~Flags.TopMost;
  394. else
  395. flags |= Flags.TopMost;
  396. XplatUI.SetTopmost(window.Handle, owner != null ? owner.window.Handle : IntPtr.Zero, TopMost);
  397. }
  398. }
  399. #endregion // Public Instance Properties
  400. #region Protected Instance Properties
  401. [MonoTODO("Need to add MDI support")]
  402. protected override CreateParams CreateParams {
  403. get {
  404. CreateParams cp = new CreateParams();
  405. if (this.form_parent_window == null) {
  406. form_parent_window = new FormParentWindow(this);
  407. }
  408. cp.Caption = "ClientArea";
  409. cp.ClassName=XplatUI.DefaultClassName;
  410. cp.ClassStyle = 0;
  411. cp.ExStyle=0;
  412. cp.Param=0;
  413. cp.Parent = this.form_parent_window.window.Handle;
  414. cp.X = Left;
  415. cp.Y = Top;
  416. cp.Width = Width;
  417. cp.Height = Height;
  418. cp.Style = (int)WindowStyles.WS_CHILD;
  419. cp.Style |= (int)WindowStyles.WS_VISIBLE;
  420. cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS;
  421. cp.Style |= (int)WindowStyles.WS_CLIPCHILDREN;
  422. if (ShowInTaskbar)
  423. cp.ExStyle |= (int)WindowStyles.WS_EX_APPWINDOW;
  424. if (MaximizeBox)
  425. cp.Style |= (int)WindowStyles.WS_MAXIMIZEBOX;
  426. if (MinimizeBox)
  427. cp.Style |= (int)WindowStyles.WS_MINIMIZEBOX;
  428. return cp;
  429. }
  430. }
  431. protected override Size DefaultSize {
  432. get {
  433. return new Size (250, 250);
  434. }
  435. }
  436. protected override void OnPaint (PaintEventArgs pevent)
  437. {
  438. base.OnPaint (pevent);
  439. }
  440. #endregion // Protected Instance Properties
  441. #region Public Static Methods
  442. #endregion // Public Static Methods
  443. #region Public Instance Methods
  444. public void AddOwnedForm(Form ownedForm) {
  445. owned_forms.Add(ownedForm);
  446. }
  447. public void RemoveOwnedForm(Form ownedForm) {
  448. owned_forms.Remove(ownedForm);
  449. }
  450. public DialogResult ShowDialog() {
  451. return ShowDialog(null);
  452. }
  453. public DialogResult ShowDialog(IWin32Window ownerWin32) {
  454. Control owner = null;
  455. if (ownerWin32 != null) {
  456. owner = Control.FromHandle(ownerWin32.Handle);
  457. }
  458. if (is_modal) {
  459. return DialogResult.None;
  460. }
  461. if (Visible) {
  462. throw new InvalidOperationException("Already visible forms cannot be displayed as a modal dialog. Set the Visible property to 'false' prior to calling Form.ShowDialog.");
  463. }
  464. if (!IsHandleCreated) {
  465. CreateControl();
  466. }
  467. XplatUI.SetModal(window.Handle, true);
  468. Show();
  469. is_modal = true;
  470. Application.ModalRun(this);
  471. is_modal = false;
  472. Hide();
  473. XplatUI.SetModal(window.Handle, false);
  474. return DialogResult;
  475. }
  476. public void Close ()
  477. {
  478. CancelEventArgs args = new CancelEventArgs ();
  479. OnClosing (args);
  480. if (!args.Cancel) {
  481. OnClosed (EventArgs.Empty);
  482. closing = true;
  483. return;
  484. }
  485. }
  486. #endregion // Public Instance Methods
  487. #region Protected Instance Methods
  488. protected override void CreateHandle() {
  489. base.CreateHandle ();
  490. }
  491. protected override void OnCreateControl() {
  492. base.OnCreateControl ();
  493. OnLoad(EventArgs.Empty);
  494. }
  495. protected override void OnHandleCreated(EventArgs e) {
  496. base.OnHandleCreated (e);
  497. }
  498. protected override void OnHandleDestroyed(EventArgs e) {
  499. base.OnHandleDestroyed (e);
  500. }
  501. protected override void OnResize(EventArgs e) {
  502. base.OnResize(e);
  503. }
  504. protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
  505. if (base.ProcessCmdKey (ref msg, keyData)) {
  506. return true;
  507. }
  508. // Give our menu a shot
  509. if (menu != null) {
  510. return menu.ProcessCmdKey(ref msg, keyData);
  511. }
  512. return false;
  513. }
  514. protected override bool ProcessDialogKey(Keys keyData) {
  515. if (keyData == Keys.Enter && accept_button != null) {
  516. accept_button.PerformClick();
  517. return true;
  518. } else if (keyData == Keys.Enter && cancel_button != null) {
  519. cancel_button.PerformClick();
  520. return true;
  521. }
  522. return base.ProcessDialogKey(keyData);
  523. }
  524. protected override bool ProcessKeyPreview(ref Message msg) {
  525. if (key_preview) {
  526. if (ProcessKeyEventArgs(ref msg)) {
  527. return true;
  528. }
  529. }
  530. return base.ProcessKeyPreview (ref msg);
  531. }
  532. protected override void WndProc(ref Message m) {
  533. switch((Msg)m.Msg) {
  534. case Msg.WM_CLOSE: {
  535. CancelEventArgs args = new CancelEventArgs();
  536. OnClosing(args);
  537. if (!args.Cancel) {
  538. OnClosed(EventArgs.Empty);
  539. closing = true;
  540. base.WndProc(ref m);
  541. break;
  542. }
  543. break;
  544. }
  545. #if topmost_workaround
  546. case Msg.WM_ACTIVATE: {
  547. if (this.OwnedForms.Length>0) {
  548. XplatUI.SetZOrder(this.OwnedForms[0].window.Handle, this.window.Handle, false, false);
  549. }
  550. break;
  551. }
  552. #endif
  553. default: {
  554. base.WndProc (ref m);
  555. break;
  556. }
  557. }
  558. }
  559. #endregion // Protected Instance Methods
  560. #region Events
  561. protected virtual void OnActivated(EventArgs e) {
  562. if (Activated != null) {
  563. Activated(this, e);
  564. }
  565. }
  566. protected virtual void OnClosed(EventArgs e) {
  567. if (Closed != null) {
  568. Closed(this, e);
  569. }
  570. }
  571. protected virtual void OnClosing(System.ComponentModel.CancelEventArgs e) {
  572. if (Closing != null) {
  573. Closing(this, e);
  574. }
  575. }
  576. protected virtual void OnDeactivate(EventArgs e) {
  577. if (Deactivate != null) {
  578. Deactivate(this, e);
  579. }
  580. }
  581. protected virtual void OnInputLanguageChanged(InputLanguageChangedEventArgs e) {
  582. if (InputLanguageChanged!=null) {
  583. InputLanguageChanged(this, e);
  584. }
  585. }
  586. protected virtual void OnInputLanguageChanging(InputLanguageChangingEventArgs e) {
  587. if (InputLanguageChanging!=null) {
  588. InputLanguageChanging(this, e);
  589. }
  590. }
  591. protected virtual void OnLoad(EventArgs e) {
  592. if (Load != null) {
  593. Load(this, e);
  594. }
  595. }
  596. protected virtual void OnMaximizedBoundsChanged(EventArgs e) {
  597. if (MaximizedBoundsChanged != null) {
  598. MaximizedBoundsChanged(this, e);
  599. }
  600. }
  601. protected virtual void OnMaximumSizeChanged(EventArgs e) {
  602. if (MaximumSizeChanged != null) {
  603. MaximumSizeChanged(this, e);
  604. }
  605. }
  606. protected virtual void OnMdiChildActivate(EventArgs e) {
  607. if (MdiChildActivate != null) {
  608. MdiChildActivate(this, e);
  609. }
  610. }
  611. protected virtual void OnMenuComplete(EventArgs e) {
  612. if (MenuComplete != null) {
  613. MenuComplete(this, e);
  614. }
  615. }
  616. protected virtual void OnMenuStart(EventArgs e) {
  617. if (MenuStart != null) {
  618. MenuStart(this, e);
  619. }
  620. }
  621. protected virtual void OnMinimumSizeChanged(EventArgs e) {
  622. if (MinimumSizeChanged != null) {
  623. MinimumSizeChanged(this, e);
  624. }
  625. }
  626. public event EventHandler Activated;
  627. public event EventHandler Closed;
  628. public event CancelEventHandler Closing;
  629. public event EventHandler Deactivate;
  630. public event InputLanguageChangedEventHandler InputLanguageChanged;
  631. public event InputLanguageChangingEventHandler InputLanguageChanging;
  632. public event EventHandler Load;
  633. public event EventHandler MaximizedBoundsChanged;
  634. public event EventHandler MaximumSizeChanged;
  635. public event EventHandler MdiChildActivate;
  636. public event EventHandler MenuComplete;
  637. public event EventHandler MenuStart;
  638. public event EventHandler MinimumSizeChanged;
  639. #endregion // Events
  640. }
  641. }