c windows winapi clipboard selection

¿Cómo obtengo el texto seleccionado de la ventana enfocada usando la API nativa de Win32?



windows winapi (3)

Mi aplicacion se ejecutará en el sistema intente monitorear una tecla de acceso rápido; cuando el usuario selecciona texto en cualquier ventana y presiona una tecla de acceso directo, ¿cómo obtengo el texto seleccionado cuando recibo el mensaje WM_HOTKEY?

Para capturar el texto en el portapapeles, intenté enviar Ctrl + C usando keybd_event() y SendInput() a la ventana activa ( GetActiveWindow() ) y la ventana de forground ( GetForegroundWindow() ); intentado combinaciones entre estos; todo en vano. ¿Puedo obtener el texto seleccionado de la ventana enfocada en Windows con las API simples del sistema Win32?


Intente agregar un Sleep() después de cada SendInput (). Algunas aplicaciones simplemente no son tan rápidas para capturar la entrada del teclado.


Prueba SendMessage (WM_COPY, etc.).


TL; DR: Sí, hay una forma de hacerlo utilizando las API del sistema win32 simple, 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 lo hará. Déjame repasar 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 el ID de HWND de la ventana de destino. Hay muchas maneras de hacer esto. Uno de estos enfoques es el que mencionó anteriormente: obtenga la ventana de primer plano y luego la ventana con el enfoque, etc. Sin embargo, hay una gran idea que muchas personas olvidan. Después de obtener la ventana de primer plano, debe AttachThreadInput para obtener la ventana enfocada. De GetFocus() 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 tu 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(). }

Enviar las pulsaciones 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 que es más importante, no puede ser desordenado por la entrada de usuarios concurrentes u otros programas que simulen pulsaciones de teclas.

Esto significa que se requerirá que el programa se ejecute en Windows XP o posterior, así que, ¡disculpe 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(). }

Ahí. 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 piensas primero. El "portapapeles" puede contener múltiples representaciones de la misma cosa. La aplicación que está activa cuando copia en el portapapeles tiene control sobre qué colocar exactamente en el portapapeles.

Cuando copia 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 manera puedes pegarlo en el wordpad y el bloc de notas. Wordpad usaría el formato de texto enriquecido, mientras que el bloc de notas usaría el formato de texto simple.

Sin embargo, para este ejemplo simple, supongamos que solo nos interesa el texto simple.

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 ahí lo tienes! Solo asegúrese de copiar lpstr en alguna variable que quiera usar, no use lpstr directamente, ya que tenemos que 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 desalentadora.

¡Aclamaciones!