TL; DR: Да, есть способ сделать это, используя простые системные API-интерфейсы win32, но это трудно реализовать правильно.
WM_COPY и WM_GETTEXT могут работать, но не во всех случаях. Они зависят от того, как окно приема обрабатывает запрос, и во многих случаях это не так. Позвольте мне пробежать один из возможных способов сделать это. Это может быть не так просто, как вы надеялись, но что находится в наполненном приключениями мире программирования win32? Готовы? Хорошо. Поехали.
Сначала нам нужно получить идентификатор HWND целевого окна. Есть много способов сделать это. Один из таких подходов - тот, который вы упомянули выше: получите окно переднего плана, а затем окно с фокусом и т. Д. Однако, есть одна огромная ошибка, которую многие люди забывают. После того, как вы получите окно переднего плана, вы должны AttachThreadInput
, чтобы получить окно с фокусом. В противном случае GetFocus()
просто вернет NULL
.
Есть намного более простой способ. Просто (не хватает) использовать функции GUITREADINFO. Это намного безопаснее, поскольку позволяет избежать всех скрытых опасностей, связанных с подключением вашего входного потока к другой программе.
LPGUITHREADINFO lpgui = NULL;
HWND target_window = NULL;
if( GetGUIThreadInfo( NULL, lpgui ) )
target_window = lpgui->hwndFocus;
else
{
// You can get more information on why the function failed by calling
// the win32 function, GetLastError().
}
Посылка нажатий клавиш для копирования текста немного сложнее ...
Мы собираемся использовать SendInput вместо keybd_event, потому что он быстрее и, что самое важное, не может испортиться при одновременном вводе пользователем или других программах, имитирующих нажатия клавиш.
Это означает, что программа должна будет работать на Windows XP или более поздней версии, поэтому, извините, если вы работаете с 98!
// We're sending two keys CONTROL and 'V'. Since keydown and keyup are two
// seperate messages, we multiply that number by two.
int key_count = 4;
INPUT* input = new INPUT[key_count];
for( int i = 0; i < key_count; i++ )
{
input[i].dwFlags = 0;
input[i].type = INPUT_KEYBOARD;
}
input[0].wVK = VK_CONTROL;
input[0].wScan = MapVirtualKey( VK_CONTROL, MAPVK_VK_TO_VSC );
input[1].wVK = 0x56 // Virtual key code for 'v'
input[1].wScan = MapVirtualKey( 0x56, MAPVK_VK_TO_VSC );
input[2].dwFlags = KEYEVENTF_KEYUP;
input[2].wVK = input[0].wVK;
input[2].wScan = input[0].wScan;
input[3].dwFlags = KEYEVENTF_KEYUP;
input[3].wVK = input[1].wVK;
input[3].wScan = input[1].wScan;
if( !SendInput( key_count, (LPINPUT)input, sizeof(INPUT) ) )
{
// You can get more information on why this function failed by calling
// the win32 function, GetLastError().
}
Там. Это было не так уж плохо, правда?
Теперь нам просто нужно взглянуть на то, что находится в буфере обмена. Это не так просто, как вы могли подумать. «Буфер обмена» может фактически содержать несколько представлений одной и той же вещи. Приложение, которое активно при копировании в буфер обмена, имеет контроль над тем, что именно поместить в буфер обмена.
Например, когда вы копируете текст из Microsoft Office, он помещает данные RTF в буфер обмена вместе с текстовым представлением того же текста. Таким образом, вы можете вставить его в WordPad и Блокнот. WordPad будет использовать формат расширенного текста, в то время как Notepad будет использовать формат простого текста.
Для этого простого примера, давайте предположим, что нас интересует только открытый текст.
if( OpenClipboard(NULL) )
{
// Optionally you may want to change CF_TEXT below to CF_UNICODE.
// Play around with it, and check out all the standard formats at:
// http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx
HGLOBAL hglb = GetClipboardData( CF_TEXT );
LPSTR lpstr = GlobalLock(hglb);
// Copy lpstr, then do whatever you want with the copy.
GlobalUnlock(hglb);
CloseClipboard();
}
else
{
// You know the drill by now. Check GetLastError() to find out what
// went wrong. :)
}
И вот оно у тебя! Просто убедитесь, что вы скопировали lpstr в какую-то переменную, которую хотите использовать, не используйте lpstr напрямую, так как мы должны передать контроль над содержимым буфера обмена, прежде чем закрыть его.
Поначалу программирование на Win32 может показаться довольно сложным, но через некоторое время ... оно все еще устрашает.
Ура!