IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ VC++ et MFCConsultez toutes les FAQ

Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013  Ajouter une question

 

Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++

Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.

Sur ce, je vous souhaite une bonne lecture. Farscape

SommaireClasses Fenêtres et FrameWorkClasses Fenêtres et FrameWork Divers (10)
précédent sommaire suivant
 

En parcourant les fenêtres sur le bureau :
Voici un exemple permettant de trouver le handle de fenêtre de Word et de fermer Word :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
char szIdentite[]="Microsoft Word"; 
CWnd* pWnd = CWnd::GetDesktopWindow( )->GetTopWindow( ); 
CWnd *pWndWord = 0; 
CString s,strWord; 
while( 1 ) 
{ 
    pWnd = pWnd->GetNextWindow(); 
    if ( pWnd == NULL ) break; 
    pWnd->GetWindowText( s ); 
    strWord=s; 
    if(strWord.Find(szIdentite)!=-1) 
    { 
        pWndWord = pWnd; 
        break; 
    } 
} 
if(pWndWord) 
::PostMessage(pWndWord->GetSafeHwnd(),WM_SYSCOMMAND, SC_CLOSE, 0L );
Note: Si le nom de l'application est fixe on pourra utiliser la commande :

Code c++ : Sélectionner tout
1
2
3
4
5
  
CWnd::FindWindow 
static CWnd* PASCAL FindWindow(  
LPCTSTR lpszClassName,  
LPCTSTR lpszWindowName );
Code c++ : Sélectionner tout
1
2
  
CWnd *pWnd=CWnd::FindWindow( NULL,"MonProg");

Mis à jour le 5 avril 2013 farscape

Les classes MFC proposent des objets permettant de maintenir des collections d'objets en mémoire.
Classiquement on retrouvera des objets gérant des tableaux ,des listes ,et des maps .
On trouve dans les MFC deux générations de ces objets :

CObArray , CObList, CMapPtrToWord
Déclinés avec des string des word ,int etc..

La seconde génération utilise des classes templates :
CArray, CList ,CMap
il est préférable d'utiliser ces classes en remplacement des précédentes.

L'exemple qui suit déclare un objet à sérialiser .
Un tableau de cet objet.
Son remplissage, sa sauvegarde et sa lecture avec la classe CArchive.

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  
// header .................. 
  
// la classe qui contient les données  
class CItem : public CObject 
{ 
  
public: 
    DECLARE_SERIAL( CItem ) 
  
    CItem(){Clear();} 
    //----------------------------- 
    ~CItem(){} 
    //----------------------------- 
     // constructeur de copie 
    CItem(const CItem &rItem) 
    { 
        CopyFrom(rItem); 
    } 
    //----------------------------- 
    // operateur d'affectation 
    const CItem& operator=(const CItem& Src) 
    { 
        CopyFrom(Src); 
        return *this; 
    } 
    //----------------------------- 
    // effacer les données. 
    void Clear() 
    { 
        m_strNom=""; 
        m_strPrenom=""; 
        m_strCdp=""; 
        m_strVille="";  
    } 
    //----------------------------- 
    // la methode de serialisation. 
    void Serialize(CArchive& ar) 
    { 
        if(ar.IsStoring()) 
            ar << m_strNom << m_strPrenom << m_strCdp <<m_strVille; 
        else 
            ar >> m_strNom >> m_strPrenom >> m_strCdp >> m_strVille; 
    } 
    //----------------------------- 
    // copier les données d'une source. 
    void CopyFrom(const CItem & Src ) 
    { 
        if(this==&Src) return; 
  
        Clear(); // clear eventuel. 
  
        m_strNom    =Src.m_strNom; 
        m_strPrenom =Src.m_strPrenom; 
        m_strCdp    =Src.m_strCdp; 
        m_strVille  =Src.m_strVille; 
   } 
    //----------------------------- 
    // dump pour test 
    CString GetStrDump() 
    { 
        return ( m_strNom + "/" +m_strPrenom + "/" + m_strCdp +"/" + m_strVille); 
    } 
  
    // les données. 
    CString m_strNom; 
    CString m_strPrenom; 
    CString m_strCdp; 
    CString m_strVille; 
}; 
  
template<> void AFXAPI SerializeElements<CItem> (CArchive& ar, CItem* pElements, int nCount); 
  
// la gestion d'un tableau de cette classe . 
typedef CArray<CItem,CItem&> CArrayItem; 
  
// Source......................... 
//--------------------------------------------------------------------------------------- 
// definition de la methode de serialisation de l'objet CItem pour le template CArray. 
template <>  void AFXAPI SerializeElements <CItem> ( CArchive& ar,  
    CItem* pItem, int nCount ) 
{ 
    for ( int i = 0; i < nCount; i++, pItem++ )             
        pItem->Serialize( ar );     
} 
  
IMPLEMENT_SERIAL( CItem, CObject, 0) 
  
void Test() 
{ 
// un element  
   CItem item; 
  
    item.m_strCdp="06800"; 
    item.m_strNom="farscape"; 
    item.m_strPrenom="???"; 
    item.m_strVille="Nice"; 
  
   // un tableau de l'element 
    CArrayItem arItem; 
  
     // remplissage. 
    arItem.Add(item); 
    for(int i=0;i<10;i++) 
    { 
        item.m_strNom.SetAt(0,'A'+i); 
        arItem.Add(item); 
    } 
     // archivage. 
    { 
        CFile File;     
        if(File.Open("MyArchive.arc", CFile::modeCreate | CFile::modeWrite )) 
        { 
            CArchive ar( &File, CArchive::store); 
            arItem.Serialize(ar); 
        } 
    } 
    // Lecture de l'archive. 
    arItem.RemoveAll(); 
    CFile File;     
    if(File.Open("MyArchive.arc", CFile::modeRead )) 
    { 
        CArchive ar( &File, CArchive::load); 
        arItem.Serialize(ar); 
    } 
    // verification du contenu. 
    for(i=0;i<arItem.GetSize();i++) 
    { 
        AfxMessageBox(arItem[i].GetStrDump()); 
    } 
  
}
Note: il faut inclure le fichier afxtempl.h dans stdafx.h
Voir l'article sur MSDN Collections: How to Make a Type-Safe Collection

Mis à jour le 23 mars 2008 farscape

En complément de Comment sérialiser des données avec les MFC ?

Pour ceux qui n'ont pas envie d'implémenter eux-mêmes la fonction SerializeElements<CItem> chaque fois qu'ils veulent sérialiser le contenu d'un CArrayou d'un autre conteneur template MFC, il est possible de définir une classe template, héritant du conteneur en question, implémentant déjà ce service.

Exemple du CArray

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
#include <string> 
#include <sstream> 
#include <afxtempl.h> 
  
template <class T,class U> 
class CArraySer: public CArray<T,U> 
{ 
  
public: 
  
    CArraySer(int line,bool b=true); 
    virtual ~CArraySer(); 
    virtual void Serialize(CArchive& ar); 
    void AFXAPI SerializeElts (CArchive& ar, T* pItem, int nCount); 
  
private: 
  
    bool isSerializable; 
                    // si true, alors CArraySer contient des objets sérialisables 
  
    std::string msg;  
                    // complément au message d'erreur affiché si on 
                    // tente de sérialiser des objets non-sérialisables 
}; 
  
  
  
template <class T,class U> 
CArraySer<T,U>::CArraySer(int line,bool b) 
{ 
    isSerializable = b; 
    std::ostringstream oss; 
    oss << "Erreur ligne " << line << " : CArraySer contient des objets non-sérialisables"; 
    msg = oss.str(); 
} 
  
  
  
template <class T,class U> 
CArraySer<T,U>::~CArraySer() 
{ 
  
} 
  
  
  
template <class T,class U> 
void AFXAPI CArraySer<T,U>::SerializeElts  ( CArchive& ar,T* pItem, int nCount ) 
{ 
    for ( int i = 0; i < nCount; i++, pItem++ )             
        pItem->Serialize( ar );     
} 
  
  
  
template<class T, class U> 
void CArraySer<T, U>::Serialize(CArchive& ar) 
{ 
    ASSERT_VALID(this); 
  
    if (isSerializable) 
    { 
        CObject::Serialize(ar); 
        if (ar.IsStoring()) 
        { 
            ar.WriteCount(GetSize()); 
        } 
        else 
        { 
            DWORD nOldSize = ar.ReadCount(); 
            SetSize(nOldSize, -1); 
        } 
        SerializeElts(ar, m_pData, GetSize()); 
    } 
    else 
    { 
        AfxMessageBox(msg.c_str()); 
    } 
}

L'utilisation de CArraySerest similaire à celle de CArray, cependant il n'est plus nécessaire d'implémenter la fonction statique SerializeElements dans le code appelant. Le constructeur comporte 2 arguments : le 1er correspond à la ligne à laquelle vous déclarerez le CArraySer, le 2è est un booléen qui indique si les objets contenus par le CArraySer sont sérialisables ou non. Reprenons l'exemple du CArray en le remplaçant par CArraySer :

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
// La macro peut-être mise dans le fichier citem.cpp s'il existe 
IMPLEMENT_SERIAL( CItem, CObject, 0) 
  
void Test() 
{ 
   // un element  
   CItem item; 
  
   item.m_strCdp="35200"; 
   item.m_strNom="Shakala"; 
   item.m_strPrenom="Bigboom"; 
   item.m_strVille="Rennes"; 
  
   // un tableau de l'element 
   CArraySer<CItem,CItem&> arItem(__LINE__); 
  
   // remplissage. 
   arItem.Add(item); 
   for(int i=0;i<10;i++) 
   { 
       item.m_strNom.SetAt(0,'A'+i); 
       arItem.Add(item); 
   } 
  
   // archivage. 
   { 
       CFile File;     
       if(File.Open("MyArchive.arc", CFile::modeCreate | CFile::modeWrite )) 
       { 
           CArchive ar( &File, CArchive::store); 
           arItem.Serialize(ar); 
       } 
   } 
  
   // Lecture de l'archive. 
   arItem.RemoveAll(); 
   CFile File;     
   if(File.Open("MyArchive.arc", CFile::modeRead )) 
   { 
       CArchive ar( &File, CArchive::load); 
       arItem.Serialize(ar); 
   } 
  
   // verification du contenu. 
   for(i=0;i<arItem.GetSize();i++) 
   { 
       AfxMessageBox(arItem[i].GetStrDump()); 
   } 
}

Si vous déclarez le contenu du CArraySer comme non-sérialisable (isSerializable = false) et que vous tentez tout de même la sérialisation, un AfxMessageBox vous délivre un message vous indiquant votre erreur et la ligne à laquelle vous avez déclarez le CArraySer incriminé.

Mis à jour le 27 novembre 2005 bigboomshakala

Les collections à base de template MFC : CArray ,CMap ,CList disposent de fonctions particulières pour compléter des traitements de construction, de sérialisation ou de destruction d'éléments.

Voici la problématique : Je déclare un CMap sur dont les valeurs sont des pointeurs sur objets Donc l'insertion dans la CMap nécessitera l'allocation de l'objet au préalable.
Exemple :
la déclaration :

Code c++ : Sélectionner tout
1
2
  
CMap<CString ,const char *,_InfosFolder* ,_InfosFolder *> m_mapFilter;
l'insertion:

Code c++ : Sélectionner tout
1
2
  
m_mapFilter.SetAt("clef", new _InfosFolder);
La destruction d'un élément par la fonction RemoveKey ou RemoveAll provoquera une fuite de mémoire puisque la CMap appelle le destructeur de l'élement type ici un pointeur sur objet ,et donc ne libérera pas l'objet lui même.
pour résoudre ce problème on implémentera la fonctionDestructElements :

voici son prototype:

Code c++ : Sélectionner tout
1
2
3
4
  
template<class TYPE > 
void AFXAPI DestructElements( TYPE* pElements,  
int nCount );
implémentation pour le type de donnée _InfosFolder *

Code c++ : Sélectionner tout
1
2
3
4
5
  
template <> void AFXAPI DestructElements <_InfosFolder *> ( _InfosFolder** pItem, int nCount ) 
{ 
    for ( int i = 0; i < nCount; i++, pItem++ ) delete *pItem;   
}
Dans ce contexte comment être sûr de ne pas faire un delete sur un élément non alloué par un new ? je propose l'utilisation d'une macro à rajouter dans la définition du type de donnée.

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
  
#ifdef _DEBUG  
  
#define TRACK_ALLOC(_class) void *m_pNew;\ 
void* operator new(size_t nSize,LPCSTR lpszFileName,int nLine)\ 
{\ 
_class *p=static_cast<_class *>(::operator new(nSize, lpszFileName, nLine));\ 
p->m_pNew=p;return p;\ 
}\ 
bool IsAlloc(){return m_pNew==this;} 
  
#else 
  
#define TRACK_ALLOC(_class) void *m_pNew;\ 
void* operator new(size_t nSize)\ 
{\ 
_class *p=static_cast<_class *>(::operator new(nSize));\ 
p->m_pNew=p;return p;\ 
}\ 
bool IsAlloc(){return m_pNew==this;} 
  
#endif
ce qui donnera :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
struct _InfosFolder 
{ 
//.............. 
TRACK_ALLOC(_InfosFolder) 
}; 
template <> void AFXAPI DestructElements <_InfosFolder *> ( _InfosFolder** pItem, int nCount ) 
{ 
    for ( int i = 0; i < nCount; i++, pItem++ )             
    { 
        if(*pItem->IsAlloc()) delete *pItem; 
    } 
}
ces macros doivent etre inserées avant le bloc de code:

Code c++ : Sélectionner tout
1
2
3
4
5
6
  
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif
Note:le même traitement peut être appliqué sur la clé de la CMap. en effet la suppression d'un élement invoque la fonctionDestructElements sur la clef et sur l'élément associé. Extrait de AfxTempl.h

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
  
void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAll() 
{ 
    ASSERT_VALID(this); 
    if (m_pHashTable != NULL) 
    { 
        // destroy elements (values and keys) 
        for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++) 
        { 
            CAssoc* pAssoc; 
            for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext) 
            { 
                DestructElements<VALUE>(&pAssoc->value, 1); 
                DestructElements<KEY>(&pAssoc->key, 1); 
            } 
        } 
    } 
    // free hash table 
    delete[] m_pHashTable; 
    m_pHashTable = NULL; 
  
    m_nCount = 0; 
    m_pFreeList = NULL; 
    m_pBlocks->FreeDataChain(); 
    m_pBlocks = NULL; 
}

Mis à jour le 19 septembre 2005 farscape

Principe de fonctionnement général d'une édition à partir d'une CViewCScrollView :

Le traitement normal d'affichage se fait dans la fonction virtuelle OnDraw utilisée aussi pour le dessin écran .

Elle reçoit en argument un objet CDC (contexte de périphérique) .

Si on imprime, la fonction OnDraw est appelée par une autre fonction virtuelle, OnPrint ;le dc sera alors un contexte de périphérique pour imprimante, et CDC::IsPrinting() renvoie TRUE .

Dans le cas de la prévisualisation écran on aura un objet CPreviewDC; OnPrint et OnDraw seront appelées.

Les fonctions disponibles pour le système d'édition sont:

  • OnPreparePrinting : définition de la plage d'édition voir CPrintInfo
  • OnBeginPrinting : créations d'objets gdi personnels.
  • OnPrepareDC : appelée pour chaque page, c'est l'emplacement convenu pour définir le système de coordonnées (autre que MM_TEXT) .
  • OnPrint : Appelée pour chaque page ,traitements spécifiques pour compléter éventuellement le dessin, entêtes, pieds de page, date et heure d'édition. Appelle OnDraw.
  • OnEndPrinting: suppression des objets GDI.

dans une view on trouve généralement les messages suivants:

Code c++ : Sélectionner tout
1
2
3
4
  
ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint) 
ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint) 
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
Correspondant aux différents appels pour l'édition de la fenêtre en cours.

  • ID_FILE_PRINT : impression avec sélection de l'imprimante.
  • ID_FILE_PRINT_DIRECT: impression directe sur l'imprimante en cours.
  • ID_FILE_PRINT_PREVIEW: prévisualisation écran.

Note : le système MFC associe l'édition/prévisualisation à la fenêtre en cours on ne dispose pas en standard d'un objet indépendant pour gérer l'édition comme ça existait chez Borland avec les OWL .

Mis à jour le 4 avril 2005 farscape

On ne peut pas générer une application de type SDI ou MDI sans menu directement.
La solution consiste à le supprimer lors de la création de Mainframe en procédant comme suit :
Pour un projet SDI: Dans la classe CMainFrame, il faut rajouter dans la fonction PreCreateWindow, le code suivant :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 
{ 
  if (cs.hMenu!=NULL) 
    { 
        ::DestroyMenu(cs.hMenu);      // delete menu if loaded 
        cs.hMenu = NULL;              // no menu for this window 
    } 
    return CFrameWnd::PreCreateWindow(cs); 
}
Pour un projet MDI: Il faudra générer avec l'assistant et modifier les fonctions suivantes comme suit:

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
  
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 
{ 
  if (cs.hMenu!=NULL) 
    { 
        ::DestroyMenu(cs.hMenu);      // delete menu if loaded 
        cs.hMenu = NULL;              // no menu for this window 
    } 
    return CMDIFrameWnd::PreCreateWindow(cs); 
} 
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)  
{ 
// TODO: Add your specialized code here and/or call the base class 
  
    return CreateClient(lpcs,NULL); // a la place de la ligne ci-dessus 
//return CMDIFrameWnd::OnCreateClient(lpcs, pContext); 
} 
BOOL CMainFrame::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)  
{ 
// TODO: Add your specialized code here and/or call the base class 
  
return CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext); 
//return CMDIFrameWnd::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext); 
}
Enfin il faudra supprimer le menu dans les ressources .
c'est à dire le menu correspondant à l'identifiant utilisé dans la déclaration du document template dans la fonction InitInstance de la classe d'application.

Mis à jour le 19 septembre 2005 farscape nico-pyright(c)

On a pu déjà remarquer que beaucoup d'applications proposent à l'utilisateur d'enregistrer le document en cours de fermeture si celui-ci a été modifié depuis son ouverture. Les MFC proposent également ce mécanisme.

L'architecture d'application gère ce comportement grâce à la donnée membre BOOL m_bModified de la classe CDocument (dirty flag : TRUE si le document a été modifié, FALSE sinon). Cet indicateur est initialisé à false à la création, lecture, enregistrement du document. C'est au programmeur de le mettre à TRUE lorsque le document a été modifié.

Sa valeur peut-être consultée avec la fonction BOOL CDocument::IsModified() et modifiée avec la fonction void SetModifiedFlag(BOOL bModified = TRUE).

Lorsque l'utilisateur ferme un document, l'architecture d'application appelle la fonction virtuelle virtual BOOL SaveModified( ) qui ouvre une boîte de dialogue si m_bModified = TRUE. On peut redéfinir le comportement de la fonction SaveModified( ).

Exemple d'indication de modification du document :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// fonction de la classe dérivée de CDocument 
void CMyDoc::ModifData(CString strName,CString strLevel,CString strLoc,CTime tDate) 
{ 
   // m_pData est une donnée membre de CMyDoc 
   m_pData->SetName(strName); 
   m_pData->SetLevel(strLevel); 
   m_pData->SetPlace(strLoc); 
   m_pData->SetDate(tDate); 
  
   // les données du document ont été modifiées 
   SetModifiedFlag(); 
  
   // mise à jour des vues sur le document 
   UpdateAllViews(NULL); 
}
Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
// modification des données de CMyDoc dans une vue 
void CMyView::MyFunction() 
{ 
   CMyDoc * pDoc = static_cast<CMyDoc*>(GetDocument()); 
  
   // appel de la fonction modificant les données du document 
   pDoc->ModifData("Nom","Niveau","Localisation",CTime::GetCurrentTime()); 
  
   // si on n'avait pas écrit la fonction CMyDoc::ModifData(...), 
   // on aurait géré les modifications du document ici et écrit : 
   // pDoc->SetModifiedFlag(); 
}

Mis à jour le 27 novembre 2005 bigboomshakala

Un splashscreen est une boîte de dialogue qui apparaît au lancement d'une application pendant que celle-ci se charge. Lorsque l'application est prête, le splashscreen disparaît et la fenêtre principale de l'application apparaît.
Pour réaliser un splashscreen il suffit de décocher l'option "Title bar" dans les propriétés de la boîte de dialogue, et d'intercepter le message WM_WINDOWPOSCHANGING (à la main) :
Dans le .h de la dialog

Code c++ : Sélectionner tout
1
2
3
4
5
6
  
// Generated message map functions 
//{{AFX_MSG(CPasBougerDlg) 
... 
afx_msg void OnWindowPosChanging( WINDOWPOS* lpwndpos ); 
//}}AFX_MSG
Dans le .cpp de la dialog

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
BEGIN_MESSAGE_MAP(CPasBougerDlg, CDialog) 
//{{AFX_MSG_MAP(CPasBougerDlg) 
... 
ON_WM_WINDOWPOSCHANGING() 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
  
... 
void CPasBougerDlg::OnWindowPosChanging(WINDOWPOS* pWndPos) 
{ 
if (IsWindowVisible()) 
pWndPos->flags |= SWP_NOMOVE; 
}
NOTE :On peut bien sûr utiliser ce principe pour empêcher le redimensionnement et le déplacement d'une fenêtre dérivée de CWnd (view, dialog, framewnd...).

Pour une boîte de dialogue, on procèdera de la même façon en laissant éventuellement la barre de titre.

Dans un contexte SDI, on interceptera le message sur le CMainFrame et on interdira le redimensionnement :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
  
void CMainFrame::OnWindowPosChanging(WINDOWPOS* pWndPos) 
{ 
if (IsWindowVisible()) 
{ 
pWndPos->flags |= SWP_NOMOVE; 
pWndPos->flags |= SWP_NOSIZE; 
} 
}

Mis à jour le 27 novembre 2005 bigboomshakala

Il s'agit tout d'abord de transformer son application MFC en application managée, pour ceci, il faut ajouter le support du CLR.
Bouton droit sur le projet -> Common properties -> general -> Common language runtime support ; Mettre à /clr (common language runtime support).

Ensuite ajoutez simplement une nouvelle winform, rajoutez des composants dessus, etc.

Instanciez votre nouvelle form,

Code C++ : Sélectionner tout
1
2
mfcPlusWinforms::mfcWinForm dlg; 
dlg.ShowDialog(); // pour qu'elle se comporte comme une dialog

N'oubliez pas bien sûr d'inclure le fichier .h correspondant au code de la winform.

Téléchargez le programme d'exemple : mfcPlusWinforms.rar

Mis à jour le 22 janvier 2007 nico-pyright(c)

Dans le cas d'une CFormView, CView les ascenseurs apparaissent automatiquement dès que la surface cliente de la fenêtre devient trop petite par rapport à la surface réelle.
Comment faire dans ce contexte pour supprimer les ascenseurs ? Hé bien une CFormView ou CView hérite de la classe CSCrollView qui dispose d'une fonction spécifique pour adapter la surface de la fenêtre à la taille fenêtrée : SetScaleToFitSize

Exemple réalisé dans la méthode OnInitialUpdate d'une CFormView :

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
CRect Rect; 
    GetParentFrame()->GetWindowRect(&Rect); 
    GetParentFrame()->SetWindowPos( NULL,0,0,Rect.Width(),Rect.Height()/2,SWP_NOMOVE | SWP_NOZORDER); // 
    SIZE size; 
    size.cx=Rect.Width(); 
    size.cy=Rect.Height()/2; 
    SetScaleToFitSize(size);

J'ai diminué la taille de la fenêtre parent (MDIChild) par deux et ajusté la taille réelle avec SetScalToFitSize.

Mis à jour le 17 septembre 2007 farscape

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 © 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.