如何创建一个悬停的C#Winforms控件

时间:2022-09-02 12:36:03

How can you create a C# Winforms control which goes out of the bounds of its region? Such as a drop down box. Kind of like if you had a DropDownBox in a Small Sized Panel.

如何创建一个超出其区域范围的C#Winforms控件?比如一个下拉框。有点像你在小尺寸面板中有一个DropDownBox。

3 个解决方案

#1


8  

Windows Forms doesn't support windows like that well, it is pretty fundamentally incompatible with the designer. Here's some code to get you started. You can't use this control in the designer, it must be created at run-time. You also must call its Dispose() method yourself.

Windows Forms不支持这样的窗口,它与设计师根本不兼容。这里有一些代码可以帮助您入门。您不能在设计器中使用此控件,它必须在运行时创建。您还必须自己调用其Dispose()方法。

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

public class MyListBox : ListBox {
  private Control mParent;
  private Point mPos;
  private bool mInitialized;

  public MyListBox(Control parent) {
    mParent = parent;
    mInitialized = true;
    this.SetTopLevel(true);
    parent.LocationChanged += new EventHandler(parent_LocationChanged);
    mPos = mParent.Location;
  }

  public new Point Location {
    get { return mParent.PointToClient(this.Location); }
    set { 
      Point zero = mParent.PointToScreen(Point.Empty);
      base.Location = new Point(zero.X + value.X, zero.Y + value.Y);
    }
  }

  protected override Size DefaultSize {
    get {
      return mInitialized ? base.DefaultSize : Size.Empty;
    }
  }

  protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
    if (this.mInitialized)
      base.SetBoundsCore(x, y, width, height, specified);
  }

  void parent_LocationChanged(object sender, EventArgs e) {
    base.Location = new Point(base.Left + mParent.Left - mPos.X, base.Top + mParent.Top - mPos.Y);
    mPos = mParent.Location;
  }

  protected override CreateParams CreateParams {
    get {
      CreateParams cp = base.CreateParams;
      if (mParent != null && !DesignMode) {
        cp.Style = (int)(((long)cp.Style & 0xffff) | 0x90200000);
        cp.Parent = mParent.Handle;
        Point pos = mParent.PointToScreen(Point.Empty);
        cp.X = pos.X;
        cp.Y = pos.Y;
        cp.Width = base.DefaultSize.Width;
        cp.Height = base.DefaultSize.Height;
      }
      return cp;
    }
  }
}

#2


2  

I did something similiar to that recently, and I used a ListBox. The cool think about a listbox, is that you can display it anywhere you want to, even out of bounds of your control. That way, when you detect via a button click or whatever, that you need to display the DropDown that you want, just populate the ListBox and display it anywhere you want. I got the idea from here:

我最近做了类似的事情,我使用了ListBox。很酷的想法是一个列表框,你可以在任何你想要的地方展示它,甚至超出你的控制范围。这样,当您通过单击按钮或其他任何内容进行检测时,您需要显示所需的DropDown,只需填充ListBox并将其显示在您想要的任何位置。我从这里得到了这个想法:

http://msdn.microsoft.com/en-us/library/aa480727.aspx

They show how to build a Custom DataGridView with filtering, and to display the filter values, they place a ListBox under the header cell.

它们展示了如何使用过滤构建Custom DataGridView,并显示过滤器值,它们将ListBox放在标题单元格下。

#3


0  

There is a good article here:

这里有一篇好文章:

http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/article.asp

This has a class which handles some of the tricky aspects of getting this to work correctly, such as keeping the application window titlebar active, handling Alt-Tab and cancelling with a mouse click.

这有一个类可以处理使其正常工作的一些棘手方面,例如保持应用程序窗口标题栏处于活动状态,处理Alt-Tab并用鼠标单击取消。

#1


8  

Windows Forms doesn't support windows like that well, it is pretty fundamentally incompatible with the designer. Here's some code to get you started. You can't use this control in the designer, it must be created at run-time. You also must call its Dispose() method yourself.

Windows Forms不支持这样的窗口,它与设计师根本不兼容。这里有一些代码可以帮助您入门。您不能在设计器中使用此控件,它必须在运行时创建。您还必须自己调用其Dispose()方法。

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

public class MyListBox : ListBox {
  private Control mParent;
  private Point mPos;
  private bool mInitialized;

  public MyListBox(Control parent) {
    mParent = parent;
    mInitialized = true;
    this.SetTopLevel(true);
    parent.LocationChanged += new EventHandler(parent_LocationChanged);
    mPos = mParent.Location;
  }

  public new Point Location {
    get { return mParent.PointToClient(this.Location); }
    set { 
      Point zero = mParent.PointToScreen(Point.Empty);
      base.Location = new Point(zero.X + value.X, zero.Y + value.Y);
    }
  }

  protected override Size DefaultSize {
    get {
      return mInitialized ? base.DefaultSize : Size.Empty;
    }
  }

  protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
    if (this.mInitialized)
      base.SetBoundsCore(x, y, width, height, specified);
  }

  void parent_LocationChanged(object sender, EventArgs e) {
    base.Location = new Point(base.Left + mParent.Left - mPos.X, base.Top + mParent.Top - mPos.Y);
    mPos = mParent.Location;
  }

  protected override CreateParams CreateParams {
    get {
      CreateParams cp = base.CreateParams;
      if (mParent != null && !DesignMode) {
        cp.Style = (int)(((long)cp.Style & 0xffff) | 0x90200000);
        cp.Parent = mParent.Handle;
        Point pos = mParent.PointToScreen(Point.Empty);
        cp.X = pos.X;
        cp.Y = pos.Y;
        cp.Width = base.DefaultSize.Width;
        cp.Height = base.DefaultSize.Height;
      }
      return cp;
    }
  }
}

#2


2  

I did something similiar to that recently, and I used a ListBox. The cool think about a listbox, is that you can display it anywhere you want to, even out of bounds of your control. That way, when you detect via a button click or whatever, that you need to display the DropDown that you want, just populate the ListBox and display it anywhere you want. I got the idea from here:

我最近做了类似的事情,我使用了ListBox。很酷的想法是一个列表框,你可以在任何你想要的地方展示它,甚至超出你的控制范围。这样,当您通过单击按钮或其他任何内容进行检测时,您需要显示所需的DropDown,只需填充ListBox并将其显示在您想要的任何位置。我从这里得到了这个想法:

http://msdn.microsoft.com/en-us/library/aa480727.aspx

They show how to build a Custom DataGridView with filtering, and to display the filter values, they place a ListBox under the header cell.

它们展示了如何使用过滤构建Custom DataGridView,并显示过滤器值,它们将ListBox放在标题单元格下。

#3


0  

There is a good article here:

这里有一篇好文章:

http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/article.asp

This has a class which handles some of the tricky aspects of getting this to work correctly, such as keeping the application window titlebar active, handling Alt-Tab and cancelling with a mouse click.

这有一个类可以处理使其正常工作的一些棘手方面,例如保持应用程序窗口标题栏处于活动状态,处理Alt-Tab并用鼠标单击取消。