Подтвердить что ты не робот

Как показать форму спереди в С#

Люди,

Пожалуйста, кто-нибудь знает, как показать форму из невидимого приложения, и получить ли она фокус (т.е. появиться поверх других окон)? Я работаю в С#.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 лет; Поэтому я вроде как "знаю кое-что".

Любые идеи были бы наиболее желанными... и Спасибо всем, что нашли время, чтобы прочитать это далеко. Совесть не является (по-видимому) моей сильной стороной.

Приветствия. Кит.

4b9b3361

Ответ 1

Просто

yourForm.TopMost = true;

Ответ 2

Там есть перегрузка Form.ShowDialog(), которая принимает объект IWin32Window. Это IWin32Window рассматривается как родительское окно для формы.

Если у вас есть родительское окно как System.Windows.Forms.Form, продолжайте и просто передайте его. Если нет, получите HWND (возможно, P/Invoking to FindWindow()) и создайте фиктивную реализацию IWin32Window, которая вернет HWND (Подробнее).

Ответ 3

  • Вы сказали, что он отлично работает, когда вы используете Application.Run. Почему вы не хотите использовать Application.Run, то?
  • Вы пытались позвонить BringToFront() из OnLoad или OnShown?

Ответ 4

Form.Activate() работал в моем случае.

Ответ 5

Это окончательное решение, которое я написал после 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);
    }
}

Ответ 6

Я взломал это из приложения, над которым я работаю. У нас есть большое приложение, которое загружает ряд модулей, написанных разными командами. Мы написали один из этих модулей и должны были открыть диалоговое окно входа во время этой инициализации. Он был установлен в .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;

    }
}

}

Ответ 7

Activate() работал у меня тоже.

BringToFront() ничего не сделал в этом случае, я не знаю почему.

Ответ 8

Похоже, что поведение специфично для XP... Поэтому я не могу воспроизвести его в Vista.

http://www.gamedev.net/community/forums/topic.asp?topic_id=218484

РЕДАКТИРОВАТЬ: PS: Прошло мое время сна (2 часа ночи, -).

Thanx все для ваших ответов... есть "несколько вещей", которые я могу попробовать... Я мог бы даже пойти в офис завтра, чтобы попробовать их... Да, да... У меня была жизнь один раз, но Я обменял его на стрижку и работу; -)

Приветствует всех. Кит.

Ответ 9

Это то, что я использую, чтобы открыть открытую форму, которая является частью моего приложения на передней панели. Вы даже можете использовать его с помощью кнопки. Но форма должна быть открыта или приложение сломается.

"YourOpenForm" должно быть именем вашей формы в окне свойств.

    private void button1_Click(object sender, EventArgs e)
    {
        Application.OpenForms["YourOpenForm"].BringToFront();
    }

Удачи!