2010-02-14 15 views
9

Estoy buscando una forma de comprobar si una ventana determinada tiene un botón en la barra de tareas. Es decir, dado un identificador a una ventana, necesito un VERDADERO si la ventana está en la barra de tareas, y FALSO de lo contrario.Determinar si una ventana tiene un botón de la barra de tareas

Por el contrario, me pregunto si hay una forma de obtener un control para la ventana que pertenece a un botón de la barra de tareas determinada, que supongo requeriría una manera de enumerar a través de los botones de la barra de tareas.

(El primer primero es la parte que necesito, y la última parte es opcional.)

muchas gracias.

+2

debes aceptar una de las respuestas a continuación. Ambos son muy buenos. –

Respuesta

11

Windows usa la heurística para decidir si se asigna o no un botón a una ventana, y algunas veces hay un retraso antes de que pueda decidirse, por lo que hacer esto 100% con precisión será bastante difícil. Aquí hay un comienzo áspero de las reglas. Hay banderas de estilo moderno que lo hacen fácil de saber, pero cuando esos estilos faltan, la barra de tareas se reduce a adivinar.

En primer lugar, necesitará las dos banderas de estilo de ventana.

LONG Style = GetWindowLong(hwnd, GWL_STYLE); 
LONG ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); 

Ahora las reglas, hay tres reglas que son ciertas.

  • ExStyle & WS_EX_APPWINDOW si, a continuación, TASKBAR
  • si ExStyle & WS_EX_TOOLWINDOW, entonces NOT_TASKBAR
  • si Style & WS_CHILD continuación NOT_TASKBAR

El resto son conjeturas:

  • Style & WS_OVERLAPPED sugiere TASKBAR
  • Style & WS_POPUP sugiere NOT_TASKBAR especialmente si GetParent() != NULL
  • ExStyle & WS_EX_OVERLAPPEDWINDOW sugiere TASKBAR
  • ExStyle & WS_EX_CLIENTEDGE sugiere NOT_TASKBAR
  • ExStyle & WS_EX_DLGMODALFRAME sugiere NOT_TASKBAR

Estoy seguro de que hay otras reglas para adivinar, y en el hecho de que las reglas de adivinanzas han cambiado de versión a versión de Windows.

+0

Guau, parece que esta es una de esas cosas frustrantes que resulta no ser sencillo ... ¿"adivinar"? :(Gracias por la información; voy a darle una oportunidad esta noche. – Synetech

+1

Excelente respuesta. Acabo de usarlo en mi aplicación. Por curiosidad, ¿cómo lo supiste? – Giorgi

+0

Independientemente de estas reglas, una ventana también aparece en el barra de tareas si se ha agregado a través de la interfaz ['ITaskbarList'] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb774652 (v = vs.85) .aspx). AFAIK existe no API para comprobar si se ha agregado una ventana a la barra de tareas de esta manera. – zett42

7
  1. ventana raíz

  2. WS_EX_APPWINDOW -> barra de tareas, independientemente de los otros estilos!

  3. propietario debe ser NULL (GetWindow (ventana, GW_OWNER))

  4. no: WS_EX_NOACTIVATE o WS_EX_TOOLWINDOW:

orden es importante.

segunda pregunta: en Windows XP/Vista fue posible entrar en el proceso de la barra de tareas y obtener todas las ventanas ID's:

void EnumTasklistWindows() 
{ 
    int b2 = 0; 
    TBBUTTON tbButton; 
    DWORD dwProcessId = 0, dwThreadId = 0; 

    HWND hDesktop =::GetDesktopWindow(); 
    HWND hTray =::FindWindowEx(hDesktop, 0, ("Shell_TrayWnd"), NULL); 
    HWND hReBar =::FindWindowEx(hTray, 0, ("ReBarWindow32"), NULL); 
    HWND hTask =::FindWindowEx(hReBar, 0, ("MSTaskSwWClass"), NULL); 
    HWND hToolbar =::FindWindowEx(hTask, 0, ("ToolbarWindow32"), NULL); 

    LRESULT count =::SendMessage(hToolbar, TB_BUTTONCOUNT, 0, 0); 
    dwThreadId = GetWindowThreadProcessId(hToolbar, &dwProcessId); 

    shared_ptr<void> hProcess (OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId), CloseHandle); 
    if (NULL == hProcess.get()) 
    { 
    return; 
    } 

    memset(&tbButton, 0, sizeof(TBBUTTON)); 

    for (int i = 0; i < count; i++) 
    { 
    memset(&tbButton, 0, sizeof(TBBUTTON)); 

    shared_ptr<void> lpRemoteBuffer (
     VirtualAllocEx(hProcess.get(), NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE), 
     bind<BOOL>(VirtualFreeEx, hProcess.get(), _1, 0, MEM_RELEASE)); 
    if (NULL == lpRemoteBuffer.get()) 
    { 
     return; 
    } 

    SendMessage(hToolbar, TB_GETBUTTON, i, (LPARAM) lpRemoteBuffer.get()); 

    b2 = ReadProcessMemory(hProcess.get(), lpRemoteBuffer.get(), 
     (LPVOID) & tbButton, sizeof(TBBUTTON), NULL); 
    if (0 == b2) 
    { 
     continue; 
    } 

    BYTE localBuffer[0x1000]; 
    BYTE *pLocalBuffer = localBuffer; 
    DWORD_PTR ipLocalBuffer = (DWORD_PTR) pLocalBuffer; 
    pLocalBuffer = localBuffer; 
    ipLocalBuffer = (DWORD_PTR) pLocalBuffer; 
    DWORD_PTR lpRemoteData = (DWORD_PTR) tbButton.dwData; 

    ReadProcessMemory(hProcess.get(), (LPVOID) lpRemoteData, (LPVOID) ipLocalBuffer, 
     sizeof(DWORD_PTR), NULL); 

    HWND windowHandle; 
    memcpy(&windowHandle, (void *) ipLocalBuffer, 4); 

    if (windowHandle != NULL) 
    { 
     trace ("adding button: %x\n", windowHandle); 
    } 
    } 
} 

esto no es posible con Windows 7 más. por lo que debe pasar por todas las ventanas de nivel superior.

+0

Encantador, gracias por la información y el código adicionales. Esta noche lo probaré. – Synetech

+0

+1 para el ejemplo de XP/Vista. En mi caso Necesitaba una aplicación rápida y sucia para el uso exclusivo de XP, ¡así que funcionó muy bien! – Unsigned

+0

Independientemente de estas reglas, también aparece una ventana en la barra de tareas si se ha agregado a través de ['ITaskbarList'] (https: // msdn .microsoft.com/es-us/library/windows/desktop/bb774652 (v = vs.85) .aspx) interfaz. AFAIK no hay API para verificar si una ventana h como se ha agregado a la barra de tareas de esta manera. – zett42

1

This MSDN article tiene una buena información acerca de cuándo y por qué el Shell decide crear un botón de la barra de tareas para una ventana:

La Shell crea un botón en la barra de tareas cuando una aplicación crea una ventana que no es propiedad . Para asegurarse de que el botón de ventana se coloca en la barra de tareas, cree una ventana sin propietario con el estilo extendido WS_EX_APPWINDOW. Para evitar que el botón de ventana se coloque en la barra de tareas, cree la ventana sin propietario con el estilo extendido WS_EX_TOOLWINDOW. Como alternativa, puede crear una ventana oculta y hacer de esta ventana oculta el propietario de su ventana visible.

Cuestiones relacionadas