我如何制作,我会称之为" popup"窗口"在WinForms?
由于我使用了自己制作的单词" popup" ,让我举一个这个所谓的" popup"窗口:
工具提示窗口(可以扩展到其父窗体的边界之外,不会出现在任务栏中,不是模态的,也不会隐藏焦点) :
一个弹出式菜单窗口(可以扩展到其父窗体的边界之外,不会出现在任务栏中,不是模态的,也不会偷取焦点):
下拉窗口(可以延伸到其父窗体的边界之外,不会出现在任务栏中,不是模态的,也不会偷取焦点):
主菜单窗口(可以扩展到其父窗体的边界之外,不会出现在任务栏中,不是模态的,也不会隐藏焦点):
更新 弹出窗口在使用鼠标或键盘进行交互时不会自行the "active" window("所有者"窗口仍然是活动窗口):
我在这个神秘的" popup"中寻找的属性就是这样:
Windows应用程序已经在设法创建这样的窗口。我怎么能在WinForms应用程序中做到这一点?
Control
?我尝试了Show(onwer) + ShowWithoutActivation
方法:
PopupForm dd = new PopupForm ();
dd.Show(this);
使用PopupForm:
public class PopupForm: Form
{
public PopupForm()
{
InitilizeComponent();
}
private void InitilizeComponent()
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.WindowState = FormWindowState.Normal;
this.ShowInTaskbar = false;
}
protected override bool ShowWithoutActivation
{ get { return true; } }
}
几乎解决了这个问题,但随后我发现被提醒了另一个属性" popup" windows:他们没有从他们的"所有者"使用鼠标或键盘进行交互时,表单会变为活动状态。
答案 0 :(得分:3)
您想拥有一个拥有的窗口。在您的主要表格中:
private void showPopup_Click(object sender, EventArgs e)
{
PopupForm popupForm = new PopupForm();
// Make "this" the owner of form2
popupForm.Show(this);
}
PopupForm应如下所示:
public partial class PopupForm : Form
{
private bool _activating = false;
public PopupForm()
{
InitializeComponent();
}
// Ensure the popup isn't activated when it is first shown
protected override bool ShowWithoutActivation
{
get
{
return true;
}
}
private const int WM_NCACTIVATE = 0x86;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
protected override void WndProc(ref Message m)
{
// The popup needs to be activated for the user to interact with it,
// but we want to keep the owner window's appearance the same.
if ((m.Msg == WM_NCACTIVATE) && !_activating && (m.WParam != IntPtr.Zero))
{
// The popup is being activated, ensure parent keeps activated appearance
_activating = true;
SendMessage(this.Owner.Handle, WM_NCACTIVATE, (IntPtr) 1, IntPtr.Zero);
_activating = false;
// Call base.WndProc here if you want the appearance of the popup to change
}
else
{
base.WndProc(ref m);
}
}
}
并确保PopupForm.ShowInTaskbar = false
。
答案 1 :(得分:3)
我很好奇组合框的下拉菜单和菜单是如何工作的,所以我做了更多的研究。
有两种基本方法。
将弹出窗口设置为由主窗口拥有的重叠窗口
如果弹出窗口具有嵌入式控件,或者您希望弹出窗口表现为无模式对话框,则需要此方法。
如果用户要在弹出窗口中与子控件进行交互,则必须接收激活。 (因此阻止激活的各种技术,例如处理WM_MOUSEACTIVATE是红色鲱鱼。)当它接收激活时,Windows将停用主窗口。解决此问题的方法是向父级发送WM_NCACTIVATE消息以更新其可视外观,而不更改其激活状态。这是.Net ToolStrip使用的方法,我的另一个答案用代码说明了它。
将弹出窗口设置为桌面窗口的子窗口
此方法由组合框下拉列表和(我猜)菜单使用,但您无法嵌入子控件,因此它不能广泛应用。
弹出窗口是子窗口,因此不会干扰激活。它总是在顶部。鼠标捕获用于检测弹出窗口外的点击并将其关闭。
但是,实施起来并不简单。激活仍然在主应用程序中,因此它保持焦点并接收击键。这似乎排除了弹出窗口中的嵌入式控件,因为它们无法获得焦点。组合框通过将击键消息转发到其下拉列表来处理此问题。 (请注意,菜单,组合框下拉列表等都是完全所有者绘制的,因为它们没有嵌入式窗口。)
答案 2 :(得分:0)
创建你的" popup"窗口作为桌面的子窗口,然后显示它而不激活它。
hWnd = CreateWindowEx(..., WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER | WS_CLIPSIBLINGS, ..., GetDesktopWindow(), ...);
SetWindowPos(hWnd, HWND_TOPMOST, ..., SWP_NOACTIVATE);
执行此操作后,即使您单击" popuped"窗口。 " popup"窗口可以有自己的子控件。您可以单击它上面的按钮。但如果它是一个编辑控件,你就无法编辑它,我也不知道为什么。也许是因为原始窗口上已经有一个光标,闪烁。