Programmation Windev...

Bon, comme je n'ai plus les mots de passe pour accéder à mon ( vieux ) site perso www.kerovnia.fr.st, je vais placer les informations à propos de la programmation Windev et particulièrement à propos de la gestion du WinPopup depuis un programme Windev.
Programmation d'un WinPopup

Le probleme de l'utilisation de messages de type WinPopup est que le programme sous Windows 9x permet d'envoyer et recevoir, mais que sous Windows NT/2K et XP, on ne peut que recevoir et il faut utiliser la commande NET SEND pour envoyer ( et la fonction SEND n'est pas implémentée dans la version de windows 9x ). Donc, il faut chercher comment ca fontionne le WinPopup et le développer sous windev pour l'intégrer dans un progiciel par exemple ( tout les exemples sont écrits en 32 bits ).

1. Principe de fonctionnement

WinPopup utilise un fichier qui est créé sur le réseau. Ce fichier est un MailSlot et possède ses propres fonctions API pour être géré. Quand on lance WinPopup, un fichier "\\NOMPOSTE\MailSlot\messng" est créé sur le réseau, ce fichier est un flux de donnée et ne peut pas être vu par un explorateur. Il suffit donc d'écrire dans ce fichier pour envoyer du texte à un poste.

2. Fonctions API pour gérer les MailSlot

a. Créer le MailSlot.

Nous utiliserons la fonction CreateMailslotA qui renvoie un handle qui sera utilisé dans les fonctions de lecture du MailSlot.

HANDLE CreateMailslotA(
LPCTSTR lpName, // pointeur vers la chaine contenant le nom du 'fichier' MailSlot
DWORD nMaxMessageSize, // Taille maxi d'un message
DWORD lReadTimeout, // nb de milliseconde avant TimeOut sur la lecture
LPSECURITY_ATTRIBUTES lpSecurityAttributes // pointer vers un objet de sécurité
);

En W-Langage, cela donne ca :

// Attention, il faut que hMailSlot soit connu dans tout le programme, le handle est détruit à la sortie de l'objet qu'il l'a initialisé !
GLOBAL
// Handle du mailslot ( c'est un fichier !!! )
hMailSlot est un entier long

// Nom du mail slot ( c'est encore un fichier )
chServeurMailSlot est une chaine = "\\.\mailslot\SBPopup"

// Parametres divers ( utilisés surtout pour ce programme de test )
MaxMessageSize,NextSize,Waiting,ReadTimeOut sont des entiers longs

MaxMessageSize=100 // octets

hMailSlot=appeldll32("kernel32","CreateMailslotA",&chServeurMailslot,MaxMessageSize,MAILSLOT_WAIT_FOREVER,null)

Voila, votre MailSlot est créé localement ( \\. ) et il se nomme SBPopup. La partie \\.\mailslot\ est impérative et ne peut pas être modifiée !

2. Envoyer un message à un autre MailSlot

Pour envoyer un message à un autre MailSlot, rien de plus simple. Nous avons besoin des fonctions CreateFileA et WriteFile dont voici les spécifications :

HANDLE CreateFile(

LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);

BOOL WriteFile(

HANDLE hFile, // handle to file to write to
LPCVOID lpBuffer, // pointer to data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
);

Donc, nous allons Ouvrir un fichier ( CreateFileA ) en ecriture avec un partage lecture et écrire ( WriteFile ) les données que l'on veut envoyer dans ce fichier. Une fois que l'on a terminé, on ferme ( CloseHandle ) le fichier ( c'est automatiquement réalisé par windows, mais c'est plus propre de le faire soi-même ).

En W-Langage, cela donne ca :

Fic est un entier long
chServeurPOPUP est une chaine = "\\DESTINATAIRE\mailslot\SBpopup"
txtMessage est une chaine = "0123456798"
byteswritten est un entier long

// Ouverture du mailslot ( fichier ) en ecriture
fic=appeldll32("kernel32","CreateFileA",&chServeurPOPUP,GENERIC_WRITE,FILE_SHARE_READ,null,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,-1)

// Envoi du texte 0123456798, pour le test
appeldll32("kernel32","WriteFile",fic,&txtMessage,10,&byteswritten,null)

// On ferme le fichier
appeldll32("kernel32","CloseHandle",fic)

3. Bin, comment qu'on lit ?

Il suffit de lire dans notre fichier MailSlot ( qui a été initialisé plus haut ). Pour cela, on utlise la fonction GetMailslotInfo qui nous indique le nombre de messages dans la file d'attente et évidement ReadFile pour lire le prochain message.

BOOL GetMailslotInfo(

HANDLE hMailslot, // mailslot handle
LPDWORD lpMaxMessageSize, // address of maximum message size
LPDWORD lpNextSize, // address of size of next message
LPDWORD lpMessageCount, // address of number of messages
LPDWORD lpReadTimeout // address of read time-out
);

BOOL ReadFile(

HANDLE hFile, // handle of file to read
LPVOID lpBuffer, // address of buffer that receives data
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // address of number of bytes read
LPOVERLAPPED lpOverlapped // address of structure for data
);

 

Donc, pour la lecture, on va utiliser un timer par exemple.

Voici le code en W-Langage pour lire le MailSlot :

txtMessage est une chaine fixe sur 100
nbOctetsLus est un entier long
retAppelDLL est un entier long

// Récupération de l'état du mailslot
// en particulier :
// NextSize = taille du prochain message
// Waiting = nombre de messages dans la file d'attente
appeldll32("kernel32","GetMailslotInfo",hMailSlot,&MaxMessageSize,&NextSize,&Waiting,&ReadTimeOut)

// Si il y a un message a lire ... bin on le lit !!!
si Waiting<>0 alors
  // Lecture dans le mailslot
  retAppelDLL=AppelDLL32("kernel32","ReadFile" , hMailSlot , &txtMessage , NextSize , &nbOctetsLus , null )
   // Le texte est contenu dans txtMessage
FIN

ANNEXES :

Dans les portions de code, j'ai omis les tests systématiques de vérifications ( lecture, ecriture, initialisation des handles, etc... ) a des fins de clarté. n'oubliez pas de tuer le handle du mailslot créé ( avec CloseHandle ).

De plus, il voici les constantes utilisées dans les exemples :
//Dans le code init du projet
constant
  GENERIC_WRITE = 0x40000000
  FILE_SHARE_READ = 0x1
  OPEN_EXISTING = 0x3
  FILE_ATTRIBUTE_NORMAL = 0x80
  MAILSLOT_WAIT_FOREVER = 0xFFFFFFFF
fin

WinPopup envoie les messages au MailSlot 'messngr' ( \\POSTE\mailslot\messngr ). Ce message est formatté comme suit : EXPEDITEUR + NULL + DESTINATAIRE + NULL + TEXT DU MESSAGE + NULL

Vous pouvez envoyer tout ce que vous voulez dans le MailSlot... On peut même piloter un programme a distance comme ca, en envoyant des sequences d'échappement ( genre ESC+"INDEX"+TAB+Liste des fichiers .... )

Je n'ai pas créé de Classe pour gérer le MailSlot car on ne peux pas faire d'appels API, evenements ou autre Timers dans les constructeurs... Il n'y a plus vraiment d'interet à utiliser un Objet si il ne s'initialise pas tout seul :(

SOURCES :

Merci ( thanks to ) Martin Djernaes ( www.djernaes.dk/martin/winpopup.html ) pour l'explication du fonctionnement du WinPopup

Liste des fonctions API Windows depuis l'aide de Windev pour les syntaxes des fonctions 32 bits

Fichier aide contenant la liste complete des API windows.

Ecrivez-moi si vous avez des problèmes kerovnia@brsystem.com