TL; DR: Sí, hay una forma de hacerlo utilizando las API del sistema win32, pero es difícil de implementar correctamente.
WM_COPY y WM_GETTEXT pueden funcionar, pero no en todos los casos. Dependen de que la ventana de recepción maneje la solicitud correctamente y, en muchos casos, no. Déjame revisar una posible forma de hacer esto. Puede que no sea tan simple como esperabas, pero ¿qué hay en el mundo lleno de aventuras de la programación de win32? Listo? De acuerdo. Vamonos.
Primero necesitamos obtener la identificación HWND de la ventana de destino. Hay muchas maneras de hacer esto. Uno de estos enfoques es el que mencionó anteriormente: obtener la ventana de primer plano y luego la ventana con foco, etc. Sin embargo, hay un enorme que muchos olvidan. Después de obtener la ventana de primer plano, debeAttachThreadInput
para obtener la ventana con foco. De lo contrario, GetFocus()
simplemente devolverá NULL
.
Hay una manera mucho más fácil. Simplemente (señorita) use las funciones GUITREADINFO. Es mucho más seguro, ya que evita todos los peligros ocultos asociados con la conexión de su hilo de entrada con otro programa.
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().
}
El envío de las pulsaciones de teclado para copiar el texto es un poco más complicado ...
Vamos a utilizar SendInput en lugar de keybd_event porque es más rápido y, lo más importante, no se puede mal estado por entrada de usuario concurrente u otros programas que simulen pulsaciones de teclas.
Esto significa que el programa tendrá que ejecutarse en Windows XP o posterior, así que, ¡lo siento si está ejecutando 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().
}
There. Eso no fue tan malo, ¿verdad?
Ahora solo tenemos que echar un vistazo a lo que hay en el portapapeles. Esto no es tan simple como pensarías primero. El "portapapeles" en realidad puede contener múltiples representaciones de la misma cosa. La aplicación que está activa cuando copia al portapapeles tiene control sobre exactamente qué colocar en el portapapeles.
Al copiar texto de Microsoft Office, por ejemplo, coloca datos RTF en el portapapeles, junto con una representación de texto sin formato del mismo texto. De esa forma, puede pegarlo en el juego de palabras y el bloc de notas. Wordpad utilizaría el formato de texto enriquecido, mientras que el bloc de notas utilizaría el formato de texto sin formato.
Para este simple ejemplo, supongamos que solo nos interesa el texto sin formato.
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. :)
}
¡Y ya lo tienes! Solo asegúrese de copiar lpstr a alguna variable que quiera usar, no use lpstr directamente, ya que debemos ceder el control del contenido del portapapeles antes de cerrarlo.
La programación de Win32 puede ser bastante desalentadora al principio, pero después de un tiempo ... sigue siendo desalentador.
¡Salud!
¿Estás seguro de que estás obteniendo el asa de la ventana correcta? Puedes probar esto con Spy ++. Además, ¿has probado el viejo WM_GETTEXT? – Luke
¿Qué versión de Windows? –
@ Aaron: Windows XP y posterior; ambos 32 y 64 bits; básicamente, estoy transfiriendo mi aplicación (http://artha.sourceforge.net/) a Windows y necesito esta característica para continuar. – legends2k