Pergunta

A partir de um par de testes preliminares parece retornos que EnumWindows sempre janelas em ordem inversa, isto é, instanciação mais recentemente instanciado janela em primeiro lugar. É que uma observação é válida? Se assim for, é verdade em todas as versões do Windows? E isso é uma suposição de confiança, ou seja, é que o comportamento em algum lugar documentado?


Contexto: Eu estou lidando com uma situação onde eu estou provocando um aplicativo de terceiros para várias janelas não-modais abertos e eu preciso enviar algumas mensagens de janela para as janelas, uma vez que eles estão abertos, mas eu não tenho certeza-fogo maneira de identificá-los como nem suas classes de janela, nem suas legendas será diferente e eu também não sei suas coordenadas esperados. No entanto, se eu pudesse contar com o comportamento acima de EnumWindows eu poderia simplesmente usar o primeiro identificador retornado por EnumWindows cuja classe e legenda corresponder a minha expectativa. Isso ainda deixa algumas brechas hipotéticos, mas eu acho que vai ser bom o suficiente. sugestões alternativas boas-vindas, no entanto.

Foi útil?

Solução

Ele retorna-los em ordem Z. Primeiro, o indicador de topo-com mais WS_EX_TOPMOST conjunto, até que a janela mais inferior com WS_EX_TOPMOST set, então a janela de mais alto sem WS_EX_TOPMOST, embora a janela o mais inferior sem WS_EX_TOPMOST. Note-se que a visibilidade não é um fator determinante, por isso, uma janela invisível que é maior no Z-order do que uma janela visível ainda vai comparecer.

Editar :

É altamente improvável que você poderia usar isso como quiser, basta dar o primeiro retorno de EnumWindows. Não só é a sua nova janela pouco provável que seja o primeiro retorno, mas você tem uma condição de corrida onde outras janelas poderão ser abertas no mesmo período. Você poderia, no entanto, manter uma lista de todas as janelas conhecidas para a aplicação, e quando você precisa encontrar uma janela, EnumWindows chamada recém-inaugurado e comparar os identificadores de janela para aqueles em sua lista. Quando você encontrar um que tem a classe e legenda correta (você pode até mesmo verificar que pertence ao processo direita com GetWindowThreadProcessID) que é não na sua lista, então você encontrou a nova janela.

Para seus propósitos, porém, você pode ser ainda melhor servido através da instalação de um gancho CBT e assistindo para a notificação HCBT_CREATEWND. Veja MSDN ajuda on SetWindowsHookEx() e o CBTProc callback para obter mais informações.

Nível de certeza sobre a ordem de enumeração :

Uma série de comentários e outras respostas para essa pergunta ter mencionado a falta de documentação precisa no MSDN sobre a ordem em que EnumWindows retorna identificadores de janela. E, de fato, as páginas EnumWindows e o EnumWindowsProc callback ambas bastante silêncio sobre o assunto. Eu ofereço como prova o seguinte:

  1. A C ++ Q & Um artigo na revista MSDN faz Estado especificamente:

    EnumWindows enumera as janelas na ordem Z de cima para baixo

  2. A página sobre EnumChildWindows alude à ordem na seção de observações:

    janela criança Um que é movido ou reposicionado na ordem Z durante o processo de enumeração será adequadamente enumerados.

    Isto implica que a ordem é dependente Z-ordem. E uma vez que, na descrição do hWndParent parâmetro, ele diz o seguinte:

    Se este parâmetro é NULL, esta função é equivalente a EnumWindows.

    pode-se supor que a mesma lógica e ordenação aplica-se a EnumWindows.

  3. Este é o comportamento observável desta função, o que torna uma alteração significativa para alterá-lo. Em geral, a Microsoft tem sido muito bom sobre não fazer alterações significativas no comportamento observável. Isso não é uma garantia, mas é uma aposta bastante segura. Você é mais provável encontrar que na próxima versão da função que você está usando foi reprovada e substituída por outra "Ex" versão do que ao descobrir que seu comportamento observável mudou.

É claro que isto é tudo muito acadêmico, neste ponto, uma vez EnumWindows provavelmente não é a melhor solução para o OP-problema, no mínimo EnumThreadWindows provavelmente seria um melhor ajuste, mas eu pensei que era vale a pena mencionar para outras pessoas que pode se deparar com este post.

Outras dicas

respostas anteriores precisam de refinamento considerável. Enum-order = Z-ordem somente se GetSystemMetrics (SM_IMMENABLED) = 0, ou seja, Input Method Gestor / entrada possui Method Editor estão desativados. Porque todas as janelas classe "IME" (o título "IME padrão") e "MSCTFIME UI" são enumerados depois que a janela "Progman" ( "Program Manager"), -. Ou seja, não em ordem Z

A ordem não é especificado na API ( MSDN ligação ) por isso não é garantido para ser qualquer coisa em particular - se houvesse uma garantia de que ele iria ser explicitamente especificado na API. O que acontece, por exemplo, se uma janela é criada no meio da enumeração - ele ser incluído na enumeração? Isso permite que o gerenciador de janelas a liberdade de mudar a sua implementação deve se tornar mais eficiente de fazê-lo.

No entanto, existe um valor único que pode ser usado para diferenciar entre as janelas - o próprio identificador de janela. No seu método de EnumWindowProc, salvar o identificador de janela para cada janela de correspondência - você precisa de qualquer maneira para enviar mensagens para a janela

.

Se você controla ambos os processos, você pode enviar a partir do primeiro a SendMessage com "HWND_BROADCAST" como primeiro parâmetro.

Em seguida, o outro programa quando receber a msg, pode fazer um SendMessage para suas janelas filho.

Se a documentação não diz nada sobre a ordem de enumeração, eu sugiro fortemente que você fique longe de quaisquer suposições. Um par de posts em blog de Raymond Chen (blogs.msdn.com/oldnewthing) iria revelar quantos aplicativos estão lá que contar com todo este material não documentado / observação, e algo dá errado quando uma nova versão do Windows sai (a menos desenvolvedores MS introduzir mais um calço para mais um aplicativo que se comporta mal).

Como para a sua finalidade, existem várias funções, como GetWindowThreadProcessID, GetParent, EnumThreadWindows e EnumWindows que poderiam ajudá-lo a realizar a tarefa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top