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 

7/27 réponses

Messages postés
154
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
2 octobre 2009
0
Merci
Essayes avec ça:
Dans ta DLL:

DWORD thID;

DWORD WINAPI ThreadFunction(LPVOID lPar)
{
WNDCLASSEX wcex;
wcex.hInstance=GetModuleHandle(NULL);
wcex.lpfnWndProc= Nom d'une fonction WndProc dans la Dll pour gérer la fenêtre
wcex.lpszClassName="DbgWnd_Class";
....
RegisterClassEx(&wcex);
HWND hWnd=CreateWindow(
"DbgWnd_Class","Messages...",WS_VISIBLE,
CW_USEDEFAULT,0,400,200,HWND_DESKTOP,NULL,GetModuleHandle(NULL),0);

// Ajoutes tes contrôles ici...

ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);

// On met ensuite une pompe à messages
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (FlgStop==true) // FlgStop est un booléen qui te permettra de stopper le thread
{
FlgStop=false;
DestroyWindow(hWnd);
}
}
return 0; // renvoie ce que tu veux...

}

extern "C" __declspec(dllexport) int CreateDebugWindow()
{
hThread=CreateThread(NULL,0,MainFuntion,NULL,0,&thID);
// Vérifies si tout c'est bien passé
return 1;
}
extern "C" __declspec(dllexport) int StopDebugWindow()
{
FlgStop=true;
// On boucle jusqu'à ce que la variable FlgStop ait été remise à false
// par la pompe à messages de ThreadFunction
while(
FlgStop
);
return 1;
}

// Tu peux ajouter une fonction exportée pour afficher des messages dans ta fenêtres

Puis, dans ton Prog, tu ajoutes ceci pour créer ta fenêtre:

typedef int (WINAPI *CREATE_FUNCTION)(void);
HMODULE Handle=LoadLibrary(MaDll.dll");
if (Handle==NULL) => Erreur
CREATE_FUNCTION MyCreateFunction=GetProcAddress(Handle,"CreateDebugWindow");
if (MyCreateFunction==NULL) => Erreur
// Créer la fenêtre
MyCreateFunction();

Je t'ai fais quelque-chose de sommaire, à toi de mettre les vérifications nécessaires.
Bonne chance.
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
Merci beaucoup je vais voir tout ça !
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
Ok ça marche !!!!!!

Merci beaucoup !!
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
Une dernière question :

A partir dans ma DLL je peux pas changer les textes dans les labels avec "SetWindowText()"...

Quelle fonction dois-je utiliser ?

Merci encore
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
Je connaissais les deux méthodes, j'utilisais la 1ère, et elle marchait pas !!

Tu m'as fait penser à la seconde, et ça marche.

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
C'est quand même bizzare que la 1ère ne marche pas.
Fais attention, car dans l'exemple que je t'ai filé, il y a un petit problème.
Je m'explique :
La fonction CreateMsgWindow crée le thread servant à la gestion de la fenêtre, et retourne la valeur 1 si tout est OK.
Le problème, c'est que quand elle redonne la main, la fenêtre n'est pas encore créée. Ton problème avec SetWindowText() vient peut-être de là...
J'ai résolu ce problème en faisant de la façon suivante: (les parties modifiées apparaissent en violet)

DLLIMPORT int CreateMsgWindow(HWND hParent)
{
if (FlgCreated==true) return 0;
hPrntWnd=hPrntWnd;
InitCommonControls();
hModule=GetModuleHandle(NULL);
hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
hThread=CreateThread(NULL,0,ThreadFunction,hEvent,0,&thID);
// On attend maximum 15 secondes que le thread ait créé la fenêtre
DWORD dwRes=WaitForSingleObject(hEvent,15000);
CloseHandle(hEvent);
if (dwRes==WAIT_TIMEOUT) // Si les 15 secondes d'attente sont passées
return 0;
return 1;
}

Puis, dans la ThreadFunction :

DWORD WINAPI ThreadFunction(LPVOID lPar)
{
WNDCLASS wc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hInstance=GetModuleHandle(NULL);
wc.lpfnWndProc=MainWndProc;
wc.lpszClassName="Msg_Wnd_Class";
wc.lpszMenuName=NULL;
wc.style=CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);
// Création de la fenêtre principale
hWndMain=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,"Msg_Wnd_Class","Messages",WS_THICKFRAME|WS_VISIBLE,CW_USEDEFAULT,0,350,150,hPrntWnd,NULL,GetModuleHandle(NULL),0);
// Création de la TextBox
hTxtMsg=CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","",WS_VISIBLE|WS_CHILD|WS_HSCROLL|WS_VSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,5,5,10,10,hWndMain,NULL,GetModuleHandle(NULL),0);
ShowWindow(hWndMain,SW_SHOW);
UpdateWindow(hWndMain);
FlgCreated=true;
// Tout s'est bien passé, on peut libérer la fonction create qui attend
SetEvent((HANDLE)lPar);
// On met une pompe à messages pour que ça tourne correctement
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

Bonne continuation ...
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
Ok je comprend le principe merci
Commenter la réponse de ncoder