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
- Comment récupérer le texte affiché dans la barre de titre d'une fenêtre quelconque ?
- Comment changer la couleur d'un TProgressBar ?
- Comment donner un privilege à une application ?
- Comment trouver le Class Name d'une fenêtre ?
- Comment obtenir le Handle d'une fenêtre non-crée par l'application ?
- Comment obtenir les informations de version d'une application ?
- Comment forcer la fermeture d'un programme en exécution (fin de tâche) grâce à son intitulé ?
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); } |
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);
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; } |
Code c++ : | Sélectionner tout |
1 2 3 | SetPrivilege("SeShutdownPrivilege",true); // actions SetPrivilege("SeShutdownPrivilege",false); |
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; } |
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); |
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----------------------------" ); } } |
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); } |
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 çaLes 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 © 2024 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.