| auteur : Farscape | en appelant la fonction globale:
On pourra aussi disposer de la ligne de commande de l'application :
|
| auteur : Farscape |
AfxGetAppName () ;
AfxGetApp ()- > m_pszAppName
|
|
| auteur : nico-pyright(c) |
void GetNom (char * nom, DWORD taille)
{
char * c;
c = nom + GetModuleFileName (NULL ,nom,taille);
while (* c! = ' \\ ' ) c- - ;
strcpy (nom,+ + c);
}
|
ou
CString CGetNom (char * nom, DWORD taille)
{
GetModuleFileName (NULL ,nom,taille);
CString Cnom (nom);
return Cnom.Mid (Cnom.ReverseFind (' \\ ' )+ 1 );
}
|
Appel :
char nom[MAX_PATH];
GetNom (nom,MAX_PATH);
char nom[MAX_PATH];
CString Cnom = CGetNom (nom, MAX_PATH);
|
|
| auteur : nico-pyright(c) |
void GetChemin (char * chemin, DWORD taille)
{
char * c;
c = chemin + GetModuleFileName (NULL ,chemin,taille);
while (* c! = ' \\ ' )
c- - ;
* c= 0 ;
}
|
ou
CString CGetChemin (char * chemin, DWORD taille)
{
GetModuleFileName (NULL ,chemin,taille);
CString Cchemin (chemin);
return Cchemin.Mid (0 ,Cchemin.ReverseFind (' \\ ' ));
}
|
Appel : char chemin[MAX_PATH];
GetChemin (chemin, MAX_PATH);
CString Cchemin = CGetChemin (chemin, MAX_PATH);
AfxMessageBox (Cchemin);
|
|
| auteur : Farscape | En utilisant la fonction AfxSetWindowText.
Cette fonction n'est pas documentée !
Il faut l'appeler dans InitInstance après l'initialisation de la MainFrame
# include <afxpriv.h>
pMainFrame- > ShowWindow (m_nCmdShow);
pMainFrame- > UpdateWindow ();
AfxSetWindowText (m_pMainWnd- > m_hWnd," TestSDI- Farscape " );
|
|
| auteur : Farscape | Dans la fonction InitInstance de la classe d'application modifier comme suit :
m_nCmdShow = SW_SHOWMAXIMIZED ;
m_pMainWnd- > ShowWindow (m_nCmdShow);
m_pMainWnd- > UpdateWindow ();
|
|
| auteur : Farscape |
CMyMainFrame * p= (CMyMainFrame * )AfxGetMainWnd () ;
|
|
| auteur : Farscape | Le point de départ c'est la classe d'application qui donne accès aux documents Template.
CWinApp* pApp = AfxGetApp ();
CDocTemplate* pTemplate;
POSITION pos = pApp- > GetFirstDocTemplatePosition ();
while (pos ! = NULL )
{
pTemplate = pApp- > GetNextDocTemplate (pos);
ASSERT (pTemplate);
POSITION pos2 = pTemplate- > GetFirstDocPosition ();
while (pos2)
{
CDocument* pDoc = pTemplate- > GetNextDoc (pos2);
ASSERT (pDoc);
POSITION pos3 = pDoc- > GetFirstViewPosition ();
while (pos3 ! = NULL )
{
CView* pView = pDoc- > GetNextView (pos3);
ASSERT (pView);
if (:: IsWindow (pView- > GetSafeHwnd ()))
{
if (pView- > IsKindOf (RUNTIME_CLASS (CFormView)))
{
}
else
if (pView- > IsKindOf (RUNTIME_CLASS (CScrollView)))
{
}
else
if (pView- > IsKindOf (RUNTIME_CLASS (CView)))
{
}
}
}
}
}
|
|
| auteur : Farscape | Plusieurs solutions peuvent être employées.
La plus simple à mon avis consiste à utiliser la possibilité de partager des variables pour tous les processus du programme.
# pragma data_seg ( " TestApp " )
LONG nCtApp = - 1 ;
# pragma data_seg ( )
# pragma comment ( linker , " / section : TestApp , rws " )
bool bFirstInstance = (InterlockedIncrement (& nCtApp) = = 0 );
if (! bFirstInstance)
{
}
|
Voir la note d'information MSDN sur le sujet :
HOWTO: Specify Shared and Nonshared Data in a DLL
Q100634
Autre solution possible, utiliser un objet Mutex.
exemple:
class CSdisamplesApp : public CWinApp
{
public :
CSdisamplesApp ();
~ CSdisamplesApp ();
CMutex m_Mutex;
bool m_bLock;
CSdisamplesApp:: CSdisamplesApp ():m_bLock (false ),m_Mutex (FALSE," SDISAMPLE " )
{
}
CSdisamplesApp:: ~ CSdisamplesApp ()
{
if (m_bLock) m_Mutex.Unlock ();
}
BOOL CSdisamplesApp:: InitInstance ()
{
if (! (m_bLock= m_Mutex.Lock (0 )))
{
AfxMessageBox (" Application active " );
return (0 );
}
|
|
| auteur : Farscape | Dans un projet MFC pour chaque document template on peut associer une extension de fichier .
Comment faire pour que lorsque l'on double-clique sur un document géré par l'application celle ?ci s'exécute ?
Il faut enregistrer les extensions dans la base de registre .
Pour un programme MFC il y a une fonction qui fait ce travail :
void RegisterShellFileTypes ( BOOL bCompat = FALSE );
|
La valeur bCompat a TRUE permet l'insertion des entrées impression et impression sur dans la base de registre ainsi que le sélectionner glisser lâcher du document sur une imprimante.
Cette fonction est à insérer derrière le dernier AddocTemplate dans la fonction InitInstance de la classe d'application.
La fonction EnableShellOpen doit être appelée.
BOOL CMyApp:: InitInstance ()
{
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate (
IDR_MYTYPE,
RUNTIME_CLASS (CMyDoc),
RUNTIME_CLASS (CMDIChildWnd),
RUNTIME_CLASS (CMyView));
AddDocTemplate (pDocTemplate);
CMainFrame* pMainFrame = new CMainFrame;
if (! pMainFrame- > LoadFrame (IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
EnableShellOpen ();
RegisterShellFileTypes ();
pMainFrame- > ShowWindow (m_nCmdShow);
pMainFrame- > UpdateWindow ();
}
|
|
| auteur : Farscape | La classe CWinApp (classe d'application) permet d'accéder à la ligne de commande par l'intermédiaire de sa donnée membre m_lpCmdLine
On pourra l'utiliser directement dans la fonction InitInstance, ou y accéder de partout dans l'application grâce à la fonction globale AfxGetApp()
AfxGetApp ()- > m_lpCmdLine.
|
Les arguments sont séparés par un blanc, pour disposer de la liste comme dans un programme classique en C avec la fonction main, on pourra procéder de la manière suivante :
BOOL CSampleSDIApp:: InitInstance ()
{
AfxEnableControlContainer ();
char szName[MAX_PATH];
GetModuleFileName (NULL ,szName,MAX_PATH);
CArray< CString ,const char * > argv;
char * szArg= strtok (m_lpCmdLine," " );
argv.Add (szName);
if (szArg)
{
do
{
argv.Add (szArg);
}
while (szArg= strtok (NULL ," " ));
}
int argc= argv.GetSize ();
for (int i= 0 ;i< argc;i+ + )
{
TRACE (" \nArgv[%d]=%s " ,i,argv[i]);
}
|
|
| auteur : Farscape | L'utilisation d'une variable globale objet a travers un projet est parfois nécessaire.
Je vous propose deux méthodes pour y parvenir:
Utiliser l'instance d'application pour stocker notre variable globale :
En effet une application MFC génère une seule instance de la classe d'application qui a la particularité d'être disponible à tout instant en utilisant la fonction globale AfxGetApp().
Il me suffira donc de déclarer l'objet ou la fonction à partager dans le projet dans la classe d'application et d'y accéder comme suit :
CMyApp * pApp= static_cast < CMyApp * > (AfxGetApp ());
pApp- > m_Global.MyFunction ();
CListCtrm & rList= pApp- > m_Global.GetLisCtrl ();
|
Autre solution utiliser le pattern Singleton : Définition
Le pattern Singleton garantit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à cette instance.
L'Exemple qui suit est adapté de ma lecture du livre : Design Patterns tête la première (en java mais très accessible à un lecteur C++).
namespace Singleton {
class MyClass
{
private : static MyClass* m_pUniqueInstance;
private : static CMutex m_LockInstance;
private : MyClass (const MyClass& );
private : void operator = (const MyClass& );
private : MyClass ()
{
}
private : ~ MyClass ()
{
m_pUniqueInstance = 0 ;
}
public : static MyClass & GetInstance ()
{
if (m_pUniqueInstance = = 0 )
{
m_LockInstance.Lock ();
if (m_pUniqueInstance = = 0 )
m_pUniqueInstance = new MyClass ();
m_LockInstance.Unlock ();
}
return * m_pUniqueInstance;
}
public : static void FreeInstance ()
{
m_LockInstance.Lock ();
delete m_pUniqueInstance;
m_LockInstance.Unlock ();
}
void UserFunction ()
{
ASSERT (m_pUniqueInstance);
}
} ;
}
CMutex Singleton:: MyClass:: m_LockInstance;
Singleton:: MyClass* Singleton:: MyClass:: m_pUniqueInstance= NULL ;
Singleton:: MyClass & theClass= Singleton:: MyClass:: GetInstance ();
theClass.UserFunction ();
Singleton:: MyClass:: GetInstance ().UserFunction ();
Singleton:: MyClass:: FreeInstance ();
|
Il existe de multiples exemples où le singleton est utile : objet de journalisation, de préférence de l'application etc ..
L'exemple que j'ai implémenté utilise un Mutex pour contrôler la création de l'instance, ce qui est préférable dans un contexte d'utilisation multithreads.
Ce même mutex pourra être utilisé pour gérer des accès à des variables ou des fonctions de la classe.
On placera la définition de la classe singleton dans l' include de la classe d'application pour que sa définition soit disponible dans toute l'application.
La déclaration des variables static pourra être faite dans le source de la classe d'application.
|
| auteur : Farscape | Une application MFC met en place une MRU ( Most Recently Used ), mais ne fournit pas d'accès directe à celle-ci pour y accéder .
En cherchant dans le code des MFC et plus exactement dans la fonction LoadStdProfileSettings on s'aperçoit que la liste est gérée par la donnée membre m_pRecentFileList de la classe CRecentFileList
void CWinApp:: LoadStdProfileSettings (UINT nMaxMRU)
{
ASSERT_VALID (this );
ASSERT (m_pRecentFileList = = NULL );
if (nMaxMRU ! = 0 )
{
m_pRecentFileList = new CRecentFileList (0 , _afxFileSection, _afxFileEntry,
nMaxMRU);
m_pRecentFileList- > ReadList ();
}
m_nNumPreviewPages = GetProfileInt (_afxPreviewSection, _afxPreviewEntry, 0 );
}
|
Pour accéder à cette liste déclarée protect dans la classe CWinApp on rajoutera un accesseur dans notre classe d'application :
class CMyApp : public CWinApp
{
public :
CMyApp ();
inline CRecentFileList * GetRecentFileList (){ return m_pRecentFileList;}
} ;
|
On rajoutera aussi le fichier :
Dans stdafx.h
Exemple Utilisation :
void CTestToolBarView:: OnInitialUpdate ()
{
CMyApp * TheApp= static_cast < CMyApp * > (AfxGetApp ());
CString str;
for ( int i= 0 ;TheApp- > GetRecentFileList ()- > GetSize ( );i+ + )
str= (* TheApp- > GetRecentFileList ())[i];
}
|
|
Consultez les autres F.A.Q.
|
|