Introduction :
Dans ce chapitre nous allons voir l'appel des boîtes de dialogues standards,
c'est-à-dire celles : d'ouverture de fichiers, de sauvegarde de fichiers, de sélections
de polices de caractères, de sélections de couleurs et les messages box
de prises de décisions.
L'exemple que nous utiliserons dans ce document sera un mini éditeur de texte,
tel celui de la copie d'écran ci-dessous. Nous pourrons y ouvrir un fichier texte,
le sauvegarder sous un nom de notre choix. Nous pourrons aussi changer la couleur
de fond du contrôle d'édition ainsi que sa police de caractère et sa couleur de
texte. Si le texte a été modifié et qu'il n'a pas été sauvegardé
une boîte de messages nous donnera le choix entre réellement quitter
ou non l'application lors de sa demande de fermeture.
L'application sera construite sur une wxFrame munie de menus comme dans le chapitre 2.
Elle comportera un unique contrôle d'édition multi lignes, instancié depuis la classe wxTextCtrl.
Sa police de caractères sera initialisée avec une police à pas fixe (deuxième paramètre du
constructeur de la police à wxMODERN).
mlTextCtrl = new wxTextCtrl(this,TextEdit,"",wxDefaultPosition,wxDefaultSize,
wxHSCROLL | wxTE_MULTILINE );
mlTextCtrl->SetFont(wxFont(11, wxMODERN, wxNORMAL, wxNORMAL));
Le fait que le contrôle soit seul sur la fiche a pour conséquence qu'il
s'étend sur toute la zone client de la fiche.
Les boîtes de dialogue de fichiers :
Les boîtes de dialogues d'ouverture ou de sauvegarde de fichiers serons appellées
depuis les commandes de menus "Ouvrir..." et "Enregister sous...". Pour leur appel
nous utilisons une fonction nommée wxFileSelector. Le premier paramètre de cette fonction est le titre
de la boîte de dialogue, le 2ème le dossier par défaut, le 3ème le nom du fichier par défaut,
le 5ème est une chaîne de caractères de sélection de types de fichiers :
Une sélection s'écrit, avec le nom du type de fichiers, suivie d'une barre verticale, suivie
de ou des extensions séparées par des points virgules. D'autres sélections
de types de fichiers peuvent être ajoutées en les séparant de barres verticales
comme le type 'resources files' dans l'exemple, elle seront accessibles depuis
la ComboBox "Type de fichiers" des boîtes de dialogues.
Son 6ème paramètre est un entier qui renseigne si elle est : une boîte d'ouverture de fichier
'wxOPEN' ou de sauvegarde de fichiers 'wxSAVE'.
void Frame::OnOuvrir(wxCommandEvent& WXUNUSED(event))
{
wxString nomfichier = wxFileSelector("Ouvrir" ,"" ,"" ,"",
"cpp files (*.cpp;*.h)|*.h;*.cpp|resources files (*.rc)|*.rc",wxOPEN);
if (!nomfichier.empty())
{
mlTextCtrl->LoadFile(nomfichier);
TextChg = false;
}
}
//------------------------------------------------------------------------------
void Frame::OnEnregistrer(wxCommandEvent& WXUNUSED(event))
{
wxString nomfichier = wxFileSelector("Enregistrer" ,"" ,"" ,"",
"cpp files (*.cpp;*.h)|*.h;*.cpp|resources files (*.rc)|*.rc",wxSAVE);
if (!nomfichier.empty())
{
mlTextCtrl->SaveFile(nomfichier);
TextChg = false;
}
}
Ces fonctions renvoient une chaîne de caractères désignant le fichier sélectionné
si elles sont fermées par "Ouvrir" pour les boîtes de dialogues
d'ouverture de fichiers ou par "Enregistrer" pour celles d'enregistrement.
Dans tous les autres cas elles renvoient une chaîne vide.
Dans cet exemple nous avons appelé ces boîtes de dialogues avec des fonctions
de la bibliothèque.
Il faut savoir que cela peut aussi ce faire avec une classe nommée wxFileDialog
(voir aide).
La boîte de dialogue de choix de police de caractères :
Nous appellerons cette boîte de dialogue depuis le menu : "Options" -> "Polices"
à l'aide de la classe wxFontDialog
prévue à cet effet. A savoir que là aussi il existe une fonction pour son appel :
wxGetFontFromUser (voir aide).
Avant d'appeler la boîte de dialogue, nous initialiserons un objet nommé dfont de type
wxFontData avec la police actuelle du contrôle d'édition ainsi qu'avec
sa couleur de texte à l'aide des méthodes SetInitialFont et SetColour
de la classe wxFontData.
Le constructeur de la boîte de dialogue recevant en paramètre un pointeur
sur l'objet de type wxFontData afin de l'initialiser avec les données de l'objet dfont.
La boîte de dialogue est appelée par sa méthode
ShowModal dont nous utiliserons la valeur de retour, nous indiquant
comment elle a été fermée. Si cette valeur retourne 'wxID_OK' nous affectons
les nouvelles valeurs au contrôle d'édition, à savoir sa police et sa couleur
qui sont retournées dans un objet de type wxFontData dont nous récupérons
les valeurs à l'aide des méthodes GetChosenFont et GetColour.
On termine par l'appel de la méthode Refresh du contrôle d'édition pour actualiser
l'affichage.
void Frame::OnPolice(wxCommandEvent& WXUNUSED(event))
{
wxFontData dfont;
dfont.SetInitialFont(mlTextCtrl->GetFont());
dfont.SetColour(mlTextCtrl->GetForegroundColour());
wxFontDialog FontDlg(this, &dfont);
if (FontDlg.ShowModal() == wxID_OK)
{
mlTextCtrl->SetFont(FontDlg.GetFontData().GetChosenFont());
mlTextCtrl->SetForegroundColour(FontDlg.GetFontData().GetColour());
mlTextCtrl->Refresh();
}
}
La boîte de dialogue de choix de couleurs :
Nous l'appelons depuis le menu : "Option" -> "Couleur du fond"
avec la fonction wxGetColourFromUser de la bibliothèque,
là aussi il existe une classe faisant la même chose.
C'est la plus simple d'utilisation, dans l'exemple nous l'initialisons avec la
couleur de fond du contrôle d'édition, nullemment besoin de faire de test car elle
renvoie cette couleur si elle est fermée par le bouton "Annuler".
Nous affecterons ensuite la couleur de fond du contrôle d'édition avec sa valeur de retour.
void Frame::OnCouleur(wxCommandEvent& WXUNUSED(event))
{
wxColour NewColor = wxGetColourFromUser(this,
mlTextCtrl->GetBackgroundColour());
mlTextCtrl->SetBackgroundColour(NewColor);
mlTextCtrl->Refresh();
}
Les fonctions ou classes pour l'appel des boîtes de dialogues de choix de couleurs
et de police de caractère nécessitent l'inclusion de leur fichier en-tête respectif.
#include "wx/fontdlg.h"
#include "wx/colordlg.h"
Les Messages Box :
Voyons tout d'abord la message box simple avec un bouton "Ok",
accessible dans l'exemple par : le menu "aide", option de menu "A propos".
Nous en avions vu une dans le chapitre précédent qui était construite
à partir d'une classe (wxMessageDialog), celle-ci l'est avec la fonction
wxMessageBox.
void Frame::OnAPropos(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox("Programme de démonstration de wxWidgets.","A propos !");
}
Voyons maintenant une message box de prise de décision, dans l'exemple elle
comportera deux boutons "Oui" et "Non" et nous l'utiliserons à la fermeture
de l'application pour nous laisser le choix entre réellement fermer
ou non l'application.
void Frame::OnClose(wxCloseEvent& event)
{
if (TextChg == true)
{
if (wxMessageBox(
"Etes-vous sûr de vouloir quitter sans sauvegarder votre travail ?",
"Attention !",wxYES_NO ) == wxYES) event.Skip();
}
else event.Skip();
}
Précisions sur le code de l'exemple :
Vous vous demandez peut-être ce qu'est la donnée membre 'TextChg', c'est elle qui
nous indique si le texte du contrôle d'édition a changé ou non. Elle est mise
à jour dans la méthode 'OnTextUpdate' :
void Frame::OnTextUpdate(wxCommandEvent& WXUNUSED(event))
{
if (TextChg == false) TextChg = true;
}
Cette méthode est appelée suite à un événement du contrôle d'édition.
Voir son appel dans la table d'événements (macro EVT_TEXT).
Par ailleurs la méthode OnClose suit le même principe et est appelée suite à une demande
de fermeture de la fenêtre principale.
BEGIN_EVENT_TABLE(Frame, wxFrame)
//...
EVT_TEXT(TextEdit, Frame::OnTextUpdate)
EVT_CLOSE(Frame::OnClose)
END_EVENT_TABLE()
Dans la méthode OnClose vous avez sans doute remarqué l'appel de la méthode Skip
de l'événement. Elle permet l'exécution du code par défaut de l'événement, à savoir
dans ce cas la fermeture de l'application.
Dans l'exemple j'ai aussi mis une message box de prise de décision quand
on crée un nouveau document vide, je ne l'ai pas mis sur l'ouverture
d'un nouveau fichier pour ne pas trop charger l'exemple, mais il va de soit
que le test serait là aussi nécessaire.
Code source complet :
wxwin.h :
#ifndef wxWinH
#define wxWinH
class Application : public wxApp
{
public:
virtual bool OnInit();
};
//------------------------------------------------------------------------------
class Frame : public wxFrame
{
public:
Frame(const wxString& title, const wxPoint& pos, const wxSize& size,
long style = wxDEFAULT_FRAME_STYLE);
private:
bool TextChg;
wxTextCtrl *mlTextCtrl;
void OnQuit(wxCommandEvent& event);
void OnNouveau(wxCommandEvent& event);
void OnOuvrir(wxCommandEvent& event);
void OnEnregistrer(wxCommandEvent& event);
void OnPolice(wxCommandEvent& event);
void OnCouleur(wxCommandEvent& event);
void OnAPropos(wxCommandEvent& event);
void OnTextUpdate(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
enum
{
App_Quit = 1,
Nouveau,
Ouvrir,
Enregister,
Police,
Couleur,
APropos,
TextEdit
};
DECLARE_EVENT_TABLE()
};
//------------------------------------------------------------------------------
#endif //wxWinH
wxwin.cpp :
#include "wx/wxprec.h"
#include "wx/fontdlg.h"
#include "wx/colordlg.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
//------------------------------------------------------------------------------
#include "wxWin.h"
BEGIN_EVENT_TABLE(Frame, wxFrame)
EVT_MENU(App_Quit, Frame::OnQuit)
EVT_MENU(Nouveau, Frame::OnNouveau)
EVT_MENU(Ouvrir, Frame::OnOuvrir)
EVT_MENU(Enregister, Frame::OnEnregistrer)
EVT_MENU(Police, Frame::OnPolice)
EVT_MENU(Couleur, Frame::OnCouleur)
EVT_MENU(APropos, Frame::OnAPropos)
EVT_TEXT(TextEdit, Frame::OnTextUpdate)
EVT_CLOSE(Frame::OnClose)
END_EVENT_TABLE()
IMPLEMENT_APP(Application)
bool Application::OnInit()
{
Frame *frame = new Frame("Frame", wxPoint(150, 150), wxSize(480, 360));
frame->Show();
return true;
}
//------------------------------------------------------------------------------
Frame::Frame(const wxString& title, const wxPoint& pos, const wxSize& size,
long style) : wxFrame(NULL, -1, title, pos, size, style)
{
SetIcon(wxICON(monicone));
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
TextChg = false;
wxMenu *menuFichier = new wxMenu;
menuFichier->Append(Nouveau,"Nouveau");
menuFichier->Append(Ouvrir,"Ouvrir...");
menuFichier->Append(Enregister,"Enregister sous...");
menuFichier->AppendSeparator();
menuFichier->Append(App_Quit,"Quitter l'application");
wxMenu *menuOption = new wxMenu;
menuOption->Append(Police,"Police");
menuOption->Append(Couleur,"Couleur du fond");
wxMenu *menuAide = new wxMenu;
menuAide->Append(APropos,"A Propos !");
wxMenuBar *menuBarre = new wxMenuBar();
menuBarre->Append(menuFichier,("Fichier"));
menuBarre->Append(menuOption,("Options"));
menuBarre->Append(menuAide,("Aide"));
SetMenuBar(menuBarre);
mlTextCtrl = new wxTextCtrl(this,TextEdit,"",wxDefaultPosition,wxDefaultSize,
wxHSCROLL | wxTE_MULTILINE );
mlTextCtrl->SetFont(wxFont(11, wxMODERN, wxNORMAL, wxNORMAL));
}
//------------------------------------------------------------------------------
void Frame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close();
}
//------------------------------------------------------------------------------
void Frame::OnNouveau(wxCommandEvent& WXUNUSED(event))
{
if (TextChg == true)
{
if (wxMessageBox("Etes-vous sûr de vouloir créer un nouveau\n\
fichier sans sauvegarder votre travail ?","Attention !",wxYES_NO ) == wxYES)
{
mlTextCtrl->Clear();
TextChg = false;
}
}
else mlTextCtrl->Clear();
}
//------------------------------------------------------------------------------
void Frame::OnOuvrir(wxCommandEvent& WXUNUSED(event))
{
wxString nomfichier = wxFileSelector("Ouvrir" ,"" ,"" ,"",
"cpp files (*.cpp;*.h)|*.h;*.cpp|resources files (*.rc)|*.rc",wxOPEN);
if (!nomfichier.empty())
{
mlTextCtrl->LoadFile(nomfichier);
TextChg = false;
}
}
//------------------------------------------------------------------------------
void Frame::OnEnregistrer(wxCommandEvent& WXUNUSED(event))
{
wxString nomfichier = wxFileSelector("Enregistrer" ,"" ,"" ,"",
"cpp files (*.cpp;*.h)|*.h;*.cpp|resources files (*.rc)|*.rc",wxSAVE);
if (!nomfichier.empty())
{
mlTextCtrl->SaveFile(nomfichier);
TextChg = false;
}
}
//------------------------------------------------------------------------------
void Frame::OnPolice(wxCommandEvent& WXUNUSED(event))
{
wxFontData dfont;
dfont.SetInitialFont(mlTextCtrl->GetFont());
dfont.SetColour(mlTextCtrl->GetForegroundColour());
wxFontDialog FontDlg(this, &dfont);
if (FontDlg.ShowModal() == wxID_OK)
{
mlTextCtrl->SetFont(FontDlg.GetFontData().GetChosenFont());
mlTextCtrl->SetForegroundColour(FontDlg.GetFontData().GetColour());
mlTextCtrl->Refresh();
}
}
//------------------------------------------------------------------------------
void Frame::OnCouleur(wxCommandEvent& WXUNUSED(event))
{
wxColour NewColor = wxGetColourFromUser(this,
mlTextCtrl->GetBackgroundColour());
mlTextCtrl->SetBackgroundColour(NewColor);
mlTextCtrl->Refresh();
}
//------------------------------------------------------------------------------
void Frame::OnAPropos(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox("Programme de démonstration de wxWidgets.","A propos !");
}
//------------------------------------------------------------------------------
void Frame::OnTextUpdate(wxCommandEvent& WXUNUSED(event))
{
if (TextChg == false) TextChg = true;
}
//------------------------------------------------------------------------------
void Frame::OnClose(wxCloseEvent& event)
{
if (TextChg == true)
{
if (wxMessageBox(
"Etes-vous sûr de vouloir quitter sans sauvegarder votre travail ?",
"Attention !",wxYES_NO ) == wxYES) event.Skip();
}
else event.Skip();
}
//------------------------------------------------------------------------------
Remarques sur ce document :
J'ai énuméré dans cet exemple les principales boîtes de dialogues standards.
L'appel des autres boîtes de dialogues standards (impressions, dossier, tips...)
suit le même principe, veuillez pour cela consulter l'aide de wxWidgets.
J'ai réalisé les compilations dans l'EDI de C++ Builder, wxWidgets étant
installé comme vu dans l'article :
"Installation de wxWidgets dans l'EDI de C++ Builder".
Pour les autres compilateurs veuillez vous référer à leur documentation
respective ainsi qu'à la documentation de wxWindows.
A bientôt,
CGi
Avec la contribution d'Alacazam pour la relecture.
|