Сделайте форму, не настраиваемую на С#

Я хочу написать виртуальную клавиатуру, такую ​​как окна на экранной клавиатуре для сенсорного экрана. Но у меня проблема с моей виртуальной клавиатурой, крадущей фокус из используемого приложения. Окна на экранной клавиатуре фокусируются на текущем приложении, даже когда пользователь нажимает на него. Есть ли способ сделать то же самое с окнами в С#?

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

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);


[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

private void button1_Click(object sender, EventArgs e)
{
    IntPtr calculatorHandle = FindWindow("notepad", null);
    SetForegroundWindow(calculatorHandle);
    SendKeys.SendWait("111");
}

Есть ли способ сделать это? Любые предложения лучшего способа иметь форму отправки событий клавиатуры в используемое приложение?

Спасибо!!

Ответ 1

Вместо того, чтобы пытаться reset открыть активное окно после того, как ваш клик был нажат, я скорее попытаюсь запретить вашему окну получать фокус/быть активированным.

Посмотрите в этой статье. В конце автор кратко объясняет, как это можно сделать:

Как я могу предотвратить, чтобы мое окно не получало активацию и фокус при показе?

В Windows Forms 2.0 появилось новое свойство ShowWithoutActivation - что вам нужно переопределить в форме. В собственных приложениях вы можете использовать SetWindowPos с SWP_NOACTIVATE или ShowWindow с флагом SW_SHOWNA.

Кроме того, в в этой статье он предоставляет пример кода для Windows Forms:

Если вы хотите использовать полную форму, теперь вы можете переопределить свойство, называемое ShowWithoutActivation:

public class NoActivateForm : Form {  
    protected override bool ShowWithoutActivation {  
        get {  
            return true;  
        }  
    }  
}

Помните, что это не "предотвращает" активацию все время - вы можете все еще активируются, вызывая методы Activate(), Focus()... и т.д. Если вы хотите запретить кликам на клиентской области активировать окна, вы можете обрабатывать сообщение WM_MOUSEACTIVATE.

private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003;

protected override void WndProc(ref Message m) {
    if (m.Msg == WM_MOUSEACTIVATE) {
         m.Result = (IntPtr)MA_NOACTIVATE;
         return;
    }
    base.WndProc(ref m);
}

Ответ 2

Решено!

Я пробовал решение от gehho, но мне также пришлось переопределить метод CreateParams:

private const int WS_EX_NOACTIVATE = 0x08000000;
protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;
            createParams.ExStyle |= WS_EX_NOACTIVATE;
            return createParams;
        }
    }