FAQ C++ BuilderConsultez toutes les FAQ

Nombre d'auteurs : 60, nombre de questions : 670, dernière mise à jour : 21 novembre 2010  Ajouter une question

 

Cette F.A.Q. a été réalisée à partir des questions fréquemment posées sur le forum C++ Builder de developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette F.A.Q. ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette F.A.Q. ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, contactez pottiez

Nous espérons que cette F.A.Q. saura répondre à un maximum de vos questions. Nous vous souhaitons une bonne lecture.

L'équipe C++ Builder de Developpez.

Commentez cette FAQ : Commentez


SommaireInterface bisAPI Windows (7)
précédent sommaire suivant
 

Il peut parfois être utile de récupérer le texte affiché dans la barre de titre d'une fenêtre quelconque (en dehors de notre application). C'est très facile à réaliser à l'aide des fonctions de l'API Windows. Dans l'exemple qui suit, nous récupérons le Caption de la fenêtre active.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
AnsiString __fastcall TForm1::GetACtiveWindowCaption() 
{ 
   HWND hwnd; 
   // On récupère le handle de la fenêtre située au premier plan 
   hwnd = GetForegroundWindow(); 
   // on alloue un buffer de caractères destiné à recevoie le texte 
   char * caption = new char[255]; 
   // on récupère le texte dans ce buffer, en laissant la place pour le zéro terminal 
   int length = GetWindowText(hwnd,caption,254); 
   // on place le zéro terminal 
   caption[length] = '\0'; 
   // on retourne le contenu sous la forme d'une AnsiString 
   return AnsiString(caption); 
}

Mis à jour le 25 avril 2005 Pierre Castelain

Le composant TProgressBar ne dispose pas de propriété Color. Par contre il existe un message Windows pour modifier directement le contrôle : PBM_SETBARCOLOR. Il suffit d'envoyer ce message au contrôle barre de progression via son Handle avec les paramètres adéquats pour positionner la couleur voulue.

Code c++ : Sélectionner tout
SendMessage(ProgressBar1->Handle,PBM_SETBARCOLOR,0,clLime);

Mis à jour le 25 avril 2005 Nono40

Si votre application doit disposer d'un privilège, pour certains actions (comme par exemple demander l'extinction du poste de travail), vous pourrez utiliser la fonction ci-dessous. Notez qu'il est conseillé de toujours retirer un privilège une fois l'action effectuée.

La fonction suivante donne ou retire (suivant la valeur du paramètre grant le privilège donné en paramètre name :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool __fastcall SetPrivilege(AnsiString name, bool grant) 
{ 
   TOKEN_PRIVILEGES wTokenIn, wTokenOut; 
   DWORD wLength; 
   HANDLE wCurrentProcess, wToken; 
   _LUID wLuid; 
   bool ret; 
  
   wCurrentProcess = GetCurrentProcess(); 
   OpenProcessToken(wCurrentProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &wToken); 
   LookupPrivilegeValue(NULL, name.c_str(), &wLuid); 
   wTokenIn.PrivilegeCount = 1; 
   wTokenIn.Privileges[0].Luid = wLuid; 
   wTokenIn.Privileges[0].Attributes = (grant?SE_PRIVILEGE_ENABLED:0); 
   ret = AdjustTokenPrivileges(wToken, FALSE, &wTokenIn, sizeof(TOKEN_PRIVILEGES), &wTokenOut,&wLength)) 
   CloseHandle(wToken); 
  
   return ret; 
}
Par exemple, pour ajouter le paramètre SE_SHUTDOWN_NAME, effectuer une action, et retirer le privilège, en nous basant sur les informations du MSDN listant les constantes d'autorisation (voir plus bas), nous allons utiliser :

Code c++ : Sélectionner tout
1
2
3
SetPrivilege("SeShutdownPrivilege",true); 
// actions 
SetPrivilege("SeShutdownPrivilege",false);

Mis à jour le 21 juin 2006 Greybird netah25

On a parfois besoin de connaître le nom de classe d'une fenêtre. Ce nom s'obtient via la fonction GetClassName de l'API Windows. Cette fonction a besoin d'un Handle vers la fenêtre dont on désire obtenir le nom.

En général, cette situation se produira lors du développement, afin d'obtenir les données nécessaire à la programmation de l'interaction avec une fenêtre d'une autre application.

Le code (application console) ci-dessous montre comment réaliser un petit utilitaire permettant d'obtenir le nom de classe de la fenêtre située au premier plan. Pour l'utiliser, il faut créer une application console (Fichier | Nouveau | Autre, puis choisir Expert Console).

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <windows.h> 
#include <stdio.h> 
#include <conio.h> 
int main(int argc, char * argv[]) 
{ 
   HWND hFore; 
   char* pszBuffer; 
   int iNbChar = 1; 
   int iNbCharReturned; 
  
   printf("Vous avez 5 secondes pour activer la fenetre dont vous voulez connaitre le class name\r\n"); 
   printf("Appuyez sur une touche pour declancher le compteur ..."); 
   getch(); 
   Sleep(5000); 
  
   hFore = GetForegroundWindow(); 
  
   do 
   { 
      iNbChar = iNbChar * 2; 
      pszBuffer = new char[iNbChar]; 
      iNbCharReturned = GetClassName(hFore,pszBuffer,iNbChar); 
      if (iNbCharReturned == 0) 
      { 
         printf("Impossible de recuperer le class name\r\n"); 
      } 
      if (iNbCharReturned < (iNbChar - 1)) 
      { 
         printf("\r\nLe class name de cette fenetre est :\r\n|%s|",pszBuffer); 
         printf("\r\nLes barres verticales (|) de gauche et droite n'en font pas partie\r\n\a"); 
      } 
      delete[] pszBuffer; 
   } 
   while ((iNbCharReturned >= (iNbChar - 1))); 
  
   printf("Appuyez sur une touche pour fermer la fenetre..."); 
   getch(); 
  
   return 0; 
}

Mis à jour le 21 juin 2006 Greybird

Pour contrôler une fenêtre d'une application tierce, et lui envoyer des messages, il est nécessaire d'obtenir son Handle, qui sera de type HWND. Celui-ci est différent du Handle de processus, que l'on peut obtenir au moyen de CreateProcess ou ShellExecuteEx.

Ceci peut se réaliser au moyen de la fonction FindWindow de l'API Windows. Cette fonction prend en premier paramètre le nom de la classe de fenêtre recherchée, et en second le titre de cette fenêtre. Il est possible de positionner l'un de ces deux paramètres à NULL afin de ne pas utiliser le critère correspondant dans la recherche.
Etant donné que le titre de la fenêtre est beaucoup plus fluctuant que le nom de la classe de fenêtre, on cherchera toujours à préférer la recherche par nom de classe.

Pour obtenir ce nom de classe, il est possible d'utiliser un code fourni dans la FAQ (lien ci-dessous).

Le code suivant montre comment mettre une instance de la calculatrice Windows au premier plan, et lui envoyer un message indiquant l'appui sur la touche R (ce qui aura pour effet de déclencher la fonction inverse).

Code c++ : Sélectionner tout
1
2
3
4
HWND h = FindWindow("SciCalc", NULL); 
SetForegroundWindow(h); 
PostMessage(h, WM_KEYDOWN, 'R', 0); 
PostMessage(h, WM_KEYUP, 'R', 0);

Mis à jour le 21 juin 2006 bibmari

Toutes les applications (fichier.exe) peuvent mémoriser des informations de version.
Pour les visualiser dans l'Explorer, on clique droit sur le fichier, puis on fait propriété.

Dans l'EDI builder, pour inclure des informations de version, on utilise l'option :

  • Projet | Options | Informations de version
  • Cocher : Inclure les informations de version
  • Puis renseigner les champs d'identification du produit.

Pour déterminer si un fichier possède des informations de version, on utilise la fonction GetFileVersionInfoSize.
Pour obtenir ces informations, on utilise en plus la fonction GetFileVersionInfo.

Exemple d'utilisation :
Lorsque l'on clique sur un bouton, on renseigne un Memo (Memo1) avec toutes les informations dont dispose l'executable de l'application.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
void __fastcall TForm1::Button1Click(TObject *Sender) 
{ 
   Memo1->Clear(); 
  
   String PathNomExt = Application->ExeName; 
   DWORD Size = GetFileVersionInfoSize(PathNomExt.c_str(), &Size); 
   if (Size <= 0) { 
      Memo1->Lines->Add( "Pas d'information de version dans cette application." ); 
      return; 
   } 
  
   BYTE *Buffer; 
   try{ 
      Buffer = new unsigned char[Size]; 
      LPVOID   Str; 
      UINT     Len; 
      String   TypeInfo; 
      LPDWORD lpdwLangCp; 
      char szFileInfo[26]; 
  
      GetFileVersionInfo(PathNomExt.c_str(), 0, Size, Buffer); 
  
      // Lecture de la table des langues et jeux de caractères 
      if (!VerQueryValue(Buffer, "\\VarFileInfo\\Translation",  (LPVOID *)&lpdwLangCp, &Len)) return; // erreur 
      wsprintf(szFileInfo, "\\StringFileInfo\\%04x%04x\\", LOWORD(*lpdwLangCp), HIWORD(*lpdwLangCp)); 
  
      // Nom de l'organisation 
      TypeInfo = szFileInfo + (AnsiString) "CompanyName"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Nom de l'organisation :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Nom de l'organisation :\tErreur de lecture" ); 
  
      // Description 
      TypeInfo = szFileInfo + (AnsiString) "FileDescription"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Description :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Description :\tErreur de lecture" ); 
  
      // Version de fichier 
      TypeInfo = szFileInfo + (AnsiString) "FileVersion"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Version de fichier :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Version de fichier :\tErreur de lecture" ); 
  
      // Nom interne 
      TypeInfo = szFileInfo + (AnsiString) "InternalName"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Nom interne :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Nom interne :\tErreur de lecture" ); 
  
      // Copyright 
      TypeInfo = szFileInfo + (AnsiString) "LegalCopyRight"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Copyright :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Copyright :\tErreur de lecture" ); 
  
      // Marques légales 
      TypeInfo = szFileInfo + (AnsiString) "LegalTrademarks"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Marques légales :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Marques légales :\tErreur de lecture" ); 
  
      // Nom d'origine du fichier 
      TypeInfo = szFileInfo + (AnsiString) "OriginalFileName"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Nom d'origine du fichier :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Nom d'origine du fichier :\tErreur de lecture" ); 
  
      // Nom du produit 
      TypeInfo = szFileInfo + (AnsiString) "ProductName"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Nom du produit :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Nom du produit :\tErreur de lecture" ); 
  
      // Version du produit 
      TypeInfo = szFileInfo + (AnsiString) "ProductVersion"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Version du produit :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Version du produit :\tErreur de lecture" ); 
  
      // Commentaire 
      TypeInfo = szFileInfo + (AnsiString) "Comments"; 
      if (VerQueryValue(Buffer, TypeInfo.c_str(), &Str, &Len)) 
            Memo1->Lines->Add( "Commentaire :\t" + (AnsiString) reinterpret_cast<char *>(Str) ); 
      else  Memo1->Lines->Add( "Commentaire :\tErreur de lecture" ); 
  
   } 
   __finally{ 
      delete Buffer; 
      Memo1->Lines->Add( "\t----------------------------" ); 
   } 
}

Mis à jour le 6 décembre 2006 Dure_Limite

Pour forcer la fermeture d'un programme, il suffit de connaître le Handle de sa fenêtre, en utilisant pour cela la fonction FindWindow
qui prend en paramètre l'intitulé de la fenêtre (texte qui se trouve dans la barre de titre de la fenêtre). Ensuite la fonction GetWindowThreadProcessId
récupère l'ID du processus grâce au Handle. TerminateProcess ferme le programme.

Pour l'exemple "Calculatrice" est le programme a terminer :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* creation des variables */ 
HWND hWnd; 
DWORD processId; 
HANDLE hProcess; 
/*CODE*/ 
do 
{ 
    hWnd = FindWindow(NULL,"Calculatrice"); 
    if (hWnd) 
    { 
        GetWindowThreadProcessId(hWnd,&processId); 
        hProcess = OpenProcess(PROCESS_TERMINATE,false,processId); 
        if (hProcess) 
        { 
            TerminateProcess(hProcess,0); 
            CloseHandle(hProcess); 
        } 
    } 
} 
while(hWnd); 
}

Mis à jour le 10 décembre 2007 bandit boy pottiez

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

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 © 2020 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.