I-TensE-I Ответов: 1

Отправить ключевой макрос в закрепленную программу в winform, даже если он свернут / фоновый


ЗАПИСКА Я НЕ использование Блокнота в качестве окончательного приложения, поэтому, пожалуйста, не говорите мне, как док-Блокнот-это бесполезная/плохая идея!

Прямо сейчас в качестве тестового приложения у меня есть блокнот, закрепленный в моей WinForm. В настоящее время я посылаю в него команды, просто фокусируя окно и используя клавиши SendKeys, но это требует фокусировки, что означает, что я не могу делать что-либо еще, пока макрос работает, иначе он отправит входные данные на то, что сфокусировано.

Есть ли способ, чтобы программа отправляла входные данные только себе или, скорее, закрепленному exe-файлу внутри нее, не затрагивая пользователя?

Например, я нажимаю кнопку и сворачиваю окно, и оно все равно набирает 5+5=10 в блокноте, а затем Ctrl+C -> Ctrl+V в другое текстовое поле, в то время как я могу печатать в другом окне.

Что я уже пробовал:

Я пробовал SendKeys (), но это требует сосредоточенности. Я где-то читал о PostMessage, но не смог понять, как его правильно использовать.

1 Ответов

Рейтинг:
1

0x01AA

Взгляните сюда, принятый ответ: Проблема с sendmessage в C#[^]

Я сделал короткий тест на нем, и он действительно работает.
Надеюсь, это поможет.

Редактировать Быстрый и грязный фрагмент тестового кода

public partial class FormMain : Form
{
    // Interop
    [DllImport("user32.dll")]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll", SetLastError = true)]   
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);   

    [DllImport("user32.dll")]
    private static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, UInt32 lParam);   

    // Notepad starter
    Process process = null;

    private void buttonStart_Click(object sender, EventArgs e)
    {
        if (process != null)
            return;
        process = new Process();
        try
        {
            string winpath = Environment.GetEnvironmentVariable("windir");
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.FileName = winpath + @"\system32\notepad.exe";
            process.Start();
            process.WaitForInputIdle();
            {
                Thread.Sleep(200);
                SetParent(process.MainWindowHandle, this.panelClient.Handle);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

    private void buttonSendKeys_Click(object sender, EventArgs e)
    {
        if (process == null)
            return;

        // https://social.msdn.microsoft.com/Forums/en-US/eebaa35b-f22c-47b2-9fc9-2a5e876f0b79/problem-with-sendmessage-in-c?forum=csharplanguage
        UInt32 WM_KEYDOWN = 0x0100;
        UInt32 repeatCount = 13;
        UInt32 scanCode = 0x2D;
        UInt32 extended = 0;
        UInt32 context = 0;
        UInt32 previousState = 0;
        UInt32 transition = 0;

        // combine the parameters above according to the bit
        // fields described in the MSDN page for WM_KEYDOWN
        UInt32 lParam = repeatCount
            | (scanCode << 16)
            | (extended << 24)
            | (context << 29)
            | (previousState << 30)
            | (transition << 31);


        IntPtr editHandle = FindWindowEx(process.MainWindowHandle, IntPtr.Zero, "EDIT", null);

        PostMessage(editHandle, WM_KEYDOWN, 'A', lParam);  
    }
    //...
}


I-TensE-I

Это, кажется, работает очень хорошо, и окно не нужно фокусировать! Это предназначено специально для блокнота, так как он находит поле редактирования в блокноте. Если это другая программа, смогу ли я просто поместить p.MainWindowHandle в качестве первого arg в PostMessage() вместо editHandle?

Итак, если я хочу отправить строку в приложение, мне придется выполнить PostMessage() для каждого отдельного символа в этой строке?

Наконец, чтобы отправить Ctrl+C или Ctrl+V, есть ли в этом особый трюк? Используя отправить вниз, затем вверх по CTRL+C не похоже на работу. Я пытался:

PostMessage(editHandle, WM_KEYDOWN, 0x11,
PostMessage(editHandle, WM_KEYDOWN, 'C',
PostMessage(editHandle, WM_KEYUP, 'C',
PostMessage(editHandle, WM_KEYUP, 0x11, 0);

0x01AA

- Как реагирует другое приложение, кроме блокнота, я думаю, вам нужно протестировать его индивидуально.
- Для отправки строки можно использовать WM_SETTEXT.
- Ctrl+C или Ctrl+V вы не можете решить с помощью WM_KEYUP :(

Наконец я предлагаю вам взглянуть сюда: Windows Input Simulator &#40; C&#35; Sendinput Wrapper-имитация клавиатуры и мыши&#41; - Home[^]. Похоже, это должно решить вашу просьбу. Но, скорее всего, вам нужно его адаптировать, на первый взгляд кажется, что он не предназначен для отправки входных данных в другие приложения.