Ответ 1
Просто
yourForm.TopMost = true;
Люди,
Пожалуйста, кто-нибудь знает, как показать форму из невидимого приложения, и получить ли она фокус (т.е. появиться поверх других окон)? Я работаю в С#.NET 3.5.
Я подозреваю, что принял "совершенно неправильный подход"... Я делаю не Application.Run(новый TheForm()) вместо этого я (новый TheForm()). ShowModal()... Форма - это в основном модальный диалог, с несколькими флажками; текстовое поле и кнопки "ОК" и "Отмена". Пользователь указывает флажок и вводит в описание (или что-то другое), затем нажимает OK, форма исчезает, и процесс считывает пользовательский ввод из формы, удаляет ее и продолжает обрабатывать.
Это работает, за исключением случаев, когда форма показывает, что она не получает фокус, вместо этого она появляется за приложением "хост", пока вы не нажмете на нее в панели задач (или что-то еще). Это наиболее неприятное поведение, которое, как я предсказываю, вызовет многие "вызовы поддержки", и существующая версия VB6 не имеет этой проблемы, поэтому я возвращаюсь в удобство использования... и пользователи не согласятся с этим (и и не должны).
Итак... Я начинаю думать, что мне нужно переосмыслить весь shebang... Я должен показать форму спереди, как "обычное приложение" и приложить оставшуюся часть обработки к кнопке OK, щелкните событие. Он должен работать, но для этого потребуется время, которое у меня нет (я уже со временем/бюджет)... так что сначала мне действительно нужно попытаться заставить текущий подход работать... даже быстрыми темпами, грязные методы.
Итак, пожалуйста, кто-нибудь знает, как "заставить" форму .NET 3.5 (справедливыми средствами или птицей), чтобы получить фокус? Я думаю, что "волшебные" вызовы API Windows (я знаю
Сумеречная зона: Это только кажется проблемой на работе, я использую Visual Studio 2008 в Windows XP SP3... Я просто не смог воспроизвести проблему с SSCCE (см. ниже) дома на Visual С# 2008 в Vista Ulimate... Это отлично работает. А? WTF?
Кроме того, я бы поклялся, что вчера на работе я показал форму, когда я запускал EXE, но не тогда, когда F5'ed (или Ctrl-F5'ed) прямо из среды IDE (которую я просто смирился). У дома форма отлично выглядит в любом случае. Полное опознавание!
Это может быть или не быть релевантным, но 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();
}
}
}
Фон: Я переношу существующую реализацию VB6 на .NET... Это "плагин" для "клиентского" ГИС-приложения, называемого MapInfo. Существующий клиент "работал невидимо", и мои инструкции "сохранить новую версию как можно ближе к старой версии", которая работает достаточно хорошо (после нескольких лет исправления); он просто написан на неподдерживаемом языке, поэтому нам нужно его портировать.
Обо мне: Я вообще-то вроде noob для С# и .NET вообще, хотя у меня есть сертификат об удалении днища, я был профессиональным программистом в течение 10 лет; Поэтому я вроде как "знаю кое-что".
Любые идеи были бы наиболее желанными... и Спасибо всем, что нашли время, чтобы прочитать это далеко. Совесть не является (по-видимому) моей сильной стороной.
Приветствия. Кит.
Просто
yourForm.TopMost = true;
Там есть перегрузка Form.ShowDialog(), которая принимает объект IWin32Window. Это IWin32Window рассматривается как родительское окно для формы.
Если у вас есть родительское окно как System.Windows.Forms.Form, продолжайте и просто передайте его. Если нет, получите HWND (возможно, P/Invoking to FindWindow()) и создайте фиктивную реализацию IWin32Window, которая вернет HWND (Подробнее).
Application.Run
. Почему вы не хотите использовать Application.Run
, то?BringToFront()
из OnLoad
или OnShown
? Form.Activate()
работал в моем случае.
Это окончательное решение, которое я написал после 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 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 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);
}
}
Я взломал это из приложения, над которым я работаю. У нас есть большое приложение, которое загружает ряд модулей, написанных разными командами. Мы написали один из этих модулей и должны были открыть диалоговое окно входа во время этой инициализации. Он был установлен в .TopMost = true, но это не сработало.
Он использует WindowsFormsSynchronizationContext, чтобы открыть диалоговое окно, а затем вернуть результат диалогового окна.
Я редко кодирую GUI и подозреваю, что это может быть излишним, но это может помочь кому-то, если они застрянут. У меня были проблемы с пониманием того, как состояние передается в SendOrPostCallback, так как все примеры, которые я мог найти, не использовали его.
Также это взято из рабочего приложения, но я удалил несколько битов кода и изменил некоторые детали. Извините, если он не компилируется.
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;
}
}
}
Activate()
работал у меня тоже.
BringToFront()
ничего не сделал в этом случае, я не знаю почему.
Похоже, что поведение специфично для XP... Поэтому я не могу воспроизвести его в Vista.
http://www.gamedev.net/community/forums/topic.asp?topic_id=218484
РЕДАКТИРОВАТЬ: PS: Прошло мое время сна (2 часа ночи, -).
Thanx все для ваших ответов... есть "несколько вещей", которые я могу попробовать... Я мог бы даже пойти в офис завтра, чтобы попробовать их... Да, да... У меня была жизнь один раз, но Я обменял его на стрижку и работу; -)
Приветствует всех. Кит.
Это то, что я использую, чтобы открыть открытую форму, которая является частью моего приложения на передней панели. Вы даже можете использовать его с помощью кнопки. Но форма должна быть открыта или приложение сломается.
"YourOpenForm" должно быть именем вашей формы в окне свойств.
private void button1_Click(object sender, EventArgs e)
{
Application.OpenForms["YourOpenForm"].BringToFront();
}
Удачи!