2012-06-06 19 views
7

He comentado casi todo lo que sé. Estoy bastante seguro de que el problema surge en AttachThreadInput. Estaba diseñado para funcionar solo a 32 bits, creo. Créame, si pudiera resolver esto yo mismo, estaría feliz de hacerlo. Leí toda la documentación para eventos en Windows (here) y no estoy más cerca de una solución. Si tienes alguna idea, me encantaría escucharlos.C - win32: AttachThreadInput & SetFocus, 64bit: ninguna pista

#include <stdio.h> 
#include <windows.h> 

int main() 
{ 
    //Structure prereqs for CreateProcess 
    STARTUPINFO   siStartupInfo; 
    PROCESS_INFORMATION piProcessInfo; 
    memset(&siStartupInfo, 0, sizeof(siStartupInfo)); 
    memset(&piProcessInfo, 0, sizeof(piProcessInfo)); 
    siStartupInfo.cb = sizeof(siStartupInfo); 

    if(CreateProcess("c:\\windows\\notepad.exe", "", 0, 0, FALSE, CREATE_DEFAULT_ERROR_MODE, 0, 0, &siStartupInfo, &piProcessInfo) == FALSE) 
    { 
     GetLastError(); 
    } 
    Sleep(1000); 

    //Target thread, I can't seem to get this to return anything !0 
    DWORD dwTargetThread = GetWindowThreadProcessId(piProcessInfo.hProcess,NULL); 
    //For example: 
    //if(dwTargetThread == 0) return -1; 

    //Print debugging info 
    if (GetCurrentThreadId() == dwTargetThread) return -1; else printf("\nMy thread: %u\n\npiProcessInfo.hThread: %u\n\nDWORD dwTargetThread: %u\n\nunsigned int dwTargetThread: %u", GetCurrentThreadId(), piProcessInfo.hThread,dwTargetThread, GetWindowThreadProcessId(piProcessInfo.hProcess,NULL)); 

    //I've tried using piProcessInfo.hThread for AttachTo but I can't cast it to a DWORD as it's 64bit 
    AttachThreadInput(GetCurrentThreadId(),dwTargetThread,TRUE); 
    printf("\n\nAttached...\n"); 
    Sleep(1000); 

    //Set the focus & bring to foreground 
    SetFocus(piProcessInfo.hProcess); 
    printf("Focus set...\n"); 
    Sleep(1000); 
    SetForegroundWindow(piProcessInfo.hProcess); 
    printf("Brought to foreground...\n"); 
    Sleep(1000); 

    //I know I shouldn't use PostMessage for keyboard input but it's just for the example 
    PostMessage(piProcessInfo.hProcess, WM_CHAR, 'g', 0); 
    printf("Message queued\n"); 

    //No better than SetForegroundWindow: 
    //SetWindowPos(piProcessInfo.hProcess, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 
} 
+0

¿Está seguro de que la llamada 'CreateProcess()' es exitosa? Todo parece depender de esto y su código hace lo mismo (aparte de la llamada 'GetLastError()') de cualquier manera. – MatthewD

+0

¿Qué devuelve 'GetLastError()' después de su llamada a 'GetWindowThreadProcessId()'? Vea el comentario inferior en esta página: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633522%28v=vs.85%29.aspx – MatthewD

+0

Sí, 'CreateProcess()' es correcto. El Bloc de notas se abre perfectamente y SendInput funciona si lo traigo al primer plano manualmente. 'GetLastError()' devuelve nulo después de 'GetWindowThreadProcessId (piProcessInfo.hProcess, NULL);' – John

Respuesta

6

GetWindowThreadProcessId recibe como entrada un identificador de ventana. Estás pasando un identificador de proceso que es un compás completamente diferente. Naturalmente, esto resulta en un fracaso. Las siguientes llamadas a SetFocus, SetForegroundWindow, PostMessage y SetWindowPos cometen el mismo error.

Use EnumWindows o FindWindow para obtener el control de la ventana del Bloc de notas.

AttachThreadInput funciona con identificadores de subprocesos. Intentó pasar un identificador a la función y en un proceso de 64 bits los identificadores tienen 64 bits de ancho y los identificadores de subprocesos siguen siendo de 32 bits de ancho. Por supuesto, AttachThreadInput funciona perfectamente bien por debajo de 64 bit. La lección para aprender aquí es que los moldes son indicativos de errores de programación. Si necesita convertir los parámetros al tipo apropiado, generalmente eso significa que está pasando algo incorrecto a la función. Evita el casting.

+0

¡Muchas gracias! Tengo este derecho: 'Manejo hTargetWindow = FindWindow (NULL, "Sin título - Bloc de notas");' y ahora 'GetWindowThreadProcessId (hTargetWindow, NULL);' funciona de maravilla. – John

+0

El tipo correcto es HWND en lugar de HANDLE. SetForegroundWindow tiene limitaciones que se describen con precisión en su documentación. Creo que respondí la pregunta que me hiciste. –

+0

Inmediatamente después de publicar que revisé la documentación y la tengo funcionando ahora. ¡Muchas gracias de nuevo por su ayuda y la corrección HANDLE/HWND! – John