程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> .net2.0+ Winform項目完成彈出容器層

.net2.0+ Winform項目完成彈出容器層

編輯:C#入門知識

.net2.0+ Winform項目完成彈出容器層。本站提示廣大學習愛好者:(.net2.0+ Winform項目完成彈出容器層)文章只能為提供參考,不一定能成為您想要的結果。以下是.net2.0+ Winform項目完成彈出容器層正文


實用於:.net2.0+ Winform項目

配景:

有時刻我們須要開一個簡略的窗口來做一些事,例如輸出一些器械、點選一個item之類的,能夠像如許:

完了前往原窗體並獲得方才的輸出,如許做並沒有甚麼成績,但在幾天前我忽然發生了一些設法主意:為何非得有聲有色的彈出一個窗體給用戶呢,是否是可以在按鈕鄰近敏捷出現一個層來做這些事呢,相似快捷菜單那樣,用戶愉快就在外面做一下該做的事,不愉快就在其它處所點一下它就消逝,原來很簡便快捷的操作,DUANG~彈出一個窗體來會不會令用戶心裡格登一下呢,感觸感染層面的工作常常是很奧妙的,不論如何,我既然起了這個動機,just try it。

我起首找了一下現成的計劃,果真在牛逼的codeproject.com曾經有牛人做了如許的工作:

http://www.codeproject.com/Articles/17502/Simple-Popup-Control

簡略體驗了一下,切實其實是了不得的發明。道理是應用ToolStripControlHost可以承載自界說控件的這一才能,讓下拉式控件ToolStripDropDown將任何自界說控件像右鍵菜單那樣彈出來(別忘了右鍵菜單ContextMenuStrip就是繼續自ToolStripDropDown),如許就等於把菜單作為一個容器,可以彈出任何或簡略或龐雜的控件組合,同時又具有菜單具有的便捷性,召之即來揮之即去。其時懂得到這計劃的時刻真挺高興,恰是我想要的後果,感到這下好了,不消瞎費力本身造了。

但很快發明一個在我看來還挺在乎的缺乏,就是ToolStripDropDown只要Show,沒有ShowDialog,就是不克不及以形式化(Modal,也有叫模態的,鑒於MSDN都稱形式,我也隨流叫它形式)的方法彈出,這是由ToolStripDropDown的固有才能決議的,該計劃既然基於ToolStripDropDown,天然也受限於此,不克不及形式化彈出。如許帶來的成績是某些情形下的挪用體驗欠好(體驗這類事固然不是用戶才有的專利,俺們碼農也是人,也要講體驗的說),好比彈出的控件是讓用戶輸出一些器械,完了用戶點擊某個按鈕甚麼的前往原窗體,然後在原窗體獲得用戶方才的輸出,然後接著做前面的事。因為非形式的Show不會壅塞代碼,所以就不克不及在Show的下方想固然的獲得值、應用值~這是明顯的。要想取得值能夠就得額定采用一些做法,例如呼應彈出控件的封閉事宜,或許把原窗體傳入彈出控件完了在後者中做本來應當在原窗體中做的事~等等,方法固然有許多,但這都是由於只能Show帶來的過剩的事,有甚麼比在一個辦法中彈出控件、期待前往、持續處置來的爽滑的呢,像如許不是很天然嗎:

string s;using (Popup p = new Popup()){ if (p.ShowDialog() != DialogResult.OK) { return; } s = p.InputText;}//go on...

所以很遺憾,不能不揮別這個優良的計劃,造本身的輪子。不外受該計劃的啟示,我想到用ContextMenu來做容器(留意這個菜單類跟下面提到的繼續自ToolStripDropDown的ContextMenuStrip年夜年夜的分歧,前者是OS原生的菜單,就是在桌面、圖標和文本框中右鍵彈出的那種菜單,.net是經由過程調API的方法來操作如許的菜單,爾後者則完整是.net完成,更多信息請參考MSDN,此處不睜開),由於ContextMenu的Show是壅塞式的,正合我意。但一番測驗考試以後廢棄,它的菜單項MenuItem不像ToolStripItem那樣可以經由過程ToolStripControlHost承載自界說控件,願望是我才能無限,總之我做不到把自界說控件弄到ContextMenu上,也沒見過原生菜單上湧現過文本框、復選框等奇異的器械,假如您曉得怎樣擴大原生菜單,還望不惜賜教,先行謝過!

我照樣打回.net的主張,傍邊依然是做了很多分歧的測驗考試,Form、Panel、UserControl、ContainerControl、Control等等看起來合適做容器層的器械都試了個遍,乃至從新在ToolStripDropDown上打主張,最初選用Form,改革一番,自我感到較幻想的完成了我要的器械:一個叫做FloatLayerBase的基類,它自己繼續自System.Windows.Forms.Form類,而須要作為浮動層顯示的運用則繼續自FloatLayerBase停止完成,例以下面這個接收用戶輸出數值的NumInputDemo完成:

模樣和特色:不會令父窗口掉去核心(不會搶核心的層才是好層):

固然,漢子不止一面:

還有其它邊框款式,有待用戶自行體驗,最初有demo供給。

可以有調劑尺寸的手柄:

可以點住客戶區拖動:

其余一些運用:

這些都只是demo,沒那末悅目和壯大,重點是有了這個FloatLayerBase,便可以完成本身的浮動運用。

應用解釋:確保FloatLayerBase類在項目中~空話。源碼在此:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace AhDung.WinForm.Controls
{
  /// <summary>
  /// 浮動層基類
  /// </summary>
  public class FloatLayerBase : Form
  {
    /// <summary>
    /// 鼠標新聞挑選器
    /// </summary>
    //因為本窗體為WS_CHILD,所以不會收到在窗體之外點擊鼠標的新聞
    //該新聞挑選器的感化就是讓本窗體獲知鼠標點擊情形,進而依據鼠標能否在本窗體之外的區域點擊,做出響應處置
    readonly AppMouseMessageHandler _mouseMsgFilter;

    /// <summary>
    /// 指導本窗體能否已ShowDialog過
    /// </summary>
    //因為屢次ShowDialog會使OnLoad/OnShown重入,故需設置此標志以供重入時斷定
    bool _isShowDialogAgain;

    //邊框相干字段
    BorderStyle _borderType;
    Border3DStyle _border3DStyle;
    ButtonBorderStyle _borderSingleStyle;
    Color _borderColor;

    /// <summary>
    /// 獲得或設置邊框類型
    /// </summary>
    [Description("獲得或設置邊框類型。")]
    [DefaultValue(BorderStyle.Fixed3D)]
    public BorderStyle BorderType
    {
      get { return _borderType; }
      set
      {
        if (_borderType == value) { return; }
        _borderType = value;
        Invalidate();
      }
    }

    /// <summary>
    /// 獲得或設置三維邊框款式
    /// </summary>
    [Description("獲得或設置三維邊框款式。")]
    [DefaultValue(Border3DStyle.RaisedInner)]
    public Border3DStyle Border3DStyle
    {
      get { return _border3DStyle; }
      set
      {
        if (_border3DStyle == value) { return; }
        _border3DStyle = value;
        Invalidate();
      }
    }

    /// <summary>
    /// 獲得或設置線型邊框款式
    /// </summary>
    [Description("獲得或設置線型邊框款式。")]
    [DefaultValue(ButtonBorderStyle.Solid)]
    public ButtonBorderStyle BorderSingleStyle
    {
      get { return _borderSingleStyle; }
      set
      {
        if (_borderSingleStyle == value) { return; }
        _borderSingleStyle = value;
        Invalidate();
      }
    }

    /// <summary>
    /// 獲得或設置邊框色彩(僅當邊框類型為線型時有用)
    /// </summary>
    [Description("獲得或設置邊框色彩(僅當邊框類型為線型時有用)。")]
    [DefaultValue(typeof(Color), "DarkGray")]
    public Color BorderColor
    {
      get { return _borderColor; }
      set
      {
        if (_borderColor == value) { return; }
        _borderColor = value;
        Invalidate();
      }
    }

    protected override sealed CreateParams CreateParams
    {
      get
      {
        CreateParams prms = base.CreateParams;

        //prms.Style = 0;
        //prms.Style |= -2147483648;  //WS_POPUP
        prms.Style |= 0x40000000;   //WS_CHILD 主要,只要CHILD窗體才不會搶父窗體核心
        prms.Style |= 0x4000000;    //WS_CLIPSIBLINGS
        prms.Style |= 0x10000;     //WS_TABSTOP
        prms.Style &= ~0x40000;    //WS_SIZEBOX    去除
        prms.Style &= ~0x800000;    //WS_BORDER    去除
        prms.Style &= ~0x400000;    //WS_DLGFRAME   去除
        //prms.Style &= ~0x20000;   //WS_MINIMIZEBOX  去除
        //prms.Style &= ~0x10000;   //WS_MAXIMIZEBOX  去除

        prms.ExStyle = 0;
        //prms.ExStyle |= 0x1;     //WS_EX_DLGMODALFRAME 平面邊框
        //prms.ExStyle |= 0x8;     //WS_EX_TOPMOST
        prms.ExStyle |= 0x10000;    //WS_EX_CONTROLPARENT
        //prms.ExStyle |= 0x80;    //WS_EX_TOOLWINDOW
        //prms.ExStyle |= 0x100;    //WS_EX_WINDOWEDGE
        //prms.ExStyle |= 0x8000000;  //WS_EX_NOACTIVATE
        //prms.ExStyle |= 0x4;     //WS_EX_NOPARENTNOTIFY

        return prms;
      }
    }

    //結構函數
    public FloatLayerBase()
    {
      //初始化新聞挑選器。添加和移除在顯示/隱蔽時擔任
      _mouseMsgFilter = new AppMouseMessageHandler(this);

      //初始化基類屬性
      InitBaseProperties();

      //初始化邊框相干
      _borderType = BorderStyle.Fixed3D;
      _border3DStyle = System.Windows.Forms.Border3DStyle.RaisedInner;
      _borderSingleStyle = ButtonBorderStyle.Solid;
      _borderColor = Color.DarkGray;
    }

    protected override void OnLoad(EventArgs e)
    {
      //避免重入
      if (_isShowDialogAgain) { return; }

      //需得減失落兩層邊框寬度,運轉時尺寸才與設計時完整符合,緣由不明
      //肯定與ControlBox、FormBorderStyle有關,但詳細接洽不明
      if (!DesignMode)
      {
        Size size = SystemInformation.FrameBorderSize;
        this.Size -= size + size;//弗成以用ClientSize,後者會依據窗口作風從新調劑Size
      }
      base.OnLoad(e);
    }

    protected override void OnShown(EventArgs e)
    {
      //避免重入
      if (_isShowDialogAgain) { return; }

      //在OnShown中為初次ShowDialog設標志
      if (Modal) { _isShowDialogAgain = true; }

      if (!DesignMode)
      {
        //激活首控件
        Control firstControl;
        if ((firstControl = GetNextControl(this, true)) != null)
        {
          firstControl.Focus();
        }
      }
      base.OnShown(e);
    }

    protected override void WndProc(ref Message m)
    {
      //當本窗體作為ShowDialog彈出時,在收到WM_SHOWWINDOW前,Owner會被Disable
      //故需在收到該新聞後立刻Enable它,否則Owner窗體和本窗體都將處於無呼應狀況
      if (m.Msg == 0x18 && m.WParam != IntPtr.Zero && m.LParam == IntPtr.Zero
        && Modal && Owner != null && !Owner.IsDisposed)
      {
        if (Owner.IsMdiChild)
        {
          //當Owner是MDI子窗體時,被Disable的是MDI主窗體
          //而且Parent也會指向MDI主窗體,故需改回為Owner,如許彈出窗體的Location才會絕對於Owner而非MDIParent
          NativeMethods.EnableWindow(Owner.MdiParent.Handle, true);
          NativeMethods.SetParent(this.Handle, Owner.Handle);//只能用API設置Parent,由於形式窗體是TopLevel,.Net謝絕為頂級窗體設置Parent
        }
        else
        {
          NativeMethods.EnableWindow(Owner.Handle, true);
        }
      }
      base.WndProc(ref m);
    }

    //畫邊框
    protected override void OnPaintBackground(PaintEventArgs e)
    {
      base.OnPaintBackground(e);

      if (_borderType == BorderStyle.Fixed3D)//繪制3D邊框
      {
        ControlPaint.DrawBorder3D(e.Graphics, ClientRectangle, Border3DStyle);
      }
      else if (_borderType == BorderStyle.FixedSingle)//繪制線型邊框
      {
        ControlPaint.DrawBorder(e.Graphics, ClientRectangle, BorderColor, BorderSingleStyle);
      }
    }

    //顯示後添加鼠標新聞挑選器以開端捕獲,隱蔽時則移除挑選器。之所以不放Dispose中是想盡早移除挑選器
    protected override void OnVisibleChanged(EventArgs e)
    {
      if (!DesignMode)
      {
        if (Visible) { Application.AddMessageFilter(_mouseMsgFilter); }
        else { Application.RemoveMessageFilter(_mouseMsgFilter); }
      }
      base.OnVisibleChanged(e);
    }

    //完成窗體客戶區拖動
    //在WndProc中完成這個較費事,所以放到這裡做
    protected override void OnMouseDown(MouseEventArgs e)
    {
      //讓鼠標點擊客戶區時到達與點擊題目欄一樣的後果,以此完成客戶區拖動
      NativeMethods.ReleaseCapture();
      NativeMethods.SendMessage(Handle, 0xA1/*WM_NCLBUTTONDOWN*/, (IntPtr)2/*CAPTION*/, IntPtr.Zero);

      base.OnMouseDown(e);
    }

    /// <summary>
    /// 顯示為形式窗體
    /// </summary>
    /// <param name="control">顯示在該控件下方</param>
    public DialogResult ShowDialog(Control control)
    {
      return ShowDialog(control, 0, control.Height);
    }

    /// <summary>
    /// 顯示為形式窗體
    /// </summary>
    /// <param name="control">觸發彈出窗體的控件</param>
    /// <param name="offsetX">絕對control程度偏移</param>
    /// <param name="offsetY">絕對control垂直偏移</param>
    public DialogResult ShowDialog(Control control, int offsetX, int offsetY)
    {
      return ShowDialog(control, new Point(offsetX, offsetY));
    }

    /// <summary>
    /// 顯示為形式窗體
    /// </summary>
    /// <param name="control">觸發彈出窗體的控件</param>
    /// <param name="offset">絕對control偏移</param>
    public DialogResult ShowDialog(Control control, Point offset)
    {
      return this.ShowDialogInternal(control, offset);
    }

    /// <summary>
    /// 顯示為形式窗體
    /// </summary>
    /// <param name="item">顯示在該對象欄項的下方</param>
    public DialogResult ShowDialog(ToolStripItem item)
    {
      return ShowDialog(item, 0, item.Height);
    }

    /// <summary>
    /// 顯示為形式窗體
    /// </summary>
    /// <param name="item">觸發彈出窗體的對象欄項</param>
    /// <param name="offsetX">絕對item程度偏移</param>
    /// <param name="offsetY">絕對item垂直偏移</param>
    public DialogResult ShowDialog(ToolStripItem item, int offsetX, int offsetY)
    {
      return ShowDialog(item, new Point(offsetX, offsetY));
    }

    /// <summary>
    /// 顯示為形式窗體
    /// </summary>
    /// <param name="item">觸發彈出窗體的對象欄項</param>
    /// <param name="offset">絕對item偏移</param>
    public DialogResult ShowDialog(ToolStripItem item, Point offset)
    {
      return this.ShowDialogInternal(item, offset);
    }

    /// <summary>
    /// 顯示窗體
    /// </summary>
    /// <param name="control">顯示在該控件下方</param>
    public void Show(Control control)
    {
      Show(control, 0, control.Height);
    }

    /// <summary>
    /// 顯示窗體
    /// </summary>
    /// <param name="control">觸發彈出窗體的控件</param>
    /// <param name="offsetX">絕對control程度偏移</param>
    /// <param name="offsetY">絕對control垂直偏移</param>
    public void Show(Control control, int offsetX, int offsetY)
    {
      Show(control, new Point(offsetX, offsetY));
    }

    /// <summary>
    /// 顯示窗體
    /// </summary>
    /// <param name="control">觸發彈出窗體的控件</param>
    /// <param name="offset">絕對control偏移</param>
    public void Show(Control control, Point offset)
    {
      this.ShowInternal(control, offset);
    }

    /// <summary>
    /// 顯示窗體
    /// </summary>
    /// <param name="item">顯示在該對象欄下方</param>
    public void Show(ToolStripItem item)
    {
      Show(item, 0, item.Height);
    }

    /// <summary>
    /// 顯示窗體
    /// </summary>
    /// <param name="item">觸發彈出窗體的對象欄項</param>
    /// <param name="offsetX">絕對item程度偏移</param>
    /// <param name="offsetY">絕對item垂直偏移</param>
    public void Show(ToolStripItem item, int offsetX, int offsetY)
    {
      Show(item, new Point(offsetX, offsetY));
    }

    /// <summary>
    /// 顯示窗體
    /// </summary>
    /// <param name="item">觸發彈出窗體的對象欄項</param>
    /// <param name="offset">絕對item偏移</param>
    public void Show(ToolStripItem item, Point offset)
    {
      this.ShowInternal(item, offset);
    }

    /// <summary>
    /// ShowDialog外部辦法
    /// </summary>
    private DialogResult ShowDialogInternal(Component controlOrItem, Point offset)
    {
      //疾速持續彈出本窗體將有能夠碰到還沒有Hide的情形下再次彈出,這會激發異常,故需做處置
      if (this.Visible) { return System.Windows.Forms.DialogResult.None; }

      this.SetLocationAndOwner(controlOrItem, offset);
      return base.ShowDialog();
    }

    /// <summary>
    /// Show外部辦法
    /// </summary>
    private void ShowInternal(Component controlOrItem, Point offset)
    {
      if (this.Visible) { return; }//緣由見ShowDialogInternal

      this.SetLocationAndOwner(controlOrItem, offset);
      base.Show();
    }

    /// <summary>
    /// 設置坐標及一切者
    /// </summary>
    /// <param name="controlOrItem">控件或對象欄項</param>
    /// <param name="offset">絕對偏移</param>
    private void SetLocationAndOwner(Component controlOrItem, Point offset)
    {
      Point pt = Point.Empty;

      if (controlOrItem is ToolStripItem)
      {
        ToolStripItem item = (ToolStripItem)controlOrItem;
        pt.Offset(item.Bounds.Location);
        controlOrItem = item.Owner;
      }

      Control c = (Control)controlOrItem;
      pt.Offset(GetControlLocationInForm(c));
      pt.Offset(offset);
      this.Location = pt;

      //設置Owner屬性與Show[Dialog](Owner)有分歧,當Owner是MDIChild時,後者會改Owner為MDIParent
      this.Owner = c.FindForm();
    }

    /// <summary>
    /// 獲得控件在窗體中的坐標
    /// </summary>
    private static Point GetControlLocationInForm(Control c)
    {
      Point pt = c.Location;
      while (!((c = c.Parent) is Form))
      {
        pt.Offset(c.Location);
      }
      return pt;
    }

    #region 屏障對本類影響嚴重的基類辦法和屬性

    /// <summary>
    /// 初始化部門基類屬性
    /// </summary>
    private void InitBaseProperties()
    {
      base.ControlBox = false;              //主要
      //必需得是SizableToolWindow能力支撐調劑年夜小的同時,不受SystemInformation.MinWindowTrackSize的限制
      base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
      base.Text = string.Empty;             //主要
      base.HelpButton = false;
      base.Icon = null;
      base.IsMdiContainer = false;
      base.MaximizeBox = false;
      base.MinimizeBox = false;
      base.ShowIcon = false;
      base.ShowInTaskbar = false;
      base.StartPosition = FormStartPosition.Manual;   //主要
      base.TopMost = false;
      base.WindowState = FormWindowState.Normal;
    }

    //屏障原辦法
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("請應用其余重載!", true)]
    public new DialogResult ShowDialog() { throw new NotImplementedException(); }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("請應用其余重載!", true)]
    public new DialogResult ShowDialog(IWin32Window owner) { throw new NotImplementedException(); }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("請應用其余重載!", true)]
    public new void Show() { throw new NotImplementedException(); }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("請應用其余重載!", true)]
    public new void Show(IWin32Window owner) { throw new NotImplementedException(); }

    //屏障原屬性
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool ControlBox { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("設置邊框請應用Border相干屬性!", true)]
    public new FormBorderStyle FormBorderStyle { get { return System.Windows.Forms.FormBorderStyle.SizableToolWindow; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public override sealed string Text { get { return string.Empty; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool HelpButton { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new Image Icon { get { return null; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool IsMdiContainer { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool MaximizeBox { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool MinimizeBox { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool ShowIcon { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool ShowInTaskbar { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new FormStartPosition StartPosition { get { return FormStartPosition.Manual; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new bool TopMost { get { return false; } set { } }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [Obsolete("禁用該屬性!", true)]
    public new FormWindowState WindowState { get { return FormWindowState.Normal; } set { } }

    #endregion

    /// <summary>
    /// 法式鼠標新聞挑選器
    /// </summary>
    private class AppMouseMessageHandler : IMessageFilter
    {
      readonly FloatLayerBase _layerForm;

      public AppMouseMessageHandler(FloatLayerBase layerForm)
      {
        _layerForm = layerForm;
      }

      public bool PreFilterMessage(ref Message m)
      {
        //假如在本窗體之外點擊鼠標,隱蔽本窗體
        //若想在點擊題目欄、轉動條等非客戶區也要讓本窗體消逝,撤消0xA1的正文便可
        //本例是依據坐標斷定,亦可以改成依據句柄,但要斟酌子孫控件
        //之所以用API而不消Form.DesktopBounds是由於後者弗成靠
        if ((m.Msg == 0x201/*|| m.Msg==0xA1*/)
          && _layerForm.Visible && !NativeMethods.GetWindowRect(_layerForm.Handle).Contains(MousePosition))
        {
          _layerForm.Hide();//之所以不Close是斟酌應當由挪用者擔任燒毀
        }

        return false;
      }
    }

    /// <summary>
    /// API封裝類
    /// </summary>
    private static class NativeMethods
    {
      [DllImport("user32.dll")]
      [return: MarshalAs(UnmanagedType.Bool)]
      public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);

      [DllImport("user32.dll", CharSet = CharSet.Auto)]
      public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

      [DllImport("user32.dll")]
      public static extern bool ReleaseCapture();

      [DllImport("user32.dll", SetLastError = true)]
      public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

      [DllImport("user32.dll", SetLastError = true)]
      private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

      [StructLayout(LayoutKind.Sequential)]
      private struct RECT
      {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public static explicit operator Rectangle(RECT rect)
        {
          return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
        }
      }

      public static Rectangle GetWindowRect(IntPtr hwnd)
      {
        RECT rect;
        GetWindowRect(hwnd, out rect);
        return (Rectangle)rect;
      }
    }
  }
}

新建繼續窗體,選擇繼續自FloatLayerBase類;也能夠新建通俗窗體,然後把基類由Form改成FloatLayerBase
在設計器和源碼中打造浮動運用
在須要的處所應用它。關於應用,先看一下FloatLayerBase的部門地下成員:

//屬性
public BorderStyle BorderType { get; set; }
public Border3DStyle Border3DStyle { get; set; }
public ButtonBorderStyle BorderSingleStyle { get; set; }
public Color BorderColor { get; set; }

//辦法
public void Show(Control control);
public void Show(Control control, Point offset);
public void Show(Control control, int offsetX, int offsetY);
public void Show(ToolStripItem item);
public void Show(ToolStripItem item, Point offset);
public void Show(ToolStripItem item, int offsetX, int offsetY);
public DialogResult ShowDialog(Control control);
public DialogResult ShowDialog(Control control, Point offset);
public DialogResult ShowDialog(Control control, int offsetX, int offsetY);
public DialogResult ShowDialog(ToolStripItem item);
public DialogResult ShowDialog(ToolStripItem item, Point offset);
public DialogResult ShowDialog(ToolStripItem item, int offsetX, int offsetY);

下面4個屬性都是跟邊框有關的,邊框總共有3種形狀,三維、線型、無,由BorderType指定;當為三維形狀時,由Border3DStyle指定詳細款式;為線型時,由BorderSingleStyle和BorderColor分離指定詳細線型和色彩。原Form.FormBorderStyle屬性已被屏障,不許可子類拜訪,還有若干原Form的屬性也已屏障,緣由都在源碼裡。別的,原Form.SizeGripStyle照舊應用,能否許可調劑浮動層年夜小就靠它了

辦法就說一下Show和ShowDialog,明顯分離是用來非形式化/形式化顯示浮動層的,二者在挪用角度的嚴重差別就是,前者不會壅塞代碼,後者則會,現實運用中依據情形選用。每一個辦法從參數又分Control和ToolStripItem兩類,都是代表從甚麼控件上彈出浮動層的意思,前者接收Button、TextBox等控件(不克不及傳入Form,效果會不高興),後者接收對象欄下面的項目,例如ToolStripButton、ToolStripTextBox之類的。重載可以指定絕對control或item的偏移地位,默許是在control/item的下方彈出浮動層。最初不管是Show照樣ShowDialog彈出來的浮動層,都可以像右鍵菜單那樣經由過程在其它處所點鼠標使之消逝,這裡須要解釋一下:

鼠標只會點在本法式內的窗體中時,讓浮動層消逝。點在法式外的窗口、桌面、義務欄這些則不會。為何要如許是由於要做到完整像右鍵菜單那樣對全局鼠標敏感,須要全局鉤子,這會增長代碼量(機能且不說,沒測過不妄語),並且我以為沒需要全局敏感浮動層消逝是挪用Hide辦法,所以關於形式化翻開的浮動層,會前往DialogResult.Cancel,這是.net對形式對話框的設計使然,形式對話框被Hide或Close時,就是前往Cancel。在此也提示一下挪用者,在應用形式對話框時,永久斟酌有前往Cancel這類情形,不限於本例,而是一切對話框

原Show()/Show(IWin32Window)和ShowDialog()/ShowDialog(IWin32Window)已被屏障,緣由見源碼。

其它:

編寫時代一向應用PopupFormBase作為類名,宣布最初時辰才改成如今的FloatLayerBase,所以demo中能夠另有根據原名起名的子類、辦法名等。

Demo下載:

http://pan.百度.com/s/1mgnGPGc

外面有個Tester供您體驗。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved