IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

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.


idea L'article Contrôle du clavier et de la souris sous Windows de gRRosminet est une bonne introduction au sous-classement.

Notez dans cet article le chapitre Les différents types de hooks


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.

    // Fichiers d'en-tête Windows :
    #include <windows.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

// TutoCPPRoulette.cpp : définit le point d'entrée pour l'application DLL.
//

#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

// Procédure de gestion des messages
LRESULT CALLBACK  FormSubclassProc(
    HWND hwnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{
	// Appel de la procédure standard de gestion des messages
	return CallWindowProc(gWndProc, hwnd, uMsg, wParam, lParam);	
}

void __stdcall MouseWheelHook(DWORD pHwnd)
{
// Déréférence le formulaire et conserve l'identifiant de la précédédante procédure de gestion des messages
	gWndProc = (WNDPROC)SetWindowLong((HWND)pHwnd, GWL_WNDPROC,  (LONG)FormSubclassProc);
}

void __stdcall MouseWheelUnHook(DWORD pHwnd)
{
// // Réactive la procédure standard de gestion des messages
	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 :

// Procédure de gestion des messages
LRESULT CALLBACK  FormSubclassProc(
    HWND hwnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{
	if (uMsg == WM_MOUSEWHEEL)
	{ MessageBox(hwnd,"test roulette","",MB_OK); }
	// Appel de la procédure standard de gestion des messages
	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 :

// Procédure de gestion des messages
LRESULT CALLBACK  FormSubclassProc(
    HWND hwnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{
	if (uMsg != WM_MOUSEWHEEL)
	{
		// Appel de la procédure standard de gestion des messages
		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

    // Fichiers d'en-tête Windows :
    #include <windows.h>
    // Fichiers d'en-tête Windows :
    #include <windows.h>
    // déclarations pour les maps
    #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.

// Identifiants des procédures de gestion des messages
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 :

Valeur = MapWndProc[Clé]

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)
{
// Test si le sous-classement de ce formulaire est déjà activé
	if (MapWndProc.find((HWND)pHwnd) == MapWndProc.end())
	{ 
        // Déréférence le formulaire et conserve l'identifiant de la précédédante procédure de gestion des messages
    	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)
{
// Test si le sous-classement de ce formulaire est activé
	if (MapWndProc.find((HWND)pHwnd) != MapWndProc.end())
	{
		// Réactive la procédure standard de gestion des messages
			SetWindowLong((HWND) pHwnd, GWL_WNDPROC,(LONG)MapWndProc[(HWND)pHwnd]);
		// Supprime les entrées dans les maps
			MapWndProc.erase((HWND)pHwnd);
	}
}
Idem dans la procédure de gestion des messages FormSubclassProc.

// Procédure de gestion des messages
LRESULT CALLBACK  FormSubclassProc(
    HWND hwnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{
	if (uMsg != WM_MOUSEWHEEL)
	{
		// Appel de la procédure standard de gestion des messages
		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.

 

Valid XHTML 1.1!Valid CSS!

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.