7

バックグラウンドで実行され、ホットキーが押されるのをリッスンする C# winforms アプリケーションがあります。ホットキーを押すと、フォームが簡単に表示されます。フォームは常に実行されていますが、ホットキー イベントを受信するまで非表示に設定されています。ホットキー イベントが発生した時点で、visible プロパティを true に設定します。コードは次のようになります。

void hook_volumeDown(object sender, KeyPressedEventArgs e)
{
    this.Visible = true;
}

このフォームの最上位のプロパティが true に設定されていることに注意してください。

本当に奇妙なのは、私の C# アプリが別のアプリケーションからフォーカスを奪った後、それが再び行われることはないということです。例: アプリを起動してから、Team Fortress 2 などのフルスクリーン アプリを起動します。次に、ホットキーを押します。Team Fortress 2 が最小化され、自分のフォームが表示されます。ただし、その後、TF2 を復元し、必要なだけ (目的の効果で) ホットキーをもう一度押すと、TF2 はフォーカスされたままになります。

とにかく、これを修正する方法を探しています。ここで同様の問題をカバーする多くの質問を見つけましたが、それらはすべて、既存のフォームを表示するのではなく、新しいフォームの作成/起動に関連しています (何かを見落としていない限り)。必要なたびに新しいフォームを作成するようにアプリケーションを作り直すこともできますが、ホットキー イベントを待つためだけに常に非表示にする別のフォームを作成する必要があるため、そのままにしておくことをお勧めします。

何か案は?

4

2 に答える 2

7

あなたの問題は、 Visible = true が最初の呼び出しとその後の呼び出しで異なる動作をするという事実に関連していると思います。visible が初めて呼び出され、ウィンドウ ハンドルが作成されていない場合、ウィンドウの動作を制御するいくつかのスタイル パラメータを持つ CreateWindowEx を呼び出すことによって Window が作成されます。ウィンドウがスタイル WS_EX_NOACTIVATE で作成されていることを確認する必要があると思います。これは、CreateParams をオーバーライドすることで実行できます。

その他の試してみること:

1) ShowWindow 関数 (Visible = true で使用) は、最初に呼び出されたときにフォーカス パラメーターを無視します ( http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx ) 。プログラムは STARTUPINFO 構造体を提供します。リフレクターを掘り下げて、Form クラスが STARTUPINFO 構造を提供しているかどうか、提供している場合はその操作方法を調べてください。

2) フォームには、オーバーライドして true に設定できる ShowWithoutActivation プロパティがあります。これをオーバーライドしましたか?

「正確な答えはありません」で申し訳ありませんが、これが少なくともさらなる調査の出発点になることを願っています. 幸運を。

于 2010-05-15T08:38:26.933 に答える
1

関数で KeyPressedEventArgs が使用されているのを見ると、非常に奇妙に見えます。ホット キーは、RegisterHotKey() API 関数を P/Invoking することで実装できます。ホットキーが押されると、ウィンドウにメッセージが送信されます。これは、起動時には見えず、ホット キーを押すと起動するフォームの例です。この場合、Ctrl+Alt+U:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        private const int MYKEYID = 0;    // In case you want to register more than one...
        public Form1() {
            InitializeComponent();
            this.FormClosing += (s, args) => UnregisterHotKey(this.Handle, MYKEYID);
        }
        protected override void SetVisibleCore(bool value) {
            if (value && !this.IsHandleCreated) {
                this.CreateHandle();
                RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U);
                value = false;
            }
            base.SetVisibleCore(value);
        }
        protected override void WndProc(ref Message m) {
            if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) {
                this.Visible = true;
                if (this.WindowState == FormWindowState.Minimized)
                    this.WindowState = FormWindowState.Normal;
                SetForegroundWindow(this.Handle);
            }
            base.WndProc(ref m);
        }
        // P/Invoke declarations
        private const int WM_HOTKEY = 0x312;
        private const int MOD_ALT = 1;
        private const int MOD_CONTROL = 2;
        private const int MOD_SHIFT = 4;
        [DllImport("user32.dll")]
        private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk);
        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
    }
}

SetForegroundWindow() 関数は問題であり、おそらく質問で説明した問題の原因でもあることに注意してください。Windows では、ユーザーが別のウィンドウをアクティブに使用しているときに、アプリがユーザーの顔にウィンドウを押し込むことを許可していません。ウィンドウがフォーカスを奪う前に、少なくとも数秒間の非アクティブ状態が期限切れになる必要があります。与えられたコードを使用すると、簡単に確認できますが、フォームのタスクバー ボタンが点滅します。ShowInTaskbar プロパティを false に設定しないでください。このコードではその必要はありません。ホット キーが押されるまで、タスク バー ボタンは表示されません。

于 2010-05-15T14:25:52.987 に答える