25

皆さん、

他の方法では見えないアプリケーションからフォームを表示し、フォーカスを取得する (つまり、他のウィンドウの上に表示する) 方法を知っている人はいますか? 私は C# .NET 3.5 で作業しています。

「完全に間違ったアプローチ」をとったのではない かと思います... Application.Run(new TheForm ())代わりに I (new TheForm()).ShowModal() ... フォームは基本的にモーダル ダイアログです。いくつかのチェックボックスがあります。テキスト ボックス、OK ボタンとキャンセル ボタン。ユーザーがチェックボックスにチェックを入れ、説明 (または何でも) を入力してから [OK] を押すと、フォームが消え、プロセスがフォームからユーザー入力を読み取り、それを破棄して、処理を続行します。

これは機能しますが、フォームが表示されている場合を除き、フォーカスが得られず、タスクバー (またはその他) でクリックするまで、「ホスト」アプリケーションの背後に表示されます。これは最も厄介な動作であり、多くの「サポート コール」が発生すると予測されます。また、既存の VB6 バージョンにはこの問題がないため、使いやすさを後退させます...そしてユーザーはそれを受け入れません (そしてまた、そうすべきではありません)。

だから...私はシバン全体を再考する必要があると考え始めています...フォームを「通常のアプリケーション」として前もって表示し、残りの処理をOKボタンクリックイベントに添付する必要があります。それはうまくいくはずですが、それには私が持っていない時間がかかります(私はすでに時間/予算を超えています)...だから最初に、現在のアプローチをうまく機能させる必要があります...迅速かつ-汚い方法。

それで、.NET 3.5フォームを(公正な手段または家禽によって)「強制」してフォーカスを得る方法を知っている人はいますか?私は「魔法の」Windows API呼び出しを考えています(私は知っています

トワイライト ゾーン:これは職場の問題のようです。私は Windows XP SP3 で Visual Studio 2008 を使用しています...自宅の Visual で SSCCE (以下を参照) で問題を再現できませんでした。 Vista Ulimate 上の C# 2008... これは正常に動作します。は?なんてこと?

また、昨日職場でEXEを実行したときにフォームが表示されたことを誓いますが、IDEから直接F5キーを押した(またはCtrl-F5キーを押した)ときは表示されませんでした(我慢しました)...家でフォームはどちらの方法でも問題なく表示されます。完全に混乱しています!

関連する場合とそうでない場合がありますが、今朝、プロジェクトがデバッグモードで実行され、「オンザフライ」でコードを編集しているときに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と呼ばれる「クライアント」GIS アプリケーションの「プラグイン」です。既存のクライアントは「目に見えないほど機能した」ので、私の指示は「新しいバージョンを古いバージョンにできるだけ近づけるように」です。サポートされていない言語で書かれているだけなので、移植する必要があります。

私について:私は一般的に C# と .NET にはほとんど慣れていませんが、ボトムワイプ証明書を持っていますが、プロのプログラマーとして 10 年間働いています。だから、私は「何かを知っている」のです。

どんな洞察も大歓迎です...そして、ここまで読んでくれてありがとう。誠実さは (明らかに) 私の得意分野ではありません。

乾杯。キース。

4

11 に答える 11

57

単に

yourForm.TopMost = true;
于 2009-06-12T15:14:55.997 に答える
6

Form.Activate()私の場合はうまくいきました。

于 2012-04-18T18:45:35.230 に答える
5

IWin32Window オブジェクトを受け取る Form.ShowDialog() のオーバーロードがあります。その IWin32Window は、フォームの親ウィンドウとして扱われます。

親ウィンドウを System.Windows.Forms.Form として持っている場合は、そのまま渡してください。そうでない場合は、HWND を取得し (FindWindow() への P/Invoking によって可能性があります)、HWND を返すだけのダミーの IWin32Window 実装を作成します (詳細)。

于 2009-06-12T15:16:26.553 に答える
3
  1. を使うとうまくいくとおっしゃっていましたApplication.Run。では、なぜあなたは使いたくないのですApplication.Runか?
  2. BringToFront()またはから電話をかけてみましたOnLoadOnShown?
于 2009-06-12T15:29:55.740 に答える
1

私が取り組んでいるアプリケーションからこれをハッキングしました。さまざまなチームによって作成された一連のモジュールをロードする大規模なアプリケーションがあります。これらのモジュールの 1 つを作成し、この初期化中にログイン ダイアログを開く必要がありました。「.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;

    }
}

}

于 2010-04-29T17:49:00.573 に答える
0

動作は XP に固有のようです... したがって、Vista では再現できません。

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

編集: PS: 就寝時刻を過ぎています (午前 2 時 ;-)。

回答ありがとうございます...私が試すことができる「いくつかのこと」があります...明日オフィスに行って試してみることもできます...ええ、ええ...私は一度人生を過ごしましたが、それを交換しました散髪と仕事のために;-)

乾杯。キース。

于 2009-06-12T16:20:18.117 に答える
-1

これは、アプリケーションの一部である開いているフォームを前面に表示するために使用するものです。ボタンでも使えます。ただし、フォームを開く必要があります。そうしないと、アプリケーションが壊れます。

「YourOpenForm」は、プロパティ ウィンドウからのフォームの名前である必要があります。

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

幸運を!

于 2013-09-27T18:53:19.567 に答える