C#如何在前面显示表格
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/987053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to show form in front in C#
提问by corlettk
Folks,
各位,
Please does anyone know how to show a Form from an otherwise invisible application, andhave it get the focus (i.e. appear on top of other windows)? I'm working in C# .NET 3.5.
请问有谁知道如何从其他不可见的应用程序中显示表单,并让它获得焦点(即出现在其他窗口的顶部)?我在 C# .NET 3.5 中工作。
I suspect I've taken "completely the wrong approach"... I do notApplication.Run(new TheForm ())instead I (new TheForm()).ShowModal()... The Form is basically a modal dialogue, with a few check-boxes; a text-box, and OK and Cancel Buttons. The user ticks a checkbox and types in a description (or whatever) then presses OK, the form disappears and the process reads the user-input from the Form, Disposes it, and continues processing.
我怀疑我采取了“完全错误的方法”......我没有Application.Run(new TheForm ())而是我(new TheForm()).ShowModal()... Form 基本上是一个模态对话,有几个复选框;一个文本框,以及确定和取消按钮。用户勾选一个复选框并输入描述(或其他内容),然后按 OK,表单消失,进程从表单读取用户输入,处理它,并继续处理。
This works, except when the form is show it doesn't get the focus, instead it appears behind the "host" application, until you click on it in the taskbar (or whatever). This is a most annoying behaviour, which I predict will cause many "support calls", and the existing VB6 version doesn't have this problem, so I'm going backwards in usability... and users won't accept that (and nor should they).
这是有效的,除非显示表单时它没有获得焦点,而是出现在“主机”应用程序后面,直到您在任务栏(或其他任何内容)中单击它。这是一个最烦人的行为,我预测这会导致许多“支持呼叫”,而现有的 VB6 版本没有这个问题,所以我在可用性方面倒退了......用户不会接受(和他们也不应该)。
So... I'm starting to think I need to rethink the whole shebang... I should show the form up front, as a "normal application" and attach the remainer of the processing to the OK-button-click event. It should work, But that will take time which I don't have (I'm already over time/budget)... so first I really need to try to make the current approach work... even by quick-and-dirty methods.
所以......我开始认为我需要重新考虑整个shebang......我应该在前面显示表单,作为“普通应用程序”并将处理的剩余部分附加到OK-button-click事件。它应该可以工作,但这需要我没有的时间(我已经超过了时间/预算)......所以首先我真的需要尝试使当前的方法有效......即使是快速和-肮脏的方法。
So please does anyone know how to "force" a .NET 3.5 Form (by fair means or fowl) to get the focus? I'm thinking "magic" windows API calls (I know
所以请问有谁知道如何“强制”一个 .NET 3.5 表单(通过公平的方式或家禽)来获得焦点?我在想“神奇”的 Windows API 调用(我知道
Twilight Zone:This only appears to be an issue at work, we're I'm using Visual Studio 2008 on Windows XP SP3... I've just failed to reproduce the problem with an SSCCE (see below) at home on Visual C# 2008 on Vista Ulimate... This works fine. Huh? WTF?
Twilight Zone:这似乎只是工作中的一个问题,我们在 Windows XP SP3 上使用 Visual Studio 2008 ......我在家里的 Visual Studio 上用 SSCCE(见下文)重现问题失败Vista Ulimate 上的 C# 2008 ......这工作正常。嗯?跆拳道?
Also, I'd swear that at work yesterday showed the form when I ran the EXE, but not when F5'ed (or Ctrl-F5'ed) straight from the IDE (which I just put up with)... At home the form shows fine either way. Totaly confusterpating!
另外,我发誓昨天在工作中运行 EXE 时显示了该表单,但当我直接从 IDE(我刚刚忍受)F5'ed(或 Ctrl-F5'ed)时不会显示该表单......在家里无论哪种方式,表格都显示良好。完全混乱!
It may or may not be relevant, but Visual Studio crashed-and-burned this morning when the project was running in debug mode and editing the code "on the fly"... it got stuck what I presumed was an endless loop of error messages. The error message was something about "can't debug this project because it is not the current project, or something... So I just killed it off with process explorer. It started up again fine, and even offered to recover the "lost" file, an offer which I accepted.
它可能相关,也可能不相关,但是今天早上,当项目在调试模式下运行并“即时”编辑代码时,Visual Studio 崩溃了……它卡住了,我认为是一个无限循环的错误消息。错误消息是关于“无法调试这个项目,因为它不是当前项目,或者什么......所以我只是用进程浏览器将它关闭。它再次启动良好,甚至提供恢复“丢失的" 文件,我接受了报价。
using System;
using System.Windows.Forms;
namespace ShowFormOnTop {
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
Form1 frm = new Form1();
frm.ShowDialog();
}
}
}
Background:I'm porting an existing VB6 implementation to .NET... It's a "plugin" for a "client" GIS application called MapInfo. The existing client "worked invisibly" and my instructions are "to keep the new version as close as possible to the old version", which works well enough (after years of patching); it's just written in an unsupported language, so we need to port it.
背景:我正在将现有的 VB6 实现移植到 .NET...它是一个名为MapInfo的“客户端”GIS 应用程序的“插件” 。现有客户端“隐身工作”,我的指示是“让新版本尽可能接近旧版本”,效果很好(经过多年的修补);它只是用不受支持的语言编写的,所以我们需要移植它。
About me:I'm pretty much a noob to C# and .NET generally, though I've got a bottoms wiping certificate, I have been a professional programmer for 10 years; So I sort of "know some stuff".
关于我:我对 C# 和 .NET 基本上是个菜鸟,虽然我有一个擦底证书,但我已经做了 10 年的专业程序员;所以我有点“知道一些东西”。
Any insights would be most welcome... and Thank you all for taking the time to read this far. Consiseness isn't (apparently) my forte.
任何见解将是最受欢迎的......感谢大家花时间阅读本文。一致性不是(显然)我的强项。
Cheers. Keith.
干杯。基思。
采纳答案by corlettk
Simply
简单地
yourForm.TopMost = true;
回答by ChrisV
There's an overload of Form.ShowDialog() which takes an IWin32Window object. That IWin32Window is treated as the parent window for the form.
Form.ShowDialog() 有一个重载,它接受一个 IWin32Window 对象。IWin32Window 被视为窗体的父窗口。
If you have the parent window as a System.Windows.Forms.Form, go ahead and just pass it. If not, get the HWND (maybe by P/Invoking to FindWindow()), and create a dummy IWin32Window implementation that just returns the HWND (More details).
如果您将父窗口作为 System.Windows.Forms.Form,请继续并传递它。如果没有,获取 HWND(可能通过 P/Invoking 到 FindWindow()),并创建一个仅返回 HWND 的虚拟 IWin32Window 实现(更多详细信息)。
回答by P Daddy
- You said that it works fine when you use
Application.Run
. Why don't you want to useApplication.Run
, then? - Have you tried calling
BringToFront()
fromOnLoad
orOnShown
?
- 您说使用
Application.Run
. 那你为什么不想用Application.Run
呢? - 你试过
BringToFront()
从OnLoad
或打电话OnShown
吗?
回答by corlettk
It would appear that is behaviour is specific to XP... Hence I can't reproduce it on Vista.
这似乎是特定于 XP 的行为......因此我无法在 Vista 上重现它。
http://www.gamedev.net/community/forums/topic.asp?topic_id=218484
http://www.gamedev.net/community/forums/topic.asp?topic_id=218484
EDIT:PS: It's past my bedtime (2 AM;-).
编辑:PS:已经过了我的就寝时间(凌晨 2 点;-)。
Thanx all for your responses... there's a "few things" I can try... I might even go into the office tomorrow to try them... Yeah, yeah... I had a life once, but I traded it for a haircut and a job ;-)
谢谢大家的回答……有“几件事”我可以尝试……我什至可能明天去办公室试试……是的,是的……我曾经有过生活,但我交易了它理发和工作;-)
Cheers all. Keith.
给大家加油。基思。
回答by alex
I've hacked this from an application I've been working on. We have a large application that loads a series of modules written by different teams. We have written one of these modules, and needed to have a login dialog open during this initialization. It was set to '.TopMost=true', but that didn't work.
我已经从我一直在开发的应用程序中破解了它。我们有一个大型应用程序,它加载了由不同团队编写的一系列模块。我们已经编写了这些模块之一,并且需要在此初始化期间打开一个登录对话框。它被设置为“.TopMost=true”,但这不起作用。
It uses the WindowsFormsSynchronizationContext to open a dialog box, and then get the result of the dialog box back.
它使用 WindowsFormsSynchronizationContext 打开一个对话框,然后返回对话框的结果。
I rarely do GUI coding, and suspect this may be overkill, but it might help someone if they get stuck. I had problems with understanding how state is passed to the SendOrPostCallback, as all the examples I could find didn't use it.
我很少进行 GUI 编码,并且怀疑这可能是矫枉过正,但如果有人遇到困难,它可能会有所帮助。我在理解状态如何传递给 SendOrPostCallback 时遇到了问题,因为我能找到的所有示例都没有使用它。
Also this is taken from a working application, but I've removed several bits of code, and changed some of the details. Apologies if it doesn't compile.
这也是从一个工作应用程序中获取的,但我删除了几位代码,并更改了一些细节。如果不能编译,请见谅。
public bool Dummy()
{
// create the login dialog
DummyDialogForm myDialog = new DummyDialogForm();
// How we show it depends on where we are. We might be in the main thread, or in a background thread
// (There may be better ways of doing this??)
if (SynchronizationContext.Current == null)
{
// We are in the main thread. Just display the dialog
DialogResult result = myDialog.ShowDialog();
return result == DialogResult.OK;
}
else
{
// Get the window handle of the main window of the calling process
IntPtr windowHandle = Process.GetCurrentProcess().MainWindowHandle;
if (windowHandle == IntPtr.Zero)
{
// No window displayed yet
DialogResult result = myDialog.ShowDialog();
return result == DialogResult.OK;
}
else
{
// Parent window exists on separate thread
// We want the dialog box to appear in front of the main window in the calling program
// We would like to be able to do 'myDialog.ShowDialog(windowHandleWrapper)', but that means doing something on the UI thread
object resultState = null;
WindowsFormsSynchronizationContext.Current.Send(
new SendOrPostCallback(delegate(object state) { resultState = myDialog.ShowDialog(); }), resultState);
if (resultState is DialogResult)
{
DialogResult result = (DialogResult) resultState;
return result == DialogResult.OK;
}
else
return false;
}
}
}
}
回答by Esen
Form.Activate()
worked in my case.
Form.Activate()
在我的情况下工作。
回答by user2162266
Activate()
worked for me too.
Activate()
也为我工作。
BringToFront()
did nothing in this case, I don't know why.
BringToFront()
在这种情况下什么也没做,我不知道为什么。
回答by Wael Azmy
This is what I use to bring an open form that is part of my application to the front. You can even use it with a button. But the form needs to be open or the application will break.
这是我用来将作为我的应用程序一部分的开放表单带到前面的方法。您甚至可以通过按钮使用它。但是表单需要打开,否则应用程序将中断。
"YourOpenForm" has to be the name of your form from the properties window.
“YourOpenForm”必须是属性窗口中表单的名称。
private void button1_Click(object sender, EventArgs e)
{
Application.OpenForms["YourOpenForm"].BringToFront();
}
Good Luck!
祝你好运!
回答by bluish
This is the final solution I wrote after 20 different attempts:
这是我在 20 次不同尝试后编写的最终解决方案:
/* A workaround for showing a form on the foreground and with focus,
* even if it is run by a process other than the main one
*/
public static void ShowInForeground(this Form form, bool showDialog = false)
{
if (showDialog)
{
//it's an hack, thanks to http://stackoverflow.com/a/1463479/505893
form.WindowState = FormWindowState.Minimized;
form.Shown += delegate(Object sender, EventArgs e) {
((Form)sender).WindowState = FormWindowState.Normal;
};
form.ShowDialog();
}
else
{
//it's an hack, thanks to http://stackoverflow.com/a/11941579/505893
form.WindowState = FormWindowState.Minimized;
form.Show();
form.WindowState = FormWindowState.Normal;
//set focus on the first control
form.SelectNextControl(form.ActiveControl, true, true, true, true);
}
}
回答by Willie Bronkhorst
This did the job perfectly :
这完美地完成了工作:
formxx.WindowState = FormWindowState.Normal;
formxx.BringToFront();
formxx.Topmost=true;
formxx.Focus();