Developpez.com

Télécharger gratuitement le magazine des développeurs, le bimestriel des développeurs avec une sélection des meilleurs tutoriels

Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :



Trucs et astuces pour C++ Builder

Par CGi

Page 1 Page 2 Page 3 Page 4 Page 5



Taille de la RAM physique :

Obtention de la taille de la Ram en Mo

     MEMORYSTATUS X;
     X.dwLength = sizeof(X);
     GlobalMemoryStatus(&X);

     TailleDeLaRam = (X.dwTotalPhys+524288)/1024/1024;




Mettre une commande dans le menu Système :

Dans le fichier Unit.h on définit une constante pour la commande CM_MONMSG. On déclare la fonction ReponseMessage et le Handle de menu MyMenu. Puis on dirige le message WM_SYSCOMMAND vers la fonction ReponseMessage.

#define CM_MONMSG  401
class TForm1 : public TForm
{
__published:    // Composants gérés par l'EDI
        void __fastcall FormCreate(TObject *Sender);
private:    // Déclarations de l'utilisateur
        HMENU MyMenu;
        void __fastcall ReponseMessage(TMessage &Msg);
public:        // Déclarations de l'utilisateur
        __fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, ReponseMessage);
END_MESSAGE_MAP(TForm)
};

Dans le fichier Unit.cpp on crée la commande de menu du menu système sur l'événement OnCreate de la Form (Form1). On définit la fonction ReponseMessage

void __fastcall TForm1::FormCreate(TObject *Sender)
{
     MyMenu = GetSystemMenu(Handle,FALSE);
     AppendMenu(MyMenu,MF_SEPARATOR ,NULL,NULL);//ajoute un séparateur
     AppendMenu(MyMenu,NULL ,CM_MONMSG , "A Propos !");
}

void __fastcall TForm1::ReponseMessage(TMessage &Msg)
{
   if (Msg.WParam == CM_MONMSG)
                ShowMessage("Message Reçu");
   else  TForm::Dispatch(&Msg);
}




Envoyer des fichiers dans la corbeille :

Par exemple nous allons envoyer tous les fichiers textes "*.txt" du dossier "C:\\tmp" dans la corbeille à l'aide de la fonction SHFileOperation.

     #include <shellapi.h>

     //................................

     SHFILEOPSTRUCT FileOpStr;
     ZeroMemory(&FileOpStr, sizeof(FileOpStr));
     FileOpStr.hwnd = Application->Handle;
     FileOpStr.fFlags = FOF_ALLOWUNDO;
     FileOpStr.wFunc = FO_DELETE;
     FileOpStr.pFrom = "C:\\tmp\\*.txt\0";
     SHFileOperation(&FileOpStr);

Cette fonction peut aussi servir à renommer, copier, déplacer des fichiers.
FileOpStr.wFunc: FO_RENAME, FO_COPY, FO_MOVE. Dossier de destination : FileOpStr.pTo = "C:\\ici"
Les chaînes pointées par FileOpStr.pFrom et FileOpStr.pTo peuvent contenir plusieurs fichiers ils doivent être séparer par des caractères NULL '\0' et les chaînes doivent se terminer par un double '\0'.
Les chaînes contenant les noms de fichiers doivent contenir des chemins complets.

Exemple :

Copie du dossier Source et tout son contenu dans le dossier Destination :

     #include <shellapi.h>

     //................................

     SHFILEOPSTRUCT FileOpStr;
     ZeroMemory(&FileOpStr, sizeof(FileOpStr));
     FileOpStr.hwnd = Application->Handle;
     FileOpStr.wFunc = FO_COPY;
     FileOpStr.pFrom = "C:\\Source\0";
     FileOpStr.pTo = "C:\\Destination\0";
     SHFileOperation(&FileOpStr);

Déplassement des fichiers du dossier Source dans le dossier Destination :

     #include <shellapi.h>

     //................................

     SHFILEOPSTRUCT FileOpStr;
     ZeroMemory(&FileOpStr, sizeof(FileOpStr));
     FileOpStr.hwnd = Application->Handle;
     FileOpStr.wFunc = FO_MOVE;
     FileOpStr.pFrom = "C:\\Source\\*.*\0";
     FileOpStr.pTo = "C:\\Destination\0";
     SHFileOperation(&FileOpStr);




Détection du changement de résolution de l'écran :

Dans Unit.h déclaration de la méthode réagissant au message (WM_DISPLAYCHANGE) envoyé par windows à toutes les applications quand la résolution de l'écran change.

private:    // Déclarations de l'utilisateur
         void __fastcall ChgtResolutionEcran(TMessage &Msg);
public:        // Déclarations de l'utilisateur
        __fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_DISPLAYCHANGE, TMessage, ChgtResolutionEcran);
END_MESSAGE_MAP(TForm)

Dans Unit.cpp définition de la fonction. C'est là que l'on met les actions à éffectuer.

void __fastcall TForm1::ChgtResolutionEcran(TMessage &Msg)
{
    ShowMessage("La résolution écran a changé.");
}




Appel de la boîte de dialogue de changement d'icônes:

Dans cet exemple nous allons appeller la boîte de dialogue de changement d'icônes. (Celle qui sert à changer les icônes des raccourcis) Puis nous afficherons l'icône sélectionnée sur la fiche.
Sur une Form (Form1) poser un bouton (Button1) et 2 Labels (Label1 et Label2).

Sur Unit.h déclaration du Handle d'icône:

private:    // Déclarations de l'utilisateur
        HICON MonIcone;

Sur Unit.cpp événement OnClick de Button1 et OnPaint de Form1:

#include <shellapi.h>

//................

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    typedef LONG (CALLBACK *SHCHANGEICONDIALOG)(HWND hWnd, LPCSTR szFilename,
                                                LONG Size, int *IconIndex);
    SHCHANGEICONDIALOG  SHChangeIconDialog = NULL;
    char szFilename[MAX_PATH];
    int IconIndex;
    HANDLE hInst;

    hInst=LoadLibrary("SHELL32.DLL");
    if(hInst)
      {
        SHChangeIconDialog=(SHCHANGEICONDIALOG)GetProcAddress(hInst,(LPCSTR)62);
        szFilename[0]='\0';
        SHChangeIconDialog(Handle,szFilename,sizeof(szFilename),&IconIndex);
        Label1->Caption = IconIndex;
        Label2->Caption = szFilename;

        MonIcone = ExtractIcon(HInstance, szFilename, IconIndex);
        Refresh();
      }
    if(hInst) FreeLibrary(hInst);
}
void __fastcall TForm1::FormPaint(TObject *Sender)
{
       DrawIcon(Canvas->Handle, 200, 10, MonIcone);
}




Ouvrir votre application par l'ouverture de l'un de ses fichiers :

Exemple: l'extension des fichiers de l'application exemple sera ".mon" se seront des fichiers textes qui se chargeront dans un Memo (Memo1) qui a été posé sur la fiche (Form1).
Pour cela il suffit de mettre ce code dans l'événement OnCreate de Form1

void __fastcall TForm1::FormCreate(TObject *Sender)
{
   if ( ParamCount() > 0 )
      Memo1->Lines->LoadFromFile(ParamStr(1));
}

ParamCount() renvoie le nombre de paramètres.
ParamStr(1) renvoie une AnsiString contenant le 1er paramètre.

Mais pour que cela fonctionne, il faut associer le type de fichiers ".mon" à l'application.

On peut faire l'association par programme :

Unit.h :

      #include <Registry.hpp>

Unit.cpp

      TRegistry *Reg = new TRegistry;
      Reg->RootKey = HKEY_CLASSES_ROOT;

      Reg->OpenKey("\\.mon",true);//Extention du fichier
      Reg->WriteString("","Mon_Fichier");//nom de la clé suivante
      Reg->CloseKey();

      Reg->OpenKey("\\Mon_Fichier",true);
      Reg->WriteString("","Fichier Mon");
                 //nom qui apparait dans l'explorateur de fichier
      Reg->CloseKey();

      Reg->OpenKey("\\Mon_Fichier\\shell\\open\\command",true);
      Reg->WriteString("","\"C:\\dossier\\mon.exe\" \"%1\"");
                //Chemin et nom du programme associé suivie de "%1"
      Reg->CloseKey();

      delete Reg;

ATTENTION aux écritures dans la base de registre. Les erreurs ne sont pas permises.
Ce code a été testé sous Windows 95, 98 et XP.
Pour le tester il faudra créer un fichier texte avec l'extension ".mon"





Sauvegarder la taille et la position de la fiche dans le registre :

Dans cet exemple nous allons utiliser la classe TRegistry pour sauvegarder et restaurer la taille et la position de la dernière utilisation avant fermeture de notre fiche (Form1).


Unit.h :

      #include <Registry.hpp>

Sauvegarde: à la fermeture de la fiche sur l'événement OnClose de Form1.

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
   TRegistry *Reg = new TRegistry;
   Reg->OpenKey("\\Software\\Votre_Societe\\Votre_Application",true);
   if ( WindowState == wsNormal )
     {
       Reg->WriteBool("Agrandie",false);
       Reg->WriteInteger("Pos_X",Left);
       Reg->WriteInteger("Pos_Y",Top);
       Reg->WriteInteger("Largeur",Width);
       Reg->WriteInteger("Hauteur",Height);
     }
   else Reg->WriteBool("Agrandie",true);
   Reg->CloseKey();
   delete Reg;
}

Restauration: à l'ouverture de la fiche sur l'événement OnCreate de Form1.

void __fastcall TForm1::FormCreate(TObject *Sender)
{
   TRegistry *Reg = new TRegistry;
   if ( Reg->OpenKey("\\Software\\Votre_Societe\\Votre_Application",false))
     {
     try
      {
       Left = Reg->ReadInteger("Pos_X");
       Top = Reg->ReadInteger("Pos_Y");
       Width = Reg->ReadInteger("Largeur");
       Height = Reg->ReadInteger("Hauteur");
      }
     catch(...) {}
       if ( Reg->ReadBool("Agrandie") ) WindowState = wsMaximized;
     }
   Reg->CloseKey();
   delete Reg;
}

Les données de taille et position peuvent ne pas être dans la base de registre si lors des premiéres utilisations la fiche a été fermée en position Maximised. D'où le bloc try catch pour éviter le message d'erreur en ce cas.
La clé par défaut de TRegistry est HKEY_CURRENT_USER. Donc dans notre exemple les données seront écrites dans : HKEY_CURRENT_USER\Software\Votre_Societe\Votre_Application
ATTENTION aux écritures dans la base de registre. Les erreurs ne sont pas permises.





Sauvegarder la taille et la position de la fiche dans un fichier ini :

Comme l'exemple précédent nous allons sauvegarder et restaurer la taille et la position de la dernière utilisation avant fermeture de notre fiche (Form1), mais cette fois dans un fichier profil ".ini" à l'aide de la classe TIniFile.

Unit.h :

      #include <Inifiles.hpp>

Sauvegarde: à la fermeture de la fiche sur l'événement OnClose de Form1.

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
      TIniFile *Ini = new TIniFile("App.ini");
      if ( WindowState == wsNormal )
       {
         Ini->WriteInteger("Position", "Pos_X", Left);
         Ini->WriteInteger("Position", "Pos_Y", Top);
         Ini->WriteInteger("Position", "Largeur", Width);
         Ini->WriteInteger("Position", "Hauteur", Height);
         Ini->WriteBool("Position", "Agrandie",false);
       }
      else Ini->WriteBool("Position", "Agrandie",true);
      delete Ini;
}

Restauration: à l'ouverture de la fiche sur l'événement OnCreate de Form1.

void __fastcall TForm1::FormCreate(TObject *Sender)
{
      TIniFile *Ini = new TIniFile("App.ini");
      Left = Ini->ReadInteger("Position", "Pos_X", Left);
      Top = Ini->ReadInteger("Position", "Pos_Y", Top);
      Width = Ini->ReadInteger("Position", "Largeur", Width);
      Height = Ini->ReadInteger("Position", "Hauteur", Height);
      if ( Ini->ReadBool("Position", "Agrandie", false) ) WindowState = wsMaximized;
      delete Ini;
}

Utilisation des fonctions de lectures et écritures :
Valeur = ReadInteger("Section", "Clé", ValeurParDéfaut);
WriteInteger("Section", "Clé", Valeur);
Dans cet exemple le fichier "App.ini" est enregistré dans le dossier Windows. Si vous voulez l'enregistrer ailleurs il faut mettre le chemin avec le nom de fichier.

Pour plus d'information voir Aide C++ Builder Rubrique TIniFile.





Changer le papier peint de Windows :

Pour cela nous utiliserons la fonction SystemParametersInfo.

 SystemParametersInfo(SPI_SETDESKWALLPAPER,
                     0,"C:\\Dossier\\Dessin.bmp",NULL );

Cette fonction permet d'obtenir ou de changer de nombreux paramètres de configuration de Windows. (voir aide API Windows)

Par exemple désactiver l'écran de veille:

  SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, NULL, 0);

Réactiver l'écran de veille:

  SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, true, NULL, 0);





Une seule instance de l'application :

Dans cet exemple le code va être inséré dans le fichier principal de notre application "Project1.cpp". Nous y créons un Mutex avec un nom qui n'a aucune chance d'exister dans une autre application. Au lancement de la deuxième instance de l'application le Mutex avec ce nom existant déjà provoque une erreur sur la fonction CreateMutex. Erreur que l'on teste pour quitter la deuxième instance de l'application le cas échéant.

#include <vcl.h>
#pragma hdrstop
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
   HANDLE hMutex;
        try
        {
          hMutex = CreateMutex (NULL,FALSE,"Mon application");
          if (GetLastError() == ERROR_ALREADY_EXISTS) return 0; 
          Application->Initialize();
          Application->CreateForm(__classid(TForm1), &Form1);
          Application->Run();
          CloseHandle(hMutex);
        }
        catch (Exception &exception)
        {
                 Application->ShowException(&exception);
        }
        return 0;
}




Comment gérer les événements d'un composant crée dynamiquement :

Dans cet exemple nous allons créer un bouton dynamiquement puis créer une méthode pour gérer son événement OnClick.

Dans Unit1.h déclaration du pointeur sur le bouton et de la méthode :

private:    // Déclarations de l'utilisateur
        TButton *MonBouton;
        void __fastcall MonBoutonClick(TObject *Sender);
Sur l'événement OnCreate de Form1 création du bouton et affectation de la méthode MonBoutonClick à l'événement OnClick du bouton :

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    MonBouton = new TButton(this);
    MonBouton->Left = 20;
    MonBouton->Top = 20;
    MonBouton->Caption = "Bouton";
    MonBouton->Parent = Form1;

    MonBouton->OnClick = MonBoutonClick;
}

Définition de la méthode :

void __fastcall TForm1::MonBoutonClick(TObject *Sender)
{
    ShowMessage("Tu viens de cliquer sur MonBouton");
}




Gestion des événements OnMouseEnter et OnMouseExit :

Pour l'exemple nous allons poser un Label (Label1) sur une fiche (Form1). Nous passerons le texte du label en rouge quand le curseur viendra au dessus puis en bleu quand il en sortira.

Unit1.h :
déclaration d'une variable TWndMethod pour mémoriser la procédure de fenêtre de Label1 et la méthode de la nouvelle procédure de fenêtre.

private:    // Déclarations de l'utilisateur
        Controls::TWndMethod OldLabelWP;
        void __fastcall NewLabelWP(TMessage &Msg);

Unit1.cpp :
événement OnCreate de Form1, sauvegarde de l'ancienne procédure de fenêtre de Label1 et affectation de la nouvelle.

void __fastcall TForm1::FormCreate(TObject *Sender)
{
        OldLabelWP = Label1->WindowProc;
        Label1->WindowProc = NewLabelWP;
}

Nouvelle procédure de fenêtre de Label1: traitement des commandes CM_MOUSELEAVE et CM_MOUSEENTER sinon appel de l'ancienne procédure de fenêtre si autre message.

void __fastcall TForm1::NewLabelWP(TMessage &Msg)
{
 if (Msg.Msg == CM_MOUSELEAVE) //OnMouseExit
  {
   Label1->Font->Color = clBlue;
  }
 else if (Msg.Msg == CM_MOUSEENTER) //OnMouseEnter
  {
   Label1->Font->Color = clRed;
  }
 else OldLabelWP(Msg);
}

Cette façon de faire est obsolète sur BCB6, on a accés à ces événements dans l'inspecteur d'objets (OnMouseEnter et OnMouseLeave).





Hint sur plusieurs lignes :

Pour que la propriété Hint s'affiche sur plusieurs ligne. Il faut l'affecter à l'éxécution par exemple sur l'événement OnCreate de la Form.

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    Hint = "Bonjour\nMonsieur";
}




Changer la couleur d'une ProgressBar :

Exemple : passer la couleur de ProgressBar1 en rouge.

    SendMessage(ProgressBar1->Handle, PBM_SETBARCOLOR, 0, clRed);




Drag and Drop de l'explorateur Windows vers votre application :

Dans cet exemple nous allons copier les noms et chemins des fichiers glissés depuis l'explorateur Windows vers une ListBox (ListBox1) qui a été posé sur la Form (Form1).

Unit.h déclaration de la méthode DropFiles réagissant au message WM_DROPFILES

private:    // Déclarations de l'utilisateur
        void DropFiles(TMessage &Message);
public:        // Déclarations de l'utilisateur
        __fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_DROPFILES, TMessage, DropFiles);
END_MESSAGE_MAP(TForm);

Unit.cpp sur l'événement OnCreate de Form1 appel de la fonction DragAcceptFiles pour autoriser l'application à recevoir les noms fichiers depuis l'explorateur.
Puis définition de la méthode DropFiles dans laquelle le premier appel de la fonction DragQueryFile nous retourne le nombre de fichiers glissés et les appels suivants leurs noms et chemins.
La fonction DragFinish libère la mémoire.

#include <shellapi.h>

//..........

void __fastcall TForm1::FormCreate(TObject *Sender)
{
       DragAcceptFiles(Handle, true);
}

void TForm1::DropFiles(TMessage &Message)
{
  int nFiles;
  char buffer[256];

  nFiles = DragQueryFile((HDROP)Message.WParam, 0xFFFFFFFF, NULL, 0);
  for (int i = 0; i < nFiles; i++)
  {
     DragQueryFile((HDROP)Message.WParam, i, buffer, 256);
     ListBox1->Items->Add((AnsiString)buffer);
  }
  DragFinish((HDROP)Message.WParam);
}




Précédant Index Suivant





C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?

  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.

Assembleur
  Assembleur sous Visual C++.

C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.

  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.

DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.

Java
  Applet java.





Copyright 2002-2016 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels.
Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document.
De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.

Contacter le responsable de la rubrique C