Mer 31/07/2013 - Presse-papier

Xavier
Administrateur du site
Messages : 817
Enregistré le : mer. 22 juin 2011 18:25

Mer 31/07/2013 - Presse-papier

Message non lu par Xavier »

Presse-papier


L'outil Copier-coller étant plus dépendant de Windows que les autres, ses spécifications seront affinées en fonction de ce qu'il est possible de faire, et il y a donc d'abord une phase de R&D.

La première étape est de recevoir les notifications de changement du presse-papier de Windows. Il y a plusieurs méthodes décrites ici, mais c'est celle du Clipboard Viewer qui a été choisie afin de rester compatible avec Windows XP. Cette méthode est d'ailleurs assez étrange car basée sur une coopération des programmes, Windows ne "discutant" qu'avec le premier de la liste, et chacun devant propager les messages aux autres programmes via une chaîne.

Cette méthode vient d'être implémentée dans XT4 grâce à un exemple simple. La Console intercepte bien les [Ctrl+C] faits dans d'autres applications. La récupération et l'utilisation de ces données seront traitées plus tard. Par contre, l'inscription dans la liste prend une bonne demi-seconde au démarrage d'XT4, sans doute à cause des délais donnés par Windows aux applications pour répondre aux SendMessage. Il faudra sans doute confier cette tâche à un thread séparé. (Il a de toute façon été prévu d'implémenter un système de création de threads à la volée, afin d'effectuer certaines actions en tâche de fond, comme les sauvegardes automatiques.)
Xavier
Administrateur du site
Messages : 817
Enregistré le : mer. 22 juin 2011 18:25

Mer 31/07/2013 - Presse-papier

Message non lu par Xavier »

Presse-papier


En supposant qu'une liste de programme à monitorer ait été paramétrée, il faudra vérifier que la fenêtre active est celle d'un des programmes listés avant de récupérer le contenu du presse-papier.

D'après les forums abordant ce sujet, il faut passer par ces étapes :
  • Récupérer le Handle de la fenêtre active via GetForegroundWindow, ça marche.
  • Récupérer le PID (Process ID) de cette fenêtre via GetWindowThreadProcessId, ça marche aussi, et les PIDs récupérés correspondent à ceux visibles dans le TaskManager de Windows.
  • Récupérer le Handle du process à partir du PID via OpenProcess, et là ça ne marche pas : le Handle retourné est le même pour toutes les fenêtres bien que la fonction ne renvoie pas de message d'erreur.
  • Récupérer le noms de l’exécutable à partir du Handle de process via GetModuleFileName, lequel échoue logiquement en disant que le Handle passé est faux.
Il serait possible de récupérer le nom de l'exécutable de la fenêtre active via l’utilisation de la commande DOS TaskList et d'en récupérer le résultat via un fichier temporaire mais comme on arrive à des solutions vraiment dégradées le sujet va être mis en pause afin qu'il décante un peu.

Code : Tout sélectionner

C:\>tasklist /FI "PID eq 3260"

Nom de l'image                 PID Nom de la sessio Numéro de s Utilisation
========================= ======== ================ =========== ============
XTools.exe                    3260 Console                    1    14 076 Ko
Xavier
Administrateur du site
Messages : 817
Enregistré le : mer. 22 juin 2011 18:25

Mer 31/07/2013 - Autres R&D

Message non lu par Xavier »

Autres R&D


Comme prévu, Delphi ne permet pas de créer un menu contextuel sur un élément d'un autre menu contextuel déjà affiché comme c'est possible dans certaines applications récentes. Si le besoin avait été critique, il aurait fallu surcharger la classe des menus mais on s'en passera, ce qui rendra d'ailleurs le menu totalement compatible avec une utilisation au clavier. ;)


Quant au dernier point à étudier, la récupération de la position du curseur dans une autre application, ça vient de fonctionner grâce à une sorte de prise de contrôle temporaire du thread de la fenêtre active (c'est du code trouvé sur un forum VB et adapté à Delphi):

Code : Tout sélectionner

		// Position du curseur
		XTools_ThreadID := GetCurrentThreadId();
		Active_Window := GetForegroundWindow;
		Active_ThreadID := GetWindowThreadProcessId(Active_Window, Nil);
		if	Active_ThreadID <> XTools_ThreadID
		then	if	AttachThreadInput(XTools_ThreadID, Active_ThreadID, True)
			then	begin
				GetCaretPos(Caret_Position);
				ClientToScreen(Active_Window, Caret_Position);
				AttachThreadInput(XTools_ThreadID, Active_ThreadID, False);
				end;
Cela permettra d'afficher le menu contextuel à l'emplacement du curseur et non plus à celui de la souris, qui peut avoir été mise de côté...


Demain on tentera à nouveau de détecter le nom de l'exécutable de la fenêtre active. Sinon il faudra trouver une solution de contournement.
Répondre