Je vais répondre à cela d'un point de vue purement CWin32, parce que je ne connais pas Delphi ou ses bibliothèques. Convertir ceci en C# peut être accompli via p/invoke, mais certaines parties peuvent/devront être non gérées.
Tout d'abord, aucune garantie. Si l'application cible effectue des contrôles sans fenêtres (s'il n'y a pas de HWND
sous chaque contrôle à l'écran), vous n'avez pas vraiment de chance. Ce n'est pas si rare, alors oui ...
Étape 1, inscrivez-vous un crochet de fenêtre d'écoute pour les nouvelles fenêtres créées par le processus cible *:
//dllHMod is an HMODULE that refers to the DLL containing ShellHookProc
HHOOK hook = SetWindowsHookEx(WH_SHELL, ShellHookProc, dllHMod, 0);
// error handling, stashing hook away for unregistering later, etc...
LRESULT CALLBACK ShellHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0) return CallNextHookEx(NULL, nCode, wParam, lParam);
if(nCode == HSHELL_WINDOWCREATED)
{
WindowCreate((HWND)wParam);
}
return 0;
}
WindowCreated(HWND)
devrait planquer HWND si le processus correct (déterminé par GetWindowThreadProcessId
) le possède. À ce stade, vous serez en mesure d'obtenir toutes les fenêtres de niveau supérieur appartenant au processus cible. Notez que l'enregistrement d'un hook global entraîne une pénalité de performance notable, pas que cela ait vraiment de l'importance dans votre cas, mais vous devriez vous y attendre.
Maintenant, pour la partie amusante. Il n'y a pas de moyen fiable de savoir quand une fenêtre est entièrement construite, ou quand elle est terminée (il y a des façons de dire quand elle commence le rendu, mais cela n'aide pas vraiment). Mon conseil, devinez. Lancez simplement une attente arbitraire et essayez d'énumérer toutes les fenêtres enfants.
Enumérer les fenêtres enfants (si vous en savez assez sur la fenêtre cible, il y a de meilleures façons de le faire, mais je suppose une recherche est plus facile):
//targetHWND is an HWND of one of the top-level windows you've found
EnumChildWindows(targetHWND, ChildWindowCallback, NULL);
//more code...
BOOL ChildWindowCallback(HWND window, LPARAM ignored)
{
if(IsTargetWindow(window)) { /* Do something */ }
return TRUE;
}
La mise en œuvre IsTargetWindow
est une autre partie délicate .J'espère que vous trouverez un test fiable pour ce faire (comme vérifier le nom de la classe, le nom de la fenêtre, le style, quelque chose, regardez GetWindowInfo
). Une fois que vous avez la fenêtre que vous voulez surveiller, vous pouvez utiliser SetWindowLongPtr
et GWLP_WNDPROC
pour voir tous les messages qu'il reçoit. Cela nécessitera l'injection de code (et donc le code non géré) et est terriblement bas niveau. Je vous le déconseille si vous pourriez l'éviter, mais manque la source ...
Je pense que cela répond à un point de départ décent, mais encore une fois cela va être incroyablement douloureux si son même possible du tout. Bonne chance. * Si vous savez que l'application cible ne crée pas de fenêtres, sauf au démarrage (ou à des moments détectables/prévisibles dans le temps), vous pouvez utiliser EnumWindows
.
Ouf. Cela fait cinq ans que je n'ai pas développé de logiciel en Delphi, donc je ne suis pas complètement qualifié pour répondre, mais cela semble tout à fait impossible quand la seule chose que vous avez est le binaire. Et je ne veux pas être jubilatoire ou être un smartass, mais des choses comme ça sont des arguments pour l'Open Source - si ce n'est pas ouvert au public, alors au moins ouvert au client payant. –
Dans quelle langue évoluez-vous? –