Fenetre dans DLL [Résolu]

Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
- - Dernière réponse : ncoder
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
- 11 déc. 2005 à 13:48
Bonjour à tous,

Dans beaucoup de mes programmes, lorsqu'une opération assez longue est en cours, j'utilise une petite fenètre indicant l'état et la tache en cours d'exécution.

Fatigué d'avoir à chaque fois a retaper les lignes de code pour cette petite fenètre, j'ai voulu mettre tout ce code dans une DLL, en faisant 3 fonctions:
- une pour créer la fenètre (initialiser)
- une pour changer le texte de l'opération en cours
- et une pour changer la valeur de la progressbar.

Ce qui donne ça :

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>


HBRUSH FondStatic= (HBRUSH)(COLOR_WINDOW);
HWND Fen_Sync, Tache, Statut, ProgressBar;

__declspec (dllexport) HWND CreateUserForm ( char *Name, char* szClassName, HINSTANCE hThisInstance, int ID_LABEL)
{
// Calcule la résolution de l'écran
POINT Ecran = {GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)};


// Crée la fenêtre de synchronisation
Fen_Sync = CreateWindowEx(0, &szClassName[0], &Name[0], WS_OVERLAPPED,
(Ecran.x-277)/2, (Ecran.y-105)/2, 277, 105, HWND_DESKTOP, NULL, hThisInstance, NULL);

//Labels
Tache = CreateWindowEx(0, "STATIC", "Tache :", WS_VISIBLE|WS_CHILD, 10, 25, 200, 13, Fen_Sync, (HMENU)ID_LABEL, hThisInstance, NULL);
Statut = CreateWindowEx(0, "STATIC", "Statut :", WS_VISIBLE|WS_CHILD, 10, 40, 200, 13, Fen_Sync, (HMENU)ID_LABEL, hThisInstance, NULL);


//ProgressBar
typedef VOID (CALLBACK* INITCOMMONCONTROLSEX)(VOID);
INITCOMMONCONTROLSEX InitCommonControlsEx;
HINSTANCE hDLL;
hDLL = LoadLibrary("comctl32.dll");
InitCommonControlsEx = (INITCOMMONCONTROLSEX)GetProcAddress(hDLL, "InitCommonControlsEx");

ProgressBar = CreateWindow(PROGRESS_CLASS, NULL,WS_CHILD|WS_VISIBLE,
10, 57, 250, 10, Fen_Sync, NULL, hThisInstance, NULL);
SendMessage(ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,100));
SendMessage(ProgressBar, PBM_SETSTEP, (WPARAM)1, 0);
SendMessage(ProgressBar, PBM_SETPOS, (WPARAM)0, 0);

// Changements des polices
HGDIOBJ PoliceNormale = GetStockObject(DEFAULT_GUI_FONT);
SendMessage(Tache, WM_SETFONT, (WPARAM)PoliceNormale, MAKELPARAM(TRUE, 0));
SendMessage(Statut, WM_SETFONT, (WPARAM)PoliceNormale, MAKELPARAM(TRUE, 0));
ShowWindow(Fen_Sync, 1);
return Fen_Sync;
}


/*
__declspec (dllexport) void ShowForm (char* Name, char* Tache, int Valeur_ProgressBar, int Show)
{
SetWindowText(Fen_Sync, &Name[0]);
SetWindowText(Tache, &Tache[0]);
SendMessage(ProgressBar, PBM_SETPOS, (WPARAM)Valeur_ProgressBar, 0);
ShowWindow(Fen_Sync, Show);
MessageBox(NULL, "ShowForm","Fonction appelée", MB_OK);
}
*/


__declspec (dllexport) void UpdateFormT (char* Tache)
{
SetWindowText(Tache, &Tache[0]);
ShowWindow(Fen_Sync, 1);
UpdateWindow(Fen_Sync);
MessageBox(NULL, "UpdateFormT","Fonction appelée", MB_OK);
}


__declspec (dllexport) void UpdateFormV (int Valeur_ProgressBar)
{
SendMessage(ProgressBar, PBM_SETPOS, (WPARAM)Valeur_ProgressBar, 0);
ShowWindow(Fen_Sync, 1);
UpdateWindow(Fen_Sync);
MessageBox(NULL, "UpdateFormV","Fonction appelée", MB_OK);
}


BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;


case DLL_PROCESS_DETACH:
break;


case DLL_THREAD_ATTACH:
break;


case DLL_THREAD_DETACH:
break;
}


/* Returns TRUE on success, FALSE on failure */
return TRUE;
}

Dev Cpp ne me génère aucune erreur, me crée la lib et la DLL.
Mais qd j'utilise ma DLL, les MsgBox s'affichent bien (donc les fonctions sont appelées),
mais ma fenètre n'apparait pas !!!

Où est le pb ?

Merci à tous.
Afficher la suite 

20/27 réponses

Meilleure réponse
Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
3
Merci
Si tu as du mal, je t'ai fais un exemple avec DevCpp
Télécharges le ZIP à cette adresse.
Je vais essayer de le fignoler un peu avant de le mettre sur CppFrance.Com

Le ZIP contient 2 projets pour DevCpp
- Le projet de la Dll
Contient 1 fonction pour créer la fenêtre, 1 fonction pour la détruire, et 1 fonction pour ajouter une ligne de message.
- Le projet Test
Crée un éxécutable qui teste les 3 fonctions exportées depuis la Dll

Bonne Prog

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 142 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_Xaviou
Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
3
Merci
Bien sûr que si.
2 méthodes possibles :
Lors de la création des labels, tu stockes leur handle dans une variable globale de ta dll
=> SetWindowText(hWndLabel,"Nouveau Texte.");
Sinon, lors de la création des labels, tu leur associes un ID
Par exemple :
#define ID_DU_LABEL 1001
CreateWindow("STATIC","Mon Label",Style,
x,y,width,height,hWndParent,
(HMENU)ID_DU_LABEL,hInstance,0);
Puis tu passes par les fonctions destinées au boites de dialogue, mais qui marchent aussi pour une fenêtre normale:
SetDlgItemText(hWndDlg,ID_DU_LABEL,"Nouveau Texte");

Y'a pas d'raisons qu'ça marche pas !

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 142 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_Xaviou
Messages postés
126
Date d'inscription
jeudi 5 juin 2003
Statut
Membre
Dernière intervention
11 juillet 2006
0
Merci
Bonjour

Essaye de mettre cette ligne de code au debut des fonctions que tu exportes

AFX_MANAGE_STATE(AfxGetStaticModuleState());

par exemple


__declspec (dllexport) void UpdateFormV (int Valeur_ProgressBar)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

SendMessage(ProgressBar, PBM_SETPOS, (WPARAM)Valeur_ProgressBar, 0);
ShowWindow(Fen_Sync, 1);
UpdateWindow(Fen_Sync);
MessageBox(NULL, "UpdateFormV","Fonction appelée", MB_OK);
}

TOCHE
Commenter la réponse de ricky78
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
Merci de ta réponse.

Dev cpp 4.9 me crée ce log :

dllmain.o(.text+0x5b):dllmain.c: undefined reference to `AfxGetStaticModuleState'
dllmain.o(.text+0x64):dllmain.c: undefined reference to `AFX_MANAGE_STATE'

Quel include (ou lib) dois-je ajouter pour empécher cette erreur ?

Merci de ton aide
Commenter la réponse de ncoder
Messages postés
126
Date d'inscription
jeudi 5 juin 2003
Statut
Membre
Dernière intervention
11 juillet 2006
0
Merci
Desole le AfxGetStaticModuleState' est pour les prog utilsant les MFC, cela ne semble pas etre ton cas

TOCHE
Commenter la réponse de ricky78
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
0
Merci
MFC n'était pas précisé et l'include de windows.h l'excluait implkicitement.

Tu n'as pas besoin de RegisterClass() ? ou alors est-il fait ailleurs ?

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
Non je n'ai pas utilisé RegisterClass() !

Comment m'y prendre svp?

Un petit exemple ?

Merci!
Commenter la réponse de ncoder
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
J'ai fait ceci :

WNDCLASSEX wincl; /* Data structure for the windowclass */


/* The Window structure */
wincl.hInstance = gh;
wincl.lpszClassName = "MsgBox";
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);


/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;


/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;

où gh = hInst; (case DLL_PROCESS_ATTACH:)

Mais ça ne marche pas...

Why?
Commenter la réponse de ncoder
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
J'ai oublié : à wincl.lpfnWndProc j'ai mis NULL
Commenter la réponse de ncoder
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
Ca marche toujours pas !!!
Que faire ??
Commenter la réponse de ncoder
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
0
Merci
Pourquoi donc ne mets tu pas toute la logique de la fenêtre dans la dll, le RegisterClass y compris puisque la windProc esr dans la dll.
D'ordinaire ce sont pluto des dialogbox qu'on fournit en dll.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
0
Merci
BruNews a raison : tu devrais mettre toute la gestion de ta fenêtre dans la Dll
Essayes ceci:
Dans ta Dll, tu ajoute une fonction Create()
Cette fonction va créer un thread qui éxécutera une seconde fonction non exportée de la Dll du style:
DWORD WINAPI ThreadFunction(void * param)
{
// Tu mets ici l'initialisation de la WNDCLASSEX
// Tu mets ici la création de ta fenêtre
// Tu mets ici la pompe à messages classique
return TaValeurIndiquantQueToutC'estBienPassé;
}

Il te suffit ensuite d'envoyer un PostQuitMessage(...) depuis une fonction "Terminate()" de ta Dll, et le tour est joué.

Par contre, comme le dit BruNews, tu devrais essayer d'utiliser une DialogBox, qui sera plus facile à gérer dans ton cas.
Commenter la réponse de cs_Xaviou
Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
0
Merci
Je crois que j'ai trouvé quelque chose qui peut également empêcher l'affichage de ta fenêtre:

Tu initialises ta variable InitCommonControlsEx avec l'adresse de la fonction obtenue par GetProcAddress (...), mais tu ne l'appelles pas, ce qui est impératif pour pouvoir afficher ne ProgressBar.

En tout cas, je sais que dans le cas d'une DialogBox contenant un CommonControl, elle ne s'affiche pas si il n'y a pas eu d'appel de InitCommonControls();
Commenter la réponse de cs_Xaviou
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
220 Xaviou == > je fais de cette manière pour toutes mes progressbar car sinon dev me dit que InitCommonControlsEx() n'existe pas, et alors là ça marche.

BruNews ==> "Pourquoi donc ne mets tu pas toute la logique de la fenêtre dans la dll, le RegisterClass y compris puisque la windProc esr dans la dll."

Peux tu dévellopper car je ne vois pas très bien ce que tu veux dire stp...

Je vais essayer avec le thread
Commenter la réponse de ncoder
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
Ca marche toujours pas !!

Vous avez pas un exemple de source où des fenètre sont dans des DLL svp ??

J'y arrive pas !!!

Merci...
Commenter la réponse de ncoder
Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
0
Merci
J'avais bien compris que tu avais écrit ça à cause d'une erreur dans DevCpp.
Le problème n'est pas dans la façon, mais tu oublies de faire un appel à InitCommonControlsEx:
De plus, cette fonction prend en paramètre un pointeur vers une structure INITCOMMONCONTROLSEX, que tu redéfinis.

Essayes plutôt avec la fonction InitCommonControls()

typedef VOID (CALLBACK* MYINITCOMMONCONTROLS)(VOID);
MYINITCOMMONCONTROLS MyInitCommonControls;
HINSTANCE hDLL;
hDLL = LoadLibrary("comctl32.dll");
MyInitCommonControls = (MYINITCOMMONCONTROLS)GetProcAddress(hDLL, " InitCommonControls ");
if (MyInitCommonControls ==NULL)
{
MessageBox(GetActiveWindow(),"Erreur d'initialisation.","Erreur",MB_ICONERROR);
return 0;
}
MyInitCommonControls(); //Il faut faire appel à la fonction au moins une fois

Bonne chance, et tiens nous au courant...
Commenter la réponse de cs_Xaviou
Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
0
Merci
Petite précision :

Si tu veux ne plus avoir de message d'erreur lors de l'utilisation de InitCommonControlsEx avec DevCpp, ajoutes
#define _WIN32_IE 0x0300 avant #include <commctrl.h>

ça vient du fait qu'elle est définit comme suit dans le fichier commctrl.h:
#if (_WIN32_IE >= 0x0300)
BOOL WINAPI InitCommonControlsEx(LPINITCOMMONCONTROLSEX);
#endif

Mais je persiste en t'affirmant que InitCommonControls() suffit. (et en plus, tu n'a pas besoin d'utiliser tout le code que je t'ai marqué dans le message précédent, car cette fonction devrait marcher sans problème (elle est définie sans compilation conditionnelle)
Commenter la réponse de cs_Xaviou
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
0
Merci
InitCommonControls suffit tout à fait, le version Ex mange seulement un peu moins de ressources mais c'est pas vraiment grand chose.
Prends l'habitude de mettre carrément
#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0501
#include <windows.h>
au début de tes progs et finis les ennuis, au moins jusque Win Server 2003.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Commenter la réponse de BruNews
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
Merci à vous deux je teste les changements !
Commenter la réponse de ncoder
Messages postés
244
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
6 avril 2008
1
0
Merci
Ca ne marche toujours pas !

Mais je n'ai plus besoin de charger InitCommonControls depuis la DLL comme je le faisait auparavant.

Mais sinon, le fenêtre n'apparait toujours pas !

D'autres idées ?

Merci beaucoup car je désespère !
Commenter la réponse de ncoder