简体   繁体   English

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

[英]How to create a C# Winforms Control that hovers

How can you create a C# Winforms control which goes out of the bounds of its region? 如何创建超出其区域范围的C#Winforms控件? Such as a drop down box. 比如一个下拉框。 Kind of like if you had a DropDownBox in a Small Sized Panel. 有点像你在小尺寸面板中有一个DropDownBox。

Windows Forms doesn't support windows like that well, it is pretty fundamentally incompatible with the designer. Windows Forms不支持这样的窗口,它与设计者根本不兼容。 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. 您还必须自己调用其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;
    }
  }
}

I did something similiar to that recently, and I used a ListBox. 我最近做了类似的事情,我使用了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. 这样,当您通过单击按钮或其他任何内容进行检测时,您需要显示所需的DropDown,只需填充ListBox并将其显示在任何您想要的位置。 I got the idea from here: 我从这里得到了这个想法:

http://msdn.microsoft.com/en-us/library/aa480727.aspx 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放在标题单元格下。

There is a good article here: 这里有一篇好文章:

http://www.vbaccelerator.com/home/NET/Code/Controls/Popup_Windows/Popup_Windows/article.asp 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并用鼠标单击取消。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM