john1990_1 Ответов: 1

Как отправить ctrl+c в активный процесс?


В приложениях Windows forms я хочу отправить Ctrl+C в активное окно, чтобы получить выделенный текст для его перевода при нажатии Win+C.

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

                    Process p = Process.GetProcessesByName(GetActiveProcessFileName()).FirstOrDefault();
                    if (p != null)
                    {
                        IntPtr h = p.MainWindowHandle;
                        SetForegroundWindow(h);

                        SendKeys.SendWait("^C");

                    }




[DllImport("User32.dll")]
static extern int SetForegroundWindow(IntPtr point);




[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);


static string GetActiveProcessFileName()
{
    IntPtr hwnd = GetForegroundWindow();
    uint pid;
    GetWindowThreadProcessId(hwnd, out pid);
    Process p = Process.GetProcessById((int)pid);
    return p.MainModule.FileName;
}

Richard MacCutchan

У вас есть вопрос?

john1990_1

Код работает только в приложении "блокнот", в остальных случаях он не вводится в приложение "Блокнот".:

if(p != null)...

p остается нулевым, когда активный процесс не Блокнот.

john1990_1

Теперь я столкнулся с этим из-за невозможности получить 64-битные приложения (когда я попытался получить имя Chrome, пожалуйста, дайте мне новый код, который действительно отправляет Ctrl+C в активное окно, чтобы получить выделенный текст и поместить его в буфер обмена.

Richard MacCutchan

Извините, но я не понимаю, что вы имеете в виду, или какое это имеет отношение к блокноту.

john1990_1

Мне нужен код, который отправляет Ctrl+C в активное окно Windows, чтобы поместить выделенный текст в буфер обмена.

Richard MacCutchan

Сначала вам нужно получить ручку окна, в которое вам нужно отправить ключи. Но если вы используете Win+C для запуска приложения, чтобы отправить Ctrl+C в другое окно, почему бы просто не использовать Ctrl+C в первом окне? И вы также должны знать, что Ctrl+C может не работать на некоторых пользовательских приложениях.

john1990_1

Это программа для перевода, я хочу, чтобы Win+C скопировал выделенный текст из активного окна и открыл свою программу и перевел текст, который выбран в активном окне окон пользователя. Теперь, возможно, Win+C проблематичен, потому что он активирует меню Пуск, я изменил его на клавишу F8. но теперь в Chrome "Inspect Element" открывается, когда я нажимаю F8 и программа отправляет Ctrl+C.

Richard MacCutchan

У меня такое чувство, что ты все усложняешь больше, чем нужно. Почему бы просто не использовать Ctrl+C на клавиатуре, чтобы скопировать текст из любого окна, на которое вы смотрите, а затем вставить его в свое приложение?

1 Ответов

Рейтинг:
11

Thomas Daniels

p является нулевым, потому что Process.GetProcessesByName ожидает "понятное имя" процесса, а не полный путь к файлу, который, как представляется, возвращается GetActiveProcessFileName.

Но вот некоторые хорошие новости: Вам даже не нужно использовать GetProcessesByName, чтобы получить нужный процесс: в GetActiveProcessFileName у вас есть строка Process p = Process.GetProcessById((int)pid) а это p это именно тот процесс, который вы хотите, поэтому вам не нужно возвращать имя файла этого процесса, чтобы получить его снова позже: просто верните p уже. Вот это да GetActiveProcess метод, возвращающий нужный процесс:

static Process GetActiveProcess()
{
    IntPtr hwnd = GetForegroundWindow();
    uint pid;
    GetWindowThreadProcessId(hwnd, out pid);
    return Process.GetProcessById((int)pid);
}
И тогда вы сможете заменить его Process p = Process.GetProcessesByName ... в соответствии с этим:
Process p = GetActiveProcess();


[Редактировать]

Оказывается, что "^C" не всегда активное приложение копирует выбранный текст, но у меня были лучшие результаты с этим приложением. "^c" (то есть строчная буква С).


john1990_1

Thx, теперь как отправить Ctrl+C в активное приложение, которое вы нашли?

Thomas Daniels

Точно так же, как это сделал ты. Единственное отличие заключается в том, что вы используете GetActiveProcess вместо Process.GetProcessesByName.

john1990_1

но это не работает.

Thomas Daniels

Объясните, что "не работает". Дает ли это ошибку? Это неправильный процесс? Или он просто не копирует текст? Когда я попробовал, это сработало отлично.

john1990_1

Когда я запускаю это на F7 keyup, он копирует текст только в том случае, если Блокнот является активным процессом:
Процесс p = GetActiveProcess();
если (p != null)
{
IntPtr h = p.MainWindowHandle;
SetForegroundWindow(h);
Отправить ключи.SendWait("^C");
}

Thomas Daniels

А, я кое-что нашел. Смотрите правку в моем ответе.

john1990_1

сработало, спасибо большое бро!

Thomas Daniels

Всегда пожалуйста!

Dave Kreskowiak

Я даже не знаю, почему вы устанавливаете окно переднего плана. SendKeys отправляет нажатия клавиш в любое окно, которое в данный момент является активным окном!

Вот почему SendKeys так опасно использовать. Ваш код устанавливает окно переднего плана, а затем вызывает SendKeys. Ну, эти две строки кода не являются атомарной операцией. В активном окне можно изменить время, которое вы установить окно переднего плана и в момент вызова sendkeys будет. Нет никакой гарантии, что ключи попадут именно в то окно, которое вы намереваетесь открыть.

Прежде чем вы спросите, нет, нет 100% гарантированного метода, который будет делать это надежно каждый раз. Даже используя вызов sendMessage[^], WM_KEYUP[^], WM_CHAR[^], и WM_KEYDOWN[^] не будет работать на каждом возможном окне, которое может использовать пользователь.

john1990_1

Thx для вашей помощи, но теперь программа не всегда работает, я удалил из нее функцию auto Ctrl+C, например, когда я отправил Ctrl+c в текст на иврите, он заменяет его на "c", что означает, что ctrl не был нажат хорошо... Я даже заставил его подождать 150 мс, прежде чем использовать буфер обмена, и clipbaord вообще не меняется.

Thomas Daniels

Я также наткнулся на предложение поставить букву С в скобки, например ^(c) Если и это не сработает, у меня закончатся идеи.

john1990_1

Я пробовал это, и это не всегда срабатывало, я также пытался удалить настройку окна переднего плана, и это тоже не всегда срабатывало...

Thomas Daniels

Тогда у меня больше нет идей. Но имейте в виду комментарий Дэйва Кресковяка.

john1990_1

Хорошо, я удалил отправку Ctrl+C в свою программу, я сделал так, что Ctrl+C дважды переводится:

https://sites.google.com/site/windowsprogramfortranslation/