Programmation de librairies dll win32
pour Access avec Visual C++ Express
Date de publication : 24/11/06 , Date de mise à jour : 24/11/06
VI. Sous-classement / Hook
VII. Exemples
VI-A. Bloquer la roulette de la souris dans un formulaire
VI-A-1. Introduction
VI-A-2. Création du projet
VI-A-3. Sous-classement d'un formulaire
VI-A-4. Annuler le message envoyé par la roulette
VI-A-5. Utilisation de la librairie pour plusieurs formulaires simultanément
VI-A-6. Utiliser la roulette pour faire défiler le formulaire de haut en bas.
VI. Sous-classement / Hook
Nous allons dans les exemples qui suivent utiliser des sous-classements, également appelés Hook en anglais.
Le principe du sous-classement est simple : détourner les messages vers une fonction spécifique.
On peut ensuite :
- modifier le message avant de l'envoyer au gestionnaire de messsages standard;
- effectuer des actions supplémentaires avant ou après le traitement du message;
- ne pas envoyer le message vers le gestionnaire de messages standard, pour annuler un événement.
VII. Exemples
VI-A. Bloquer la roulette de la souris dans un formulaire
VI-A-1. Introduction
Vous trouverez la librairie compilée et le tutoriel d'utilisation ici :
Gestion de la roulette de la souris dans les formulaires (dll sans référencement)
Dans ce chapitre nous allons programmez cette librairie étape par étape :
1 - Sous-classement d'un formulaire;
2 - Annuler le message envoyé par la roulette de la souris;
3 - Utilisation de la librairie pour plusieurs formulaires simultanément;
3 - Aller plus loin en utilisant la roulette pour faire défiler le formulaire de haut en bas.
VI-A-2. Création du projet
Créez un nouveau projet en suivant les sections
Créer un nouveau projet et
Configurer le projet.
Pour la suite, cette librairie est nommée
TutoCPPRoulette.
On ajoute tout de suite la déclaration du fichier d'en-tête Windows dans le fichier
stdafx.h.
Ce fichier contient les déclarations des APIs et constantes communément utilisées.
VI-A-3. Sous-classement d'un formulaire
Le sous-classement d'un formulaire (donc d'un fenêtre Windows) s'effectue à l'aide de la fonction SetWindowLong
L'identifiant GWL_WNDPROC demande le changement de procédure de traitement des messages pour la fenêtre concernée.
La fonction SetWindowLong nous renvoit l'identifiant de la procédure standard de traitement des messages.
Il est indispensable de conserver cet identifiant : en effet tous les messages ne seront pas gérés par notre procédure.
Il faut donc rediriger les messages vers la procédure standard pour permettre aux messages d'être traités normalement.
Code du fichier TutoCPPRoulette.cpp pour sous-classement d'un formulaire |
# include "stdafx.h"
WNDPROC gWndProc;
# ifdef _MANAGED
# pragma managed ( push , off )
# endif
BOOL APIENTRY DllMain ( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
# ifdef _MANAGED
# pragma managed ( pop )
# endif
LRESULT CALLBACK FormSubclassProc (
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return CallWindowProc (gWndProc, hwnd, uMsg, wParam, lParam);
}
void __stdcall MouseWheelHook (DWORD pHwnd)
{
gWndProc = (WNDPROC)SetWindowLong ((HWND)pHwnd, GWL_WNDPROC, (LONG)FormSubclassProc);
}
void __stdcall MouseWheelUnHook (DWORD pHwnd)
{
SetWindowLong ((HWND) pHwnd, GWL_WNDPROC,(LONG)gWndProc);
}
|
La fonction
MouseWheelHook pourra être appelée depuis Access VBA pour mettre en place le sous-classement.
La fonction
MouseWheelUnHook annule le sous-classement.
Suivre la section
Ajouter une procédure à la librairie pour créer le fichier de définition.
Fichier TutoCPPRoulette.def |
LIBRARY TutoCPPRoulette
EXPORTS
MouseWheelHook @1
MouseWheelUnHook @2
|
Il faut ensuite demander au compilateur d'utiliser ce fichier de définition.
Dans les propriétés du projet :
Propriétés de configuration : Editeur de liens : Entrée.
Fichier de définition de module : TutoCPPRoulette.def
L'identifiant de la procédure standard de gestion des messages est stocké dans la variable gWndProc.
Il est ensuite utilisé en paramètre de la fonction CallWindowProc pour transmettre les messages à traiter.
Où en est-on?
Après appel de la fonction MouseWheelHook depuis Access VBA, lorsque le formulaire reçoit un message, celui-ci est envoyé
à notre procédure FormSubclassProc.
Dans cette procédure la fonction CallWindowProc renvoit le message vers la procédure standard qui traite alors le message.
Comment s'assurer alors que le sous-classement fonctionne?
Ajoutons une boîte de message lors de l'utilisation de la roulette.
La procédure de gestion des messages devient : |
LRESULT CALLBACK FormSubclassProc (
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
if (uMsg = = WM_MOUSEWHEEL)
{ MessageBox (hwnd," test roulette " ," " ,MB_OK); }
return CallWindowProc (gWndProc, hwnd, uMsg, wParam, lParam);
}
|
WM_MOUSEWHEEL est l'identifiant du message envoyé lors de l'action sur la roulette de la souris.
Si le message reçu correspond à un roulement de la souris, on affiche une boîte de message "Test roulette".
Pour tester la librairie, créez un formulaire puis placez ce code dans son module de code :
Code à écrire dans le module du formulaire |
Option Compare Database
Option Explicit
Private Declare Sub MouseWheelHook _
Lib " E:\Transfert_doc\Programmation\VCExpress\Tutoriels\TutoCPPRoulette\release\TutoCPPRoulette.dll " _
(ByVal pHwnd As Long)
Private Declare Sub MouseWheelUnHook _
Lib " E:\Transfert_doc\Programmation\VCExpress\Tutoriels\TutoCPPRoulette\release\TutoCPPRoulette.dll " _
(ByVal pHwnd As Long)
Private Sub Form_Load ()
MouseWheelHook Me. Hwnd
End Sub
Private Sub Form_Unload (Cancel As Integer)
MouseWheelUnHook Me. Hwnd
End Sub
|
Utilisez le chemin où est stocké votre librairie ou utilisez
LoadLibrary.
Voir
Exécuter la procédure à partir d'Access pour plus d'infos.
Si tout fonctionne correctement, vous devez voir apparaître une boîte de message lors de l'utilisation de la roulette de la souris.
VI-A-4. Annuler le message envoyé par la roulette
Pour annuler le message envoyée par la roulette de la souris, il suffit de ne pas envoyer ce message
à la procédure standard de gestino des messages.
La procédure de gestion des messages devient : |
LRESULT CALLBACK FormSubclassProc (
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
if (uMsg ! = WM_MOUSEWHEEL)
{
return CallWindowProc (gWndProc, hwnd, uMsg, wParam, lParam);
}
}
|
Tester le nouveau code dans Access en créant un formulaire basé sur une tabe.
Par défaut, la roulette fait défiler les enregistrements.
Si on ajoute le précédent code VBA au formulaire, le défilement des enregistrements est annulé.
VI-A-5. Utilisation de la librairie pour plusieurs formulaires simultanément
Le code de la librairie n'est pas prévu pour gérer le blocage de la roulette sur plusieurs formulaires.
Pour pouvoir gérer plusieurs formulaires, il faut conserver les identifiants des procédures standards de gestion
des messages de chacun des fomulaires.
Pour stocker ces identifiants et pouvoir facilement les relire, on utilise une map.
Cette map est plus ou moins équivalente à une collection en VBA.
Pour utiliser les maps, on doit ajouter les déclarations nécessaires dans le fichier stdafx.h.
Ajouter les déclarations pour les maps à la suite de la déclaration du fichier d'en-tête Windows |
# include <windows.h>
# include <windows.h>
# include <map>
using namespace std;
|
La procédure de gestion des messages était stockée dans la variable gWndProc.
On remplace la déclaration de cette variable par la déclaration d'une map, que l'on peut assimiler à un tableau
d'identifiants.
map< HWND, WNDPROC> MapWndProc;
|
Le premier paramètre de la map est de type HWND, c'est l'identifiant du formulaire.
Ce premier paramètre est la clé de la map qui sert à distinguer chaque entrée du tableau.
Le deuxième paramètre de la map est de type WNDPROC, c'est l'identifiant de la procédure standard
de gestion des messages du fomulaire.
Ce deuxième paramètre est la valeur de la map.
Pour obtenir la valeur d'une entrée en fonction de sa clé on utilise la syntaxe :
Dans la procédure MouseWheelHook, au lieu de stocker le retour de l'API SetWindowLong
dans la variable gWndProc, on va le stocker dans la map MapWndProc.
Au préalable on utilise la méthode find de la map pour rechercher si l'identifiant du
formulaire est déjà dans la map.
void __stdcall MouseWheelHook (DWORD pHwnd)
{
if (MapWndProc.find ((HWND)pHwnd) = = MapWndProc.end ())
{
MapWndProc[(HWND)pHwnd] = (WNDPROC)SetWindowLong ((HWND)pHwnd, GWL_WNDPROC, (LONG)FormSubclassProc);
}
}
|
(HWND)pHwnd est l'identifiant du formulaire sous-classé.
Dans la procédure MouseWheelUnHook, on doit rechercher l'identifiant de procédure correspondant
à l'identifiant de formulaire passé en paramètre.
Une fois le sous-classement annulé, on peut supprimer l'entrée correspondante dans la map.
void __stdcall MouseWheelUnHook (DWORD pHwnd)
{
if (MapWndProc.find ((HWND)pHwnd) ! = MapWndProc.end ())
{
SetWindowLong ((HWND) pHwnd, GWL_WNDPROC,(LONG)MapWndProc[(HWND)pHwnd]);
MapWndProc.erase ((HWND)pHwnd);
}
}
|
Idem dans la procédure de gestion des messages FormSubclassProc.
LRESULT CALLBACK FormSubclassProc (
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
if (uMsg ! = WM_MOUSEWHEEL)
{
return CallWindowProc (MapWndProc[(HWND)hwnd], hwnd, uMsg, wParam, lParam);
}
}
|
On peut maintenant utiliser la même librairie pour plusieurs formulaires.
VI-A-6. Utiliser la roulette pour faire défiler le formulaire de haut en bas.
Les sources présentées sur cette page sont libres de droits
et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation
constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ©
Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être
faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.