[winapi] Listowanie aktualnie otwartych i widocznych okien

0

Chcę napisać listę, mającą taki format: [uchwyt][spacja, myślnik, spacja][tytuł okna]. Ma ona dotyczyć tylko okien widocznych dla użytkownika - czyli nie chcę listować okien niewidocznych, bo tych jest naprawdę sporo, a mnie one kompletnie nie interesują.

Napisałem sobie taki kod(oczywiście wspomagając się msdn'em):

#include <windows.h>
#include <iostream>

BOOL CALLBACK MyEnumProc(HWND hWnd, LPARAM lParam);
void Dzialaj(void);

void Dzialaj(void)
{
	EnumWindows(&MyEnumProc, 0);
}

BOOL CALLBACK MyEnumProc(HWND hWnd, LPARAM lParam)
{
	if (IsWindowVisible(hWnd)!=false){return true;}
	std::cout << hWnd << " - ";
	char tytul[500];
	GetWindowText(hWnd, (LPWSTR)tytul, 250);
	std::cout << tytul << std::endl;
	// zeby kontynuowac enumeracje zwracamy true, zeby przerwac false:
	// w tym wypadku ciagle zwracam true, wiec przerwie sie dopiero wtedy kiedy funkcja EnumProcess dotrze do ostatniego okna
	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	Dzialaj();
	system("PAUSE");
	return 0;
}

Czyli niby odrzucam okna niewidzialne. Z MSDN wynika, że funkcja EnumWindows nie powinna mi listować okien-dzieci (czyli np. buttonów). Efekt działania programu jest taki, że aplikacja wypisuje masę uchwytów, oczywiście później spację, myślnik i kolejną spację, ale w miejscu gdzie powinien być tytuł dostaję jedną literkę albo kompletnie nic.

Wypisywanych uchwytów jest z całą pewnością więcej niż aktualnie otwartych okien. Co robię nie tak?

PS.
Wiem, że system("PAUSE"); to zło w czystej postaci, tutaj tylko tak na szybko napisałem, na razie chcę żeby program działał, później zrobię refactoring kodu :)

0

Wydaje mi się, że nie można pobrać tekstu przez GetWindowText z okna, które zrobił inny proces, w takiej sytuacji należy użyć SendMessage i komunikatu WM_GETTEXT. Wtedy przynajmniej poznasz tytuły tych wszystkich okien. No i masz odwrotny warunek - teraz listujesz okna niewidzialne, nie wiem czy o to chodzi (z opisu wynika, że nie).

0
Fanael napisał(a)

No i masz odwrotny warunek - teraz listujesz okna niewidzialne, nie wiem czy o to chodzi (z opisu wynika, że nie).

Dzięki, to dużo dało, teraz mam listowanie odpowiedniej liczby okien.

Fanael napisał(a)

Wydaje mi się, że nie można pobrać tekstu przez GetWindowText z okna, które zrobił inny proces, w takiej sytuacji należy użyć SendMessage i komunikatu WM_GETTEXT. Wtedy przynajmniej poznasz tytuły tych wszystkich okien.

Teraz użyłem mocy debuggera MSVC++ 2008 i ustaliłem co następuje:

  • można ustalić tytuły zewnętrznych okien przez GetWindowText - dlaczego u mnie następuje problem opisane poniżej
  • w tablicy tytul po tym całym magicznym rzutowaniu zamiast np. napisu start jest coś takiego [s][bajt zerowy][t][bajt zerowy]... A jak wiadomo funkcja wypisująca mi na ekran tablicę charów po natrafieniu na bajt zerowy przestaje mi wypisywać moją tablicę. Stąd brało się to, że otrzymywałem tylko jedną literkę.

Pytanie brzmi: jak to poprawnie rzutować, żeby w tablicy tytul nie było bajtu zerowego po każdej literze?

0

Po zmianie
GetWindowText(hWnd, (LPWSTR)tytul, 250);
na
GetWindowText(hWnd, (LPSTR)tytul, 250);
u mnie działa poprawnie. Wydaje mi się, że to kwestia Unicodu.

0

Użyj funkcji GetWindowTextA - przy domyślnych ustawieniach Visuala włączony jest unikod, przez co GetWindowText rozwijane jest do GetWindowTextW, czyli wersji unikodowej - a ty zapisujesz do tablicy char, czyli chcesz wersję ASCII, z literką A na końcu - GetWindowTextA.

0

Obie rady równie dobrze ratują mnie z opresji. Nie powiem z której skorzystałem :) Dziękuję pięknie za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1