InternalWindowManager.cs :  » 2.6.4-mono-.net-core » System.Windows.Forms » System » Windows » Forms » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows.Forms 
System.Windows.Forms » System » Windows » Forms » InternalWindowManager.cs
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
//
// Authors:
//  Jackson Harper (jackson@ximian.com)
//
//


using System;
using System.Drawing;
using System.Runtime.InteropServices;


namespace System.Windows.Forms{

  internal abstract class InternalWindowManager {
    private TitleButtons title_buttons;
    internal Form form;

    // moving windows
    internal Point start;
    internal State state;
    protected Point clicked_point;
    private FormPos sizing_edge;
    internal Rectangle virtual_position;

    private Rectangle normal_bounds;
    private Rectangle iconic_bounds;
    

    public enum State {
      Idle,
      Moving,
      Sizing,
    }

    [Flags]
    public enum FormPos {
      None,

      TitleBar = 1,

      Top = 2,
      Left = 4,
      Right = 8,
      Bottom = 16,

      TopLeft = Top | Left,
      TopRight = Top | Right,

      BottomLeft = Bottom | Left,
      BottomRight = Bottom | Right,

      AnyEdge = Top | Left | Right | Bottom,
    }

    public InternalWindowManager (Form form)
    {
      this.form = form;

      form.SizeChanged += new EventHandler (FormSizeChangedHandler);

      title_buttons = new TitleButtons (form);
      ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
    }

    public Form Form {
      get { return form; }
    }
    
    public int IconWidth {
      get { return TitleBarHeight - 5; }
    }

    public TitleButtons TitleButtons {
      get {
        return title_buttons;
      }
    }
    internal Rectangle NormalBounds {
      get {
        return normal_bounds;
      }
      set {
        normal_bounds = value;
      }
    }
    internal Size IconicSize {
      get {
        return SystemInformation.MinimizedWindowSize;
      }
    }
    
    internal Rectangle IconicBounds {
      get {
        if (iconic_bounds == Rectangle.Empty)
          return Rectangle.Empty;
        Rectangle result = iconic_bounds;
        result.Y = Form.Parent.ClientRectangle.Bottom - iconic_bounds.Y;
        return result;
      }
      set {
        iconic_bounds = value;
        iconic_bounds.Y = Form.Parent.ClientRectangle.Bottom - iconic_bounds.Y;
      }
    }

    internal virtual Rectangle MaximizedBounds {
      get {
        return Form.Parent.ClientRectangle;
      }
    }
        
    public virtual void UpdateWindowState (FormWindowState old_window_state, FormWindowState new_window_state, bool force)
    {
      if (old_window_state == FormWindowState.Normal) {
        NormalBounds = form.Bounds;
      } else if (old_window_state == FormWindowState.Minimized) {
        IconicBounds = form.Bounds;
      }

      switch (new_window_state) {
      case FormWindowState.Minimized:
        if (IconicBounds == Rectangle.Empty) {
          Size size = IconicSize;
          Point location = new Point (0, Form.Parent.ClientSize.Height - size.Height);
          IconicBounds = new Rectangle (location, size);
        }
        form.Bounds = IconicBounds;
        break;
      case FormWindowState.Maximized:
        form.Bounds = MaximizedBounds;
        break;
      case FormWindowState.Normal:
        form.Bounds = NormalBounds;
        break;
      }

      UpdateWindowDecorations (new_window_state);
      form.ResetCursor ();
    }
    
    public virtual void UpdateWindowDecorations (FormWindowState window_state)
    {
      ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
      if (form.IsHandleCreated)
        XplatUI.RequestNCRecalc (form.Handle);
    }
    
    public virtual bool WndProc (ref Message m)
    {
#if debug
      Console.WriteLine(DateTime.Now.ToLongTimeString () + " " + this.GetType () .Name + " (Handle={0},Text={1}) received message {2}", form.IsHandleCreated ? form.Handle : IntPtr.Zero,  form.Text, m.ToString ());
#endif

      switch ((Msg)m.Msg) {


        // The mouse handling messages are actually
        // not WM_NC* messages except for the first button and NCMOVEs
        // down because we capture on the form

      case Msg.WM_MOUSEMOVE:
        return HandleMouseMove (form, ref m);

      case Msg.WM_LBUTTONUP:
        HandleLButtonUp (ref m);
        break;

      case Msg.WM_RBUTTONDOWN:
        return HandleRButtonDown (ref m);
        
      case Msg.WM_LBUTTONDOWN:
        return HandleLButtonDown (ref m);
        
      case Msg.WM_LBUTTONDBLCLK:
        return HandleLButtonDblClick (ref m);
        
      case Msg.WM_PARENTNOTIFY:
        if (Control.LowOrder(m.WParam.ToInt32()) == (int) Msg.WM_LBUTTONDOWN) 
          Activate ();
        break;

      case Msg.WM_NCHITTEST: 
        return HandleNCHitTest (ref m);

        // Return true from these guys, otherwise win32 will mess up z-order
      case Msg.WM_NCLBUTTONUP:
        HandleNCLButtonUp (ref m);
        return true;

      case Msg.WM_NCLBUTTONDOWN:
        HandleNCLButtonDown (ref m);
        return true;

      case Msg.WM_NCMOUSEMOVE:
        HandleNCMouseMove (ref m);
        return true;
        
      case Msg.WM_NCLBUTTONDBLCLK:
        HandleNCLButtonDblClick (ref m);
        break;

      case Msg.WM_NCMOUSELEAVE:
        HandleNCMouseLeave (ref m);
        break;
      
      case Msg.WM_MOUSELEAVE:
        HandleMouseLeave (ref m);
        break;

      case Msg.WM_NCCALCSIZE:
        return HandleNCCalcSize (ref m);

      case Msg.WM_NCPAINT:
        return HandleNCPaint (ref m);
      }

      return false;
    }

    protected virtual bool HandleNCPaint (ref Message m)
    {
      PaintEventArgs pe = XplatUI.PaintEventStart (ref m, form.Handle, false);

      Rectangle clip;
      
      if (form.ActiveMenu != null) {
        Point pnt;

        pnt = GetMenuOrigin ();

        // The entire menu has to be in the clip rectangle because the 
        // control buttons are right-aligned and otherwise they would
        // stay painted when the window gets resized.
        clip = new Rectangle (pnt.X, pnt.Y, form.ClientSize.Width, 0);
        clip = Rectangle.Union (clip, pe.ClipRectangle);
        pe.SetClip (clip);
        pe.Graphics.SetClip (clip);

        form.ActiveMenu.Draw (pe, new Rectangle (pnt.X, pnt.Y, form.ClientSize.Width, 0));
      }
      if (HasBorders || IsMinimized && !(Form.IsMdiChild && IsMaximized)) {
        // clip region is not correct on win32.
        // use the entire form's area.
        clip = new Rectangle (0, 0, form.Width, form.Height);
        ThemeEngine.Current.DrawManagedWindowDecorations (pe.Graphics, clip, this);
      }
      XplatUI.PaintEventEnd (ref m, form.Handle, false);
      return true;
    }

    protected virtual bool HandleNCCalcSize (ref Message m)
    {
      XplatUIWin32.NCCALCSIZE_PARAMS ncp;
      XplatUIWin32.RECT rect;

      if (m.WParam == (IntPtr)1) {
        ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (m.LParam,
            typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
        
        ncp.rgrc1 = NCCalcSize (ncp.rgrc1);

        Marshal.StructureToPtr (ncp, m.LParam, true);
      } else {
        rect = (XplatUIWin32.RECT) Marshal.PtrToStructure (m.LParam, typeof (XplatUIWin32.RECT));
        
        rect = NCCalcSize (rect);
        
        Marshal.StructureToPtr (rect, m.LParam, true);
      }
      
      return true;
    }

    protected virtual XplatUIWin32.RECT NCCalcSize (XplatUIWin32.RECT proposed_window_rect)
    {
      int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);

      if (HasBorders) {
        proposed_window_rect.top += TitleBarHeight + bw;
        proposed_window_rect.bottom -= bw;
        proposed_window_rect.left += bw;
        proposed_window_rect.right -= bw;
      }

      if (XplatUI.RequiresPositiveClientAreaSize) {
        // This is necessary for Linux, can't handle <= 0-sized 
        // client areas correctly.
        if (proposed_window_rect.right <= proposed_window_rect.left) {
          proposed_window_rect.right += proposed_window_rect.left - proposed_window_rect.right + 1;
        }
        if (proposed_window_rect.top >= proposed_window_rect.bottom) {
          proposed_window_rect.bottom += proposed_window_rect.top - proposed_window_rect.bottom + 1;
        }
      }

      return proposed_window_rect;
    }

    protected virtual bool HandleNCHitTest (ref Message m)
    {

      int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
      int y = Control.HighOrder ((int)m.LParam.ToInt32 ());

      NCPointToClient (ref x, ref y);

      FormPos pos = FormPosForCoords (x, y);

      if (pos == FormPos.TitleBar) {
        m.Result = new IntPtr ((int)HitTest.HTCAPTION);
        return true;
      }

      if (!IsSizable)
        return false;

      switch (pos) {
      case FormPos.Top:
        m.Result = new IntPtr ((int)HitTest.HTTOP);
        break;
      case FormPos.Left:
        m.Result = new IntPtr ((int)HitTest.HTLEFT);
        break;
      case FormPos.Right:
        m.Result = new IntPtr ((int)HitTest.HTRIGHT);
        break;
      case FormPos.Bottom:
        m.Result = new IntPtr ((int)HitTest.HTBOTTOM);
        break;
      case FormPos.TopLeft:
        m.Result = new IntPtr ((int)HitTest.HTTOPLEFT);
        break;
      case FormPos.TopRight:
        m.Result = new IntPtr ((int)HitTest.HTTOPRIGHT);
        break;
      case FormPos.BottomLeft:
        m.Result = new IntPtr ((int)HitTest.HTBOTTOMLEFT);
        break;
      case FormPos.BottomRight:
        m.Result = new IntPtr ((int)HitTest.HTBOTTOMRIGHT);
        break;
      default:
        // We return false so that DefWndProc handles things
        return false;
      }
      return true;
    }

    public virtual void UpdateBorderStyle (FormBorderStyle border_style)
    {
      if (form.IsHandleCreated) {
        XplatUI.SetBorderStyle (form.Handle, border_style);
      }

      if (ShouldRemoveWindowManager (border_style)) {
        form.RemoveWindowManager ();
        return;
      }
        
      ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
    }

    
    
    public virtual void SetWindowState (FormWindowState old_state, FormWindowState window_state)
    {
      UpdateWindowState (old_state, window_state, false);
    }

    public virtual FormWindowState GetWindowState ()
    {
      return form.window_state;
    }

    public virtual void PointToClient (ref int x, ref int y)
    {
      // toolwindows stay in screencoords we just have to make sure
      // they obey the working area
      Rectangle working = SystemInformation.WorkingArea;

      if (x > working.Right)
        x = working.Right;
      if (x < working.Left)
        x = working.Left;

      if (y < working.Top)
        y = working.Top;
      if (y > working.Bottom)
        y = working.Bottom;
    }

    public virtual void PointToScreen (ref int x, ref int y)
    {
      XplatUI.ClientToScreen (form.Handle, ref x, ref y);
    }

    protected virtual bool ShouldRemoveWindowManager (FormBorderStyle style)
    {
      return style != FormBorderStyle.FixedToolWindow && style != FormBorderStyle.SizableToolWindow;
    }

    public bool IconRectangleContains (int x, int y)
    {
      if (!ShowIcon)
        return false;

      Rectangle icon = ThemeEngine.Current.ManagedWindowGetTitleBarIconArea (this);
      return icon.Contains (x, y);
    }

    public bool ShowIcon {
      get {
#if NET_2_0
        if (!Form.ShowIcon)
          return false;
#endif
        if (!HasBorders)
          return false;
        if (IsMinimized)
          return true;
        if (IsToolWindow || Form.FormBorderStyle == FormBorderStyle.FixedDialog)
          return false;
        return true;
      }
    }

    protected virtual void Activate ()
    {
      form.Invalidate (true);
      form.Update ();
    }

    public virtual bool IsActive {
      get {
        return true;
      }
    }


    private void FormSizeChangedHandler (object sender, EventArgs e)
    {
      if (form.IsHandleCreated) {
        ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
        XplatUI.InvalidateNC (form.Handle);
      }
    }

    protected virtual bool HandleRButtonDown (ref Message m)
    {
      Activate ();
      return false;
    }
    
    protected virtual bool HandleLButtonDown (ref Message m)
    {
      Activate ();
      return false;
    }

    protected virtual bool HandleLButtonDblClick(ref Message m)
    {
      return false;
    }
    
    protected virtual bool HandleNCMouseLeave (ref Message m)
    {
      int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
      int y = Control.HighOrder ((int)m.LParam.ToInt32 ());

      NCPointToClient (ref x, ref y);
      FormPos pos = FormPosForCoords (x, y);

      if (pos != FormPos.TitleBar) {
        HandleTitleBarLeave (x, y);
        return true;
      }

      return true;
    }
    
    protected virtual bool HandleNCMouseMove (ref Message m)
    {
      int x = Control.LowOrder((int)m.LParam.ToInt32( ));
      int y = Control.HighOrder((int)m.LParam.ToInt32( ));

      NCPointToClient (ref x, ref y);
      FormPos pos = FormPosForCoords (x, y);

      if (pos == FormPos.TitleBar) {
        HandleTitleBarMouseMove (x, y);
        return true;
      }

      if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
        MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y, 0);
        form.ActiveMenu.OnMouseMove (form, mea);
      }

      return true;
      
    }
    
    protected virtual bool HandleNCLButtonDown (ref Message m)
    {
      Activate ();

      start = Cursor.Position;
      virtual_position = form.Bounds;
      
      int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
      int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
      
      // Need to adjust because we are in NC land
      NCPointToClient (ref x, ref y);
      FormPos pos = FormPosForCoords (x, y);
      
      if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
        MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y - TitleBarHeight, 0);
        form.ActiveMenu.OnMouseDown (form, mea);
      }
      
      if (pos == FormPos.TitleBar) {
        HandleTitleBarDown (x, y);
        return true;
      }

      if (IsSizable) {
        if ((pos & FormPos.AnyEdge) == 0)
          return false;

        virtual_position = form.Bounds;
        state = State.Sizing;
        sizing_edge = pos;
        form.Capture = true;
        return true;
      }

      return false;
    }

    protected virtual void HandleNCLButtonDblClick (ref Message m)
    {
      int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
      int y = Control.HighOrder ((int)m.LParam.ToInt32 ());

      // Need to adjust because we are in NC land
      NCPointToClient (ref x, ref y);

      FormPos pos = FormPosForCoords (x, y);
      if (pos == FormPos.TitleBar || pos == FormPos.Top)
        HandleTitleBarDoubleClick (x, y);

    }
    
    protected virtual void HandleTitleBarDoubleClick (int x, int y)
    {
    
    }
    
    protected virtual void HandleTitleBarLeave (int x, int y)
    {
      title_buttons.MouseLeave (x, y);
    }
    
    protected virtual void HandleTitleBarMouseMove (int x, int y)
    {
      if (title_buttons.MouseMove (x, y))
        XplatUI.InvalidateNC (form.Handle);
    }
    
    protected virtual void HandleTitleBarUp (int x, int y)
    {
      title_buttons.MouseUp (x, y);

      return;
    }
    
    protected virtual void HandleTitleBarDown (int x, int y)
    {
      title_buttons.MouseDown (x, y);

      if (!TitleButtons.AnyPushedTitleButtons && !IsMaximized) {
        state = State.Moving;
        clicked_point = new Point (x, y);
        if (form.Parent != null) {
          form.CaptureWithConfine (form.Parent);
        } else {
          form.Capture = true;
        }
      }
      
      XplatUI.InvalidateNC (form.Handle);
    }

    private bool HandleMouseMove (Form form, ref Message m)
    {
      switch (state) {
      case State.Moving:
        HandleWindowMove (m);
        return true;
      case State.Sizing:
        HandleSizing (m);
        return true;
      }
      
      return false;
    }

    private void HandleMouseLeave (ref Message m)
    {
      form.ResetCursor ();
    }
  
    protected virtual void HandleWindowMove (Message m)
    {
      Point move = MouseMove (Cursor.Position);

      UpdateVP (virtual_position.X + move.X, virtual_position.Y + move.Y,
          virtual_position.Width, virtual_position.Height);
    }

    private void HandleSizing (Message m)
    {
      Rectangle pos = virtual_position;
      int mw;
      int mh;
      if (IsToolWindow) {
        int border_width = BorderWidth;
        mw = 2 * (border_width + Theme.ManagedWindowSpacingAfterLastTitleButton) + ThemeEngine.Current.ManagedWindowButtonSize (this).Width;
        mh = 2 * border_width + TitleBarHeight;
      } else {
        Size minimum_size = SystemInformation.MinWindowTrackSize;
        mw = minimum_size.Width;
        mh = minimum_size.Height;
      }
      int x = Cursor.Position.X;
      int y = Cursor.Position.Y;

      PointToClient (ref x, ref y);

      if ((sizing_edge & FormPos.Top) != 0) {
        if (pos.Bottom - y < mh)
          y = pos.Bottom - mh;
        pos.Height = pos.Bottom - y;
        pos.Y = y;
      } else if ((sizing_edge & FormPos.Bottom) != 0) {
        int height = y - pos.Top;
        if (height <= mh)
          height = mh;
        pos.Height = height;
      }

      if ((sizing_edge & FormPos.Left) != 0) {
        if (pos.Right - x < mw)
          x = pos.Right - mw;
        pos.Width = pos.Right - x;
        pos.X = x;
      } else if ((sizing_edge & FormPos.Right) != 0) {
        int width = x - form.Left;
        if (width <= mw)
          width = mw;
        pos.Width = width;
      }

      UpdateVP (pos);
    }

    public bool IsMaximized {
      get { return GetWindowState () == FormWindowState.Maximized; }
    }

    public bool IsMinimized {
      get { return GetWindowState () == FormWindowState.Minimized; }
    }

    public bool IsSizable {
      get {
        switch (form.FormBorderStyle) {
        case FormBorderStyle.Sizable:
        case FormBorderStyle.SizableToolWindow:
          return (form.window_state != FormWindowState.Minimized);
        default:
          return false;
        }
      }
    }

    public bool HasBorders {
      get {
        return form.FormBorderStyle != FormBorderStyle.None;
      }
    }

    public bool IsToolWindow {
      get {
        if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
            form.FormBorderStyle == FormBorderStyle.FixedToolWindow || 
            form.GetCreateParams().IsSet (WindowExStyles.WS_EX_TOOLWINDOW))
          return true;
        return false;
      }
    }

    public int TitleBarHeight {
      get {
        return ThemeEngine.Current.ManagedWindowTitleBarHeight (this);
      }
    }

    public int BorderWidth {
      get {
        return ThemeEngine.Current.ManagedWindowBorderWidth (this);
      }
    }
    
    public virtual int MenuHeight {
      get {
        return (form.Menu != null ? ThemeEngine.Current.MenuHeight : 0);
      }
    }

    protected void UpdateVP (Rectangle r)
    {
      UpdateVP (r.X, r.Y, r.Width, r.Height);
    }

    protected void UpdateVP (Point loc, int w, int h)
    {
      UpdateVP (loc.X, loc.Y, w, h);
    }

    protected void UpdateVP (int x, int y, int w, int h)
    {
      virtual_position.X = x;
      virtual_position.Y = y;
      virtual_position.Width = w;
      virtual_position.Height = h;

      DrawVirtualPosition (virtual_position);
    }

    protected virtual void HandleLButtonUp (ref Message m)
    {
      if (state == State.Idle)
        return;

      ClearVirtualPosition ();

      form.Capture = false;
      if (state == State.Moving && form.Location != virtual_position.Location) 
        form.Location = virtual_position.Location;
      else if (state == State.Sizing && form.Bounds != virtual_position)
        form.Bounds = virtual_position;
      state = State.Idle;

      OnWindowFinishedMoving ();
    }

    private bool HandleNCLButtonUp (ref Message m)
    {
      if (form.Capture) {
        ClearVirtualPosition ();

        form.Capture = false;
        state = State.Idle;
        if (form.MdiContainer != null)
          form.MdiContainer.SizeScrollBars();
      }
        
      int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
      int y = Control.HighOrder ((int) m.LParam.ToInt32 ());

      NCPointToClient (ref x, ref y);
      FormPos pos = FormPosForCoords (x, y);

      if (pos == FormPos.TitleBar) {
        HandleTitleBarUp (x, y);
        return true;
      }
      
      return true;
    }
    
    protected void DrawTitleButton (Graphics dc, TitleButton button, Rectangle clip)
    {
      if (!button.Rectangle.IntersectsWith (clip))
        return;

      ThemeEngine.Current.ManagedWindowDrawMenuButton (dc, button, clip, this);
    }

    public virtual void DrawMaximizedButtons (object sender, PaintEventArgs pe)
    {
    }

    protected Point MouseMove (Point pos)
    {
      return new Point (pos.X - start.X, pos.Y - start.Y);
    }

    protected virtual void DrawVirtualPosition (Rectangle virtual_position)
    {
      form.Bounds = virtual_position;
      start = Cursor.Position;
    }

    protected virtual void ClearVirtualPosition ()
    {
      
    }

    protected virtual void OnWindowFinishedMoving ()
    {
    }

    protected virtual void NCPointToClient(ref int x, ref int y) {
      form.PointToClient(ref x, ref y);
      NCClientToNC (ref x, ref y);
    }

    protected virtual void NCClientToNC (ref int x, ref int y) {
      y += TitleBarHeight;
      y += BorderWidth;
      y += MenuHeight;
    }
    
    internal Point GetMenuOrigin ()
    {
      return new Point (BorderWidth, BorderWidth + TitleBarHeight);
    }
    
    protected FormPos FormPosForCoords (int x, int y)
    {
      int bw = BorderWidth;
      if (y < TitleBarHeight + bw) {
        //  Console.WriteLine ("A");
        if (y > bw && x > bw &&
            x < form.Width - bw)
          return FormPos.TitleBar;

        if (x < bw || (x < 20 && y < bw))
          return FormPos.TopLeft;

        if (x > form.Width - bw ||
          (x > form.Width - 20 && y < bw))
          return FormPos.TopRight;

        if (y < bw)
          return FormPos.Top;

      } else if (y > form.Height - 20) {
        //  Console.WriteLine ("B");
        if (x < bw ||
            (x < 20 && y > form.Height - bw))
          return FormPos.BottomLeft;

        if (x > form.Width - (bw * 2) ||
            (x > form.Width - 20 &&
             y > form.Height - bw))
          return FormPos.BottomRight;

        if (y > form.Height - (bw * 2))
          return FormPos.Bottom;


      } else if (x < bw) {
        //  Console.WriteLine ("C");
        return FormPos.Left;
      } else if (x > form.Width - (bw * 2)) {
//        Console.WriteLine ("D");
        return FormPos.Right;
      } else {
        //      Console.WriteLine ("E   {0}", form.Width - bw);
      }
      
      return FormPos.None;
    }
  }
  internal class TitleButton
  {
    public Rectangle Rectangle;
    public ButtonState State;
    public CaptionButton Caption;
    private EventHandler Clicked;
    public bool Visible;
    bool entered;

    public TitleButton (CaptionButton caption, EventHandler clicked)
    {
      Caption = caption;
      Clicked = clicked;
    }
    
    public void OnClick ()
    {
      if (Clicked != null) {
        Clicked (this, EventArgs.Empty);
      }
    }

    public bool Entered {
      get { return entered; }
      set { entered = value; }
    }
  }

  internal class TitleButtons : System.Collections.IEnumerable
  {
    public TitleButton MinimizeButton;
    public TitleButton MaximizeButton;
    public TitleButton RestoreButton;
    public TitleButton CloseButton;
    public TitleButton HelpButton;

    public TitleButton [] AllButtons;
    public bool Visible;

    private ToolTip.ToolTipWindow tooltip;
    private Timer tooltip_timer;
    private TitleButton tooltip_hovered_button;
    private TitleButton tooltip_hidden_button;
    private const int tooltip_hide_interval = 3000;
    private const int tooltip_show_interval = 1000;
    private Form form;
    
    public TitleButtons (Form frm)
    {
      this.form = frm;
      this.Visible = true;
      
      MinimizeButton = new TitleButton (CaptionButton.Minimize, new EventHandler (ClickHandler));
      MaximizeButton = new TitleButton (CaptionButton.Maximize, new EventHandler (ClickHandler));
      RestoreButton = new TitleButton (CaptionButton.Restore, new EventHandler (ClickHandler));
      CloseButton = new TitleButton (CaptionButton.Close, new EventHandler (ClickHandler));
      HelpButton = new TitleButton (CaptionButton.Help, new EventHandler (ClickHandler));

      AllButtons = new TitleButton [] { MinimizeButton, MaximizeButton, RestoreButton, CloseButton, HelpButton };
    }
    
    private void ClickHandler (object sender, EventArgs e)
    {
      if (!Visible) {
        return;
      }
      
      TitleButton button = (TitleButton) sender;
      
      switch (button.Caption) {
        case CaptionButton.Close: 
          form.Close ();
          break;
        case CaptionButton.Help:
          Console.WriteLine ("Help not implemented.");
          break;
        case CaptionButton.Maximize:
          form.WindowState = FormWindowState.Maximized;
          break;
        case CaptionButton.Minimize:
          form.WindowState = FormWindowState.Minimized;
          break;
        case CaptionButton.Restore:
          form.WindowState = FormWindowState.Normal;
          break;
      }
    }
    
    public TitleButton FindButton (int x, int y)
    {
      if (!Visible) {
        return null;
      }
      
      foreach (TitleButton button in AllButtons) {
        if (button.Visible && button.Rectangle.Contains (x, y)) {
          return button;
        }
      }
      return null;
    }
    
    public bool AnyPushedTitleButtons {
      get {
        if (!Visible) {
          return false;
        }
        
        foreach (TitleButton button in AllButtons) {
          if (button.Visible && button.State == ButtonState.Pushed) {
            return true;
          }
        }
        return false;
      }
    }

    #region IEnumerable Members

    public System.Collections.IEnumerator GetEnumerator ()
    {
      return AllButtons.GetEnumerator ();
    }
    #endregion

    #region ToolTip helpers
    // Called from MouseMove if mouse is over a button
    public void ToolTipStart (TitleButton button)
    {
      tooltip_hovered_button = button;

      if (tooltip_hovered_button == tooltip_hidden_button)
        return;
      tooltip_hidden_button = null;

      if (tooltip != null && tooltip.Visible)
        ToolTipShow (true);

      if (tooltip_timer == null) {

        tooltip_timer = new Timer ();
        tooltip_timer.Tick += new EventHandler (ToolTipTimerTick);
      }

      tooltip_timer.Interval = tooltip_show_interval;
      tooltip_timer.Start ();
      tooltip_hovered_button = button;
    }

    public void ToolTipTimerTick (object sender, EventArgs e)
    {
      if (tooltip_timer.Interval == tooltip_hide_interval) {
        tooltip_hidden_button = tooltip_hovered_button;
        ToolTipHide (false);
      } else {
        ToolTipShow (false);
      }
    }
    // Called from timer (with only_refresh = false)
    // Called from ToolTipStart if tooltip is already shown (with only_refresh = true)
    public void ToolTipShow (bool only_refresh)
    {
      if (!form.Visible)
        return;

      string text = Locale.GetText (tooltip_hovered_button.Caption.ToString ());

      tooltip_timer.Interval = tooltip_hide_interval;
      tooltip_timer.Enabled = true;

      if (only_refresh && (tooltip == null || !tooltip.Visible)) {
        return;
      }

      if (tooltip == null)
        tooltip = new ToolTip.ToolTipWindow ();
      else if (tooltip.Text == text && tooltip.Visible)
        return;
      else if (tooltip.Visible)
        tooltip.Visible = false;

      if (form.WindowState == FormWindowState.Maximized && form.MdiParent != null)
        tooltip.Present (form.MdiParent, text);
      else
        tooltip.Present (form, text);
      
    }
    
    // Called from MouseLeave (with reset_hidden_button = true)
    // Called from MouseDown  (with reset_hidden_button = false)
    // Called from MouseMove if mouse isn't over any button (with reset_hidden_button = false)
    // Called from Timer if hiding (with reset_hidden_button = false)
    public void ToolTipHide (bool reset_hidden_button)
    {
      if (tooltip_timer != null)
        tooltip_timer.Enabled = false;
      if (tooltip != null && tooltip.Visible)
        tooltip.Visible = false;
      if (reset_hidden_button)
        tooltip_hidden_button = null;
    }
    #endregion
    
    public bool MouseMove (int x, int y)
    {
      if (!Visible) {
        return false;
      }

      bool any_change = false;
      bool any_pushed_buttons = AnyPushedTitleButtons;
      bool any_tooltip = false;
      TitleButton over_button = FindButton (x, y);

      foreach (TitleButton button in this) {
        if (button == null)
          continue;
        
        if (button.State == ButtonState.Inactive)
          continue;
          
        if (button == over_button) {
          if (any_pushed_buttons) {
            any_change |= button.State != ButtonState.Pushed;
            button.State = ButtonState.Pushed;
          }
          ToolTipStart (button);
          any_tooltip = true;
          if (!button.Entered) {
            button.Entered = true;
            if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
              any_change = true;
          }
        } else {
          if (any_pushed_buttons) {
            any_change |= button.State != ButtonState.Normal;
            button.State = ButtonState.Normal;
          }
          if (button.Entered) {
            button.Entered = false;
            if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
              any_change = true;
          }
        }
      }

      if (!any_tooltip)
        ToolTipHide (false);

      return any_change;
    }

    public void MouseDown (int x, int y)
    {
      if (!Visible) {
        return;
      }

      ToolTipHide (false);

      foreach (TitleButton button in this) {
        if (button != null && button.State != ButtonState.Inactive) {
          button.State = ButtonState.Normal;
        }
      }
      TitleButton clicked_button = FindButton (x, y);
      if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
        clicked_button.State = ButtonState.Pushed;
      }
    }

    public void MouseUp (int x, int y)
    {
      if (!Visible) {
        return;
      }
      
      TitleButton clicked_button = FindButton (x, y);
      if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
        clicked_button.OnClick ();
      }

      foreach (TitleButton button in this) {
        if (button == null || button.State == ButtonState.Inactive)
          continue;

        button.State = ButtonState.Normal;
      }

      if (clicked_button == CloseButton && !form.closing)
        XplatUI.InvalidateNC (form.Handle);
        
      ToolTipHide (true);
    }

    internal void MouseLeave (int x, int y)
    {
      if (!Visible) {
        return;
      }
      
      foreach (TitleButton button in this) {
        if (button == null || button.State == ButtonState.Inactive)
          continue;

        button.State = ButtonState.Normal;
      }
      
      ToolTipHide (true);
    }
  }
}


www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.