簡體   English   中英

當我將可見的正確設置為true時,如何防止我的C#winforms應用程序竊取焦點?

[英]How to prevent my C# winforms application from stealing focus when I set the visible properly to true?

我有一個在后台運行的C#winforms應用程序,正在監聽要按下的熱鍵。 當按下熱鍵時,我的表格會短暫出現。 表單始終在運行,但設置為隱藏,直到我收到熱鍵事件,此時我將visible屬性設置為true。 代碼如下所示:

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

應該注意,此表單的最頂層屬性設置為true。

真正奇怪的是,在我的C#應用​​程序從另一個應用程序中竊取焦點后,它將再也不會這樣做了。 例如:我啟動我的應用程序,然后啟動一些像Team Fortress 2這樣的fullscreep應用程序。然后我按下我的熱鍵。 Team Fortress 2最小化,我看到了我的形式。 然而,然后,我可以恢復TF2,並再次按我的熱鍵我想要的(具有所需的效果),TF2將保持聚焦。

無論如何,我正在尋找解決這個問題的方法。 我在這里發現了很多關於類似問題的問題,但是所有問題都與創建/啟動新表單有關,而不是使現有表單可見(除非我遺漏了一些東西)。 我可以重新編寫應用程序,以便在每次需要時創建一個新表單,但這需要創建另一個表單,以便一直看不見只是為了等待熱鍵事件,所以我寧願保持原樣。

有任何想法嗎?

我認為你的問題與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)Form有一個ShowWithoutActivation屬性,可以覆蓋並設置為true,你有沒有覆蓋它?

對不起“沒有確切的答案”,但我希望這至少可以為您提供一些進一步調查的起點。 祝好運。

看到你的函數中使用的KeyPressedEventArgs看起來奇怪。 熱鍵可以通過P / Invoking RegisterHotKey()API函數實現。 當按下熱鍵時,它會向您的窗口發送一條消息。 這是一個在啟動時不可見的表單示例,當您按下熱鍵時彈出。 在這種情況下,按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。 沒有必要使用此代碼,任務欄按鈕將不會顯示,直到按下熱鍵。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM