2009-01-26 8 views
12

Estoy creando una pequeña utilidad en C#, que agregará texto a un cuadro de texto activo cuando se presione una tecla rápida global, es un tipo de función de autocompletar. Tengo mi tecla de acceso rápida global funcionando, pero ahora no sé cómo obtener el texto actual en el cuadro de texto activo (si la ventana activa es un cuadro de texto). Lo que he intentado hasta ahora es usarObtiene el texto de la ventana activa (y le envía más texto)

a. GetForegroundWindow y luego usar ese identificador llamando a GetWindowText. Esto me dio el título de la ventana activa, no el contenido de la caja de texto.

b. GetActiveWindow y utilizando ese identificador para llamar a GetWindowText. Eso no me da ningún texto en absoluto.

He aquí un ejemplo de lo que he hecho

[DllImport("user32.dll")] 
private static extern bool UnregisterHotKey(IntPtr hWnd, int id); 
[ DllImport("user32.dll") ] 
static extern int GetForegroundWindow(); 
[ DllImport("user32.dll") ] 
static extern int GetWindowText(int hWnd, StringBuilder text, int count); 
[DllImport("user32.dll")] 
static extern int GetActiveWindow(); 

public static void TestA() { 
    int h = GetForegroundWindow(); 
    StringBuilder b = new StringBuilder(); 
    GetWindowText(h, b, 256); 
    MessageBox.Show(b.ToString()); 
} 

public static void TestB() { 
    int h = GetActiveWindow(); 
    StringBuilder b = new StringBuilder(); 
    GetWindowText(h, b, 256); 
    MessageBox.Show(b.ToString()); 
} 

Por lo tanto, cualquier idea sobre cómo lograr esto?

Editar 28.01.2009: Así que, descubrí cómo hacer esto. Esto es lo que utilicé:

using System; 
using System.Text; 
using System.Runtime.InteropServices; 

public class Example 
{ 
[DllImport("user32.dll")] 
static extern int GetFocus(); 

[DllImport("user32.dll")] 
static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); 

[DllImport("kernel32.dll")] 
static extern uint GetCurrentThreadId(); 

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

[DllImport("user32.dll") ] 
static extern int GetForegroundWindow(); 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
static extern int SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam); 

const int WM_SETTEXT = 12; 
const int WM_GETTEXT = 13; 

public static void Main() 
{ 
    //Wait 5 seconds to give us a chance to give focus to some edit window, 
    //notepad for example 
    System.Threading.Thread.Sleep(5000); 
    StringBuilder builder = new StringBuilder(500); 

    int foregroundWindowHandle = GetForegroundWindow(); 
    uint remoteThreadId = GetWindowThreadProcessId(foregroundWindowHandle, 0); 
    uint currentThreadId = GetCurrentThreadId(); 

    //AttachTrheadInput is needed so we can get the handle of a focused window in another app 
    AttachThreadInput(remoteThreadId, currentThreadId, true); 
    //Get the handle of a focused window 
    int focused = GetFocus(); 
    //Now detach since we got the focused handle 
    AttachThreadInput(remoteThreadId, currentThreadId, false); 

    //Get the text from the active window into the stringbuilder 
    SendMessage(focused, WM_GETTEXT, builder.Capacity, builder); 
    Console.WriteLine("Text in active window was " + builder); 
    builder.Append(" Extra text"); 
    //Change the text in the active window 
    SendMessage(focused, WM_SETTEXT, 0, builder); 
    Console.ReadKey(); 
    } 
} 

Algunas notas sobre esto. El ejemplo espera 5 segundos antes de hacer cualquier cosa, dándole la oportunidad de enfocar una ventana de edición. En mi aplicación real, estoy usando una tecla de acceso rápido para activar esto, pero eso solo confundiría este ejemplo. Además, en el código de producción, debe verificar los valores devueltos de las llamadas win32 para ver si tuvieron éxito o no.

Respuesta

Cuestiones relacionadas