| 
		

 
 |  |  | auteur : Farscape |  | 
On utilisera les radios chaque fois que l'on doit faire un choix unique parmi des options.Exemple imaginons le traitement du régime TVA d'un client on aura par exemple France / Corse / Export / CEE .
 1) étape :
 Dans l'éditeur de ressources sur la dialogue concernée on placera le premier radio en spécifiant son nom :
 Dans mon exemple je le nommerai IDC_RADIOTVA son label France
 Ensuite ne pas oublier de cocher l'option Tab Stop et surtout l'option Group permettant de spécifier que l'on commence un nouveau groupe et donc que les contrôles suivants de même nature en font partie.
 On place ensuite les autres radios et on laissera l'éditeur donner l'ID du radio  qu'il incrémentera de manière automatique par rapport au premier radio.
 Si je dois placer un autre groupe de radios derrière il faudra juste spécifier sur le premier radio l'option groupe pour distinguer les deux groupes.
 2) étape :
 Pour connaître la valeur de la sélection il faut attacher une variable uniquement sur le premier bouton radio du groupe.
 Pour cela il faut lancer « ClassWizard » ,onglet « member variables » ,sélectionner dans la liste l'id du bouton radio ici IDC_RADIOTVA
 Cliquer sur le bouton « Add Variable »  spécifier le nom de la variable de type « int »
 Exemple « m_nRegimeTVA ».
 Et valider le choix par le bouton « Ok »
 « ClassWizard » génère automatiquement :
 
 
 
			Le code de déclaration dans la classe.Initialise la valeur dans le constructeur - 1.Place le code d'échange des informations entre la variable et le contrôle dans la fonction   membre de la classe dialogue : DoDataExchange(CDataExchange* pDX). 
3)étape :Pour donner une valeur de départ à l'affichage de la fenêtre il suffira d'initialiser la variable dans la fonction InitDialog pour une boite de dialogue modale (CDialog) et OnInitialUpdate pour une classe CFormView :
 
 Ceci sélectionnera le deuxième radio de la liste,l'indexation commençant à zéro et finissant au nombre de bouton radio du groupe ? 1 dans mon exemple : 3.La valeur à « -1 » voulant dire aucune valeur sélectionnée.
 Pour signifier sa valeur au contrôle on utilisera la fonction
 
 pour la mise à jour du contrôle et
 Pour récupérer la valeur dans la variable.
 Autre cas: si la variable ne suffit pas et que l'on désire par exemple récupérer le label du radio sélectionné on peut procéder comme suit.
 Toujours par rapport à mon exemple :
 | 
CString CMyDialog::GetRadioLabelForValue(UINT nId,int&rnValue){CWnd*pRadio=NULL;UpdateData(TRUE);if(rnValue>=0){pRadio=GetDlgItem(nId);for(intn=0;pRadio&&n<rnValue;n++)
            pRadio=pRadio->GetWindow (GW_HWNDNEXT);}CString str;if(pRadio) pRadio->GetWindowText(str);returnstr;}CString str=GetRadioLabelForValue(IDC_RADIOTVA , m_nRegimeTVA);
 | 
 | 
|  |  | auteur : Farscape |  | Exemple je traite le message OnKeyUp dans une fenêtre
 et je veux savoir si la touche contrôle ou majuscule est enfoncée :
 | 
#define IsShiftDown()( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0   )#define IsCtrlDown()( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 )#define IsAltDown()( (GetKeyState(VK_LMENU) & (1 << (sizeof(SHORT)*8-1))) != 0   )voidCMyEdit::OnKeyUp(UINT nChar,
            UINT nRepCnt, UINT nFlags){if(IsCtrlDown()){switch(nChar){caseVK_INSERT:case'c':case'C':Copy();return;case'z':case'Z':Undo();return;case'x':case'X':Cut();return;}}if(IsShiftDown()){if(nChar==VK_INSERT){Paste();return;}}CEdit::OnKeyUp(nChar, nRepCnt, nFlags);}voidCMyEdit::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){if(IsAltDown()){TRACE("\nAlt");}CEdit::OnSysKeyDown(nChar, nRepCnt, nFlags);}
 | 
 | 
|  |  | auteur : Farscape |  | Exemple : Je voudrais avoir un message m'indiquant que l'on a relâché le bouton gauche sur un CButton et avoir ce genre de message directement au niveau de la fenêtre de traitement.
 Pour réaliser cette opération nous disposons du message WM_NOTIFY, permettant à un contrôle de communiquer avec son parent.
 
 Méthode:
 Avec l'aide de ClassWizard:
 On générera une classe dérivée de la classe CButton.
 Ensuite on interceptera le message WM_LBUTTONUP.
 Enfin on enverra le message WM_NOTIFY au parent comme suit :
 
 | 
#define BN_LBUTTONUP 1 // evenement custom LBUTTONUPCMyButton::CMyButton(){}CMyButton::~CMyButton(){}BEGIN_MESSAGE_MAP(CMyButton, CButton)ON_WM_LBUTTONUP()END_MESSAGE_MAP()voidCMyButton::OnLButtonUp(UINT nFlags, CPoint point){NMHDR hdr;
        hdr.hwndFrom=GetSafeHwnd();
        hdr.idFrom=GetDlgCtrlID();
        hdr.code=BN_LBUTTONUP;GetParent()->SendMessage(WM_NOTIFY,GetDlgCtrlID(), (LPARAM)&hdr);CButton::OnLButtonUp(nFlags, point);}BEGIN_MESSAGE_MAP(CSdisamplesView, CFormView)ON_BN_CLICKED(IDC_BUTTON1, OnButton1)ON_NOTIFY(BN_LBUTTONUP,IDC_BUTTON1,OnButtonUp)END_MESSAGE_MAP()voidCSdisamplesView::OnButtonUp(NMHDR*pNMHDR, LRESULT*pResult){TRACE("\nId:%u mess:%d",pNMHDR->idFrom,pNMHDR->code);}
 | 
La macro ON_NOTIFY est à rajouter manuellement dans BEGIN_MESSAGE_MAP.Ainsi que la fonction en réponse au message OnButtonUp(NMHDR* pNMHDR, LRESULT* pResult)
 Note :L'exemple ci-dessus utilise directement la structure NMHDR pour support du message, il est tout à fait possible de construire votre structure personnelle comme suit:
 | 
structTREE_NOTIFY Notify;
Notify.hdr.hwndFrom=GetSafeHwnd();
Notify.hdr.idFrom=GetDlgCtrlID();
Notify.hdr.code=TREE_INSERTITEM;
Notify.hItem=hNewItem;GetParent()->SendMessage(WM_NOTIFY,GetDlgCtrlID(), (LPARAM)&Notify);
 | 
 | 
|  |  | auteur : Farscape |  | La technique :
 On récupère les coordonnées du contrôle avec la fonction membre GetWindowRect.
 
 Les coordonnées sont données en rapport à l'écran.
 
 Pour déplacer un contrôle dans sa fenêtre on utilisera la fonction MoveWindow ou SetWindowPos, mais les coordonnées doivent être fournis en  rapport à la fenêtre de placement  (la view ou la dialogue) .
 
 On utilisera pour la conversion la fonction ScreenToClient à partir de la fenêtre parent :
 
 C'est-à-dire on demande de convertir des coordonnées écrans en coordonnées en rapport avec l'objet qui appel ScreenToClient .
 
 Ensuite on applique la fonction de déplacement.
 
 Note : dans le cas où on veut changer la taille on utilisera de préférence SetWindowPos  à MoveWindow.
 
 Dans l'exemple en dessus j'ai mis this->ScreenToClient pour bien montrer que c'est l'objet sur lequel on se trouve qui sert de référence pour la conversion.
 | 
CRect Rect; 
MyStatic.GetWindowRect(&Rect);this->ScreenToClient(&Rect); 
Rect.InflateRect(Rect.Width(),Rect.Height()); 
MyStatic.SetWindowPos(NULL,0,0,Rect.Width(),Rect.Height(),SWP_NOMOVE|SWP_NOZORDER); 
MyStatic.MoveWindow(&Rect) ;
 | 
 | 
|  |  | auteur : Farscape |  | Il n'existe pas de mécanismes standard de gestion des positions (layout) sur les contrôles.La classe Template suivante se propose de remédier à ce problème.
 
 | 
#if !defined(AFX_TPLLAYOUT_H__59DC7C67_79D6_4082_A38B_4CD17E8257C1__INCLUDED_)#define AFX_TPLLAYOUT_H__59DC7C67_79D6_4082_A38B_4CD17E8257C1__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <algorithm>#include <vector>#ifndef OBM_SIZE#define OBM_SIZE 32766#endiftemplate<classGENERIC_LAYOUT>classCTplLayout :publicGENERIC_LAYOUT{public:CTplLayout( UINT nIDTemplate ):GENERIC_LAYOUT(nIDTemplate){Init();}CTplLayout(){Init();}voidInit(){m_bModeReSizing=false;
        m_xAllow=sizeResize;
        m_yAllow=sizeResize;        
        m_bInited=false;}public:
    
    
    CSizeGetSizeDialog(UINT id);voidSetModeResizeCtrl(boolbEnable=true){m_bModeReSizing=bEnable;}boolm_bModeReSizing;enumeSizeType{sizeNone,                           
            sizeResize,                         
            sizeRepos,                          
            sizeRelative};protected:classCItem{public:
        UINT      m_resID;                  
        UINT      m_resIDChain;             
        eSizeType m_xSize;                  
        eSizeType m_ySize;                  
        CRect     m_rcControl;              
        CRect  m_rcInitial;
        CRect  m_rcInitialChain;boolm_bFlickerFree;doublem_xRatio;doublem_yRatio;doublem_xPercen;doublem_yPercen;boolm_bPercen;
        CSize  m_Space;protected:voidAssign(constCItem&src){m_rcControl=src.m_rcControl;
            m_rcInitial=src.m_rcControl;
            m_rcInitialChain=src.m_rcInitialChain;
            
            m_resID=src.m_resID;
            m_resIDChain=src.m_resIDChain;
            m_xSize=src.m_xSize;
            m_ySize=src.m_ySize;
            m_bFlickerFree=src.m_bFlickerFree;
            m_xRatio=src.m_xRatio;
            m_yRatio=src.m_yRatio;
            m_bPercen=src.m_bPercen;
            m_xPercen=src.m_xPercen;
            m_yPercen=src.m_yPercen;
            m_Space=src.m_Space;}public:CItem(){m_bPercen=false;}CItem(constCItem&src){Assign(src);}voidOnSize(HDWP hdwp,constCRect&rcParentOld,constCRect&rcParentNew,CWnd*pDlg){CSize diff;
            CRect rcControl;
            CWnd*pWnd;intnewpos,newsize;doublex;boolbx=false,by=false;
            
            
            pWnd=pDlg->GetDlgItem(m_resID);
            
            
            
            diff.cx=rcParentNew.Width()-rcParentOld.Width();
            diff.cy=rcParentNew.Height()-rcParentOld.Height();
            
            
            
            rcControl=m_rcControl;switch(m_xSize){casesizeResize:if(m_resIDChain){diff.cx/=2;
                    bx=true;}rcControl.right+=diff.cx;if(m_bPercen){x=m_rcInitial.Width()+(m_rcInitial.Width()*(m_xPercen/100.));if(static_cast<double>(rcControl.Width())>x)
                        rcControl.right=rcControl.left+static_cast<long>(x);if(rcControl.Width()<m_rcInitial.Width())
                        rcControl.right=m_rcInitial.right;}break;casesizeRepos:
                rcControl.left+=diff.cx;
                rcControl.right+=diff.cx;break;casesizeRelative:
                newpos=static_cast<int>((m_xRatio*(double)rcParentNew.Width())/(1.0+m_xRatio));
                newsize=rcControl.Width();
                rcControl.left=newpos;
                rcControl.right=newpos+newsize;break;}switch(m_ySize){casesizeResize:if(m_resIDChain){by=true;
                    diff.cy/=2;}rcControl.bottom+=diff.cy;if(m_bPercen){x=m_rcInitial.Height()+(m_rcInitial.Height()*(m_yPercen/100.));if(rcControl.Height()>static_cast<long>(x))
                        rcControl.bottom=rcControl.top+static_cast<long>(x);if(rcControl.Height()<m_rcInitial.Height())
                        rcControl.bottom=m_rcInitial.bottom;}break;casesizeRepos:
                rcControl.top+=diff.cy;
                rcControl.bottom+=diff.cy;break;casesizeRelative:
                newpos=static_cast<int>((m_yRatio*(double)rcParentNew.Height())/(1.0+m_yRatio));
                newsize=rcControl.Height();
                rcControl.top=newpos;
                rcControl.bottom=newpos+newsize;break;}if((rcControl!=m_rcControl)||(m_xSize!=m_ySize)){if(m_resID<=2){pWnd->MoveWindow(&rcControl);}elseDeferWindowPos(hdwp,*pWnd,NULL,
                                    rcControl.left,
                                    rcControl.top,
                                    rcControl.Width(),
                                    rcControl.Height(),
                                    SWP_NOZORDER);
                m_rcControl=rcControl;if(m_resIDChain&&(bx||by)){CRect rect;
                    pWnd=pDlg->GetDlgItem(m_resIDChain);
                    
                    pWnd->GetWindowRect(rect);
                    pDlg->ScreenToClient(rect);if(bx){x=rect.Width();
                        rect.left=rcControl.right+m_Space.cx;
                        rect.right=rect.left+static_cast<int>(x)+diff.cx;}if(by){x=rect.Height();
                        rect.top=rcControl.bottom+m_Space.cy;
                        rect.bottom=rect.top+static_cast<int>(x)+diff.cy;}DeferWindowPos(hdwp,*pWnd,NULL,
                                    rect.left,
                                    rect.top,
                                    rect.Width(),
                                    rect.Height(),
                                    SWP_NOZORDER);}}}CItem&operator=(constCItem&src){Assign(src);return*this;}};enum{m_idSizeIcon=0x4545};std::vector<CItem>m_Items;           
CRect              m_rcDialog;        
CPoint             m_MinSize;         
eSizeType          m_xAllow;          
eSizeType          m_yAllow;          
CBitmap            m_bmSizeIcon;      
CStatic            m_wndSizeIcon;boolm_bInited;public:voidInitDialog(CRect&Rect,BOOL bSetIcon=TRUE);voidInitDialogBar(UINT uResId);voidSetPercenMaxSize(constUINT resID,doubledysize,doubledxsize);voidAddChainControl(constUINT resIDSrc,constUINT resIDChain);voidAddControl(constUINT resID,consteSizeType xsize,consteSizeType ysize,constboolbFlickerFree=true);voidAllowSizing(consteSizeType xsize,consteSizeType ysize);voidHideSizeIcon(void);void_OnSize(UINT nType,intcx,intcy);
    BOOL_OnGetMinMaxInfo(MINMAXINFO*lpMMI);virtualLRESULTDefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam){if(nMsg==WM_SIZE ){_OnSize(wParam,LOWORD(lParam),HIWORD(lParam));}if(nMsg==WM_GETMINMAXINFO){_OnGetMinMaxInfo(reinterpret_cast<MINMAXINFO*>(lParam));}returnGENERIC_LAYOUT::DefWindowProc( nMsg, wParam,lParam);}};template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::SetPercenMaxSize(constUINT resID,doubledysize,doubledxsize){std::vector<CItem>::iterator it;if(m_Items.size()){for(it=m_Items.begin();it!=m_Items.end();it++){if(it->m_resID==resID){it->m_bPercen=true;
                it->m_xPercen=dxsize;
                it->m_yPercen=dysize;return;}}}}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::AddChainControl(constUINT resIDSrc,constUINT resIDChain){std::vector<CItem>::iterator it;if(m_Items.size()){for(it=m_Items.begin();it!=m_Items.end();it++){if(it->m_resID==resIDSrc){it->m_resIDChain=resIDChain;GetDlgItem(resIDChain)->GetWindowRect(it->m_rcInitialChain);ScreenToClient(it->m_rcInitialChain);
                it->m_Space.cx=it->m_rcInitialChain.left-it->m_rcControl.right;
                it->m_Space.cy=it->m_rcInitialChain.top-it->m_rcControl.bottom;return;}}}}template<classGENERIC_LAYOUT>CSize CTplLayout<GENERIC_LAYOUT>::GetSizeDialog(UINT id){intcy=0,cx=0;
    LPCTSTR lpszTemplateName;
    lpszTemplateName=MAKEINTRESOURCE(id);
    
    LPDLGTEMPLATE lpDialogTemplate=0;
    HGLOBAL hDialogTemplate=0;
    HINSTANCE hInst=AfxGetResourceHandle();if(lpszTemplateName!=NULL){hInst=AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
        HRSRC hResource=::FindResource(hInst, lpszTemplateName, RT_DIALOG);
        hDialogTemplate=LoadResource(hInst, hResource);}if(hDialogTemplate!=NULL)
        lpDialogTemplate=(LPDLGTEMPLATE)LockResource(hDialogTemplate);if(hDialogTemplate!=NULL){LOGFONT lf;
        CFont Font;memset(&lf,0,sizeof(lf));
        lf.lfHeight=-11;
        lf.lfWeight=400;strcpy(lf.lfFaceName,"MS Sans Serif");
        Font.CreateFontIndirect(&lf );
        CWnd*pWnd=AfxGetMainWnd();
        CDC*pDC=pWnd->GetDC();
        CFont*oldFont=pDC->SelectObject(&Font);
        TEXTMETRIC tm;
        pDC->GetTextMetrics(&tm );intbaseUnitY=tm.tmHeight;
        CSize size;
        size=pDC->GetTextExtent("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",52);intbaseUnitX=(size.cx/26+1)/2;    
        pDC->SelectObject(oldFont);
        Font.DeleteObject();
        
        cy=(lpDialogTemplate->cy*baseUnitY)/8;
        cx=(lpDialogTemplate->cx*baseUnitX)/4;}if(lpszTemplateName!=NULL||hDialogTemplate!=NULL)UnlockResource(hDialogTemplate);if(lpszTemplateName!=NULL)FreeResource(hDialogTemplate);returnCSize(cx,cy);}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::AddControl(constUINT resID,consteSizeType xsize,consteSizeType ysize,constboolbFlickerFree){CItem item;
    
    
    CWnd*pWnd=GetDlgItem(resID);
    pWnd->GetWindowRect(item.m_rcControl);ScreenToClient(item.m_rcControl);
    item.m_rcInitial=item.m_rcControl;
    item.m_bFlickerFree=bFlickerFree;
    item.m_resID=resID;
    item.m_resIDChain=0;
    item.m_xSize=xsize;
    item.m_ySize=ysize;
    item.m_bPercen=false;
    item.m_rcInitialChain=CRect(0,0,0,0);if(xsize==sizeRelative)
        item.m_xRatio=(double)item.m_rcControl.left/((double)m_rcDialog.Width()-(double)item.m_rcControl.left);if(ysize==sizeRelative)
        item.m_yRatio=(double)item.m_rcControl.top/((double)m_rcDialog.Height()-(double)item.m_rcControl.top);
    
    
    m_Items.push_back(item);}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::AllowSizing(consteSizeType xsize,consteSizeType ysize){m_xAllow=xsize;
    m_yAllow=ysize;}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::HideSizeIcon(void){m_wndSizeIcon.ShowWindow(SW_HIDE);}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::_OnSize(UINT nType,intcx,intcy){if(!m_bModeReSizing)return;
    CRect rect;
    HDWP hdwp;std::vector<CItem>::iterator it;if(m_Items.size()){if(IsKindOf(RUNTIME_CLASS(CFormView))){if(m_MinSize.x&&m_MinSize.y){if(cx<m_MinSize.x||cy<m_MinSize.y)return;}}GetWindowRect(rect);
        
        
        hdwp=BeginDeferWindowPos(20);for(it=m_Items.begin();it!=m_Items.end();it++)
            it->OnSize(hdwp,m_rcDialog,rect,this);EndDeferWindowPos(hdwp);}m_rcDialog=rect;}template<classGENERIC_LAYOUT>BOOL CTplLayout<GENERIC_LAYOUT>::_OnGetMinMaxInfo(MINMAXINFO*lpMMI){if(!m_bModeReSizing)returnFALSE;if(m_bInited){lpMMI->ptMinTrackSize=m_MinSize;if(m_xAllow==sizeNone)
            lpMMI->ptMaxTrackSize.x=lpMMI->ptMaxSize.x=m_MinSize.x;if(m_yAllow==sizeNone)
            lpMMI->ptMaxTrackSize.y=lpMMI->ptMaxSize.y=m_MinSize.y;returnTRUE;}returnFALSE;}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::InitDialogBar(UINT uResId){CSize size=GetSizeDialog(uResId);InitDialog(CRect(0,0,size.cx,size.cy),FALSE);}template<classGENERIC_LAYOUT>voidCTplLayout<GENERIC_LAYOUT>::InitDialog(CRect&Rect,BOOL bSetIcon){SetModeResizeCtrl();    
    
    CRect rcIcon,rcDialogClient,rcCurrent;
    m_rcDialog=Rect;if(!Rect.left&&!Rect.top&&!Rect.bottom&&!Rect.right){GetWindowRect(m_rcDialog);  
        Rect=m_rcDialog;}GetWindowRect(rcCurrent);
    
    m_MinSize.x=m_rcDialog.Width();
    m_MinSize.y=m_rcDialog.Height();if(bSetIcon){m_bmSizeIcon.LoadOEMBitmap(OBM_SIZE);
        m_wndSizeIcon.Create(NULL,
            WS_CHILD|WS_VISIBLE|SS_BITMAP,CRect(0,0,10,10),this,m_idSizeIcon);
        
        m_wndSizeIcon.SetBitmap(m_bmSizeIcon);GetClientRect(rcDialogClient);
        m_wndSizeIcon.GetWindowRect(rcIcon);ScreenToClient(rcIcon);
        m_wndSizeIcon.SetWindowPos(NULL,rcDialogClient.right-rcIcon.Width(),
            rcDialogClient.bottom-rcIcon.Height(),0,0,SWP_NOZORDER|SWP_NOSIZE);AddControl(m_idSizeIcon,sizeRepos,sizeRepos);}m_bInited=true;if(Rect!=rcCurrent)_OnSize(0,rcCurrent.Width(),rcCurrent.Height());}#endif // !defined(AFX_TPLLAYOUT_H__59DC7C67_79D6_4082_A38B_4CD17E8257C1__INCLUDED_)
 | 
utilisation avec une CFormView :
 | 
#include "TplLayout.hpp"classCTestMdILayoutView :publicCTplLayout<CFormView>{....
 | 
| 
CTestMdILayoutView::CTestMdILayoutView()
: CTplLayout<CFormView>(CTestMdILayoutView::IDD){}voidCTestMdILayoutView::OnInitialUpdate(){CFormView::OnInitialUpdate();
    
    CChildFrame*pChild=static_cast<CChildFrame*>(GetParentFrame());if(pChild->GetInitialRectFrame().IsRectNull()){ResizeParentToFit();}AddControl(IDC_STATICLIB,eSizeType::sizeResize,eSizeType::sizeRepos);AddControl(IDOK,eSizeType::sizeRepos,eSizeType::sizeNone);AddControl(IDCANCEL,eSizeType::sizeRepos,eSizeType::sizeNone);InitDialog(pChild->GetInitialRectFrame(),FALSE);}
 | 
pour une boîte de Dialogue (CDialog) Déclaration:
 | 
classCAboutDlg :publicCTplLayout<CDialog>{public:CAboutDlg();
 | 
code:
 | 
CAboutDlg::CAboutDlg() : CTplLayout<CDialog>(CAboutDlg::IDD){}BOOLCAboutDlg::OnInitDialog(){CDialog::OnInitDialog();AddControl(IDOK,eSizeType::sizeRepos,eSizeType::sizeNone);
    CRectRect(0,0,0,0);InitDialog(Rect,TRUE);returnTRUE;}
 | 
Note: le style resizing  doit être activé sur la dialogue dans l'éditeur de  ressources.
 pour une CDialogBar :
 la déclaration :
 
 | 
#include "TplLayout.hpp"classCMyDlgBar :publicCTplLayout<CDialogBar>{public:CMyDlgBar();voidInitDialog();
 | 
le code :
 | 
CMyDlgBar::CMyDlgBar(): CTplLayout<CDialogBar>(){}voidCMyDlgBar::InitDialog(){AddControl(IDC_BUTTON,eSizeType::sizeRepos,eSizeType::sizeNone);AddControl(IDC_STATIC1,eSizeType::sizeRepos,eSizeType::sizeNone);AddControl(IDC_EDIT1,eSizeType::sizeResize,eSizeType::sizeNone);InitDialogBar(IDD_DIALOGBAR);}
 | 
Initialisation de la CDialogBar à partir de la view:
 | 
voidCTestMdILayoutView::OnInitialUpdate(){CFormView::OnInitialUpdate();    
    CChildFrame*pChild=static_cast<CChildFrame*>(GetParentFrame());if(pChild->GetInitialRectFrame().IsRectNull()){ResizeParentToFit();}AddControl(IDC_STATICLIB,eSizeType::sizeResize,eSizeType::sizeRepos);AddControl(IDOK,eSizeType::sizeRepos,eSizeType::sizeNone);AddControl(IDCANCEL,eSizeType::sizeRepos,eSizeType::sizeNone);InitDialog(pChild->GetInitialRectFrame(),FALSE);
pChild->m_DlgBar.InitDialog();}
 | 
le positionnement est géré sur l'axe des X et Y :sizeNone      :  ne fait rien 
sizeResize   :  dimensionnement du contrôle proportionel 
sizeRepos     :  maintient la distance en fonction du point haut /gauche 
sizeRelative  :  distance proportionelle en fonction des côtés  
Les Fonctions:
void SetPercenMaxSize(const UINT resID,double dysize,double dxsize): 
Permet de spécifier la taille maximum de d'étirement sur la largeur et hauteur du contrôle identifié par resID
void AddChainControl(const UINT resIDSrc,const UINT resIDChain); 
Permet de lier  au déplacement d'un contrôle resIDSrc  un contrôle secondaire resIDChain
L'espace initial entre les deux est maintenu.
void AddControl(const UINT resID,const eSizeType xsize,const eSizeType 
ysize,const bool bFlickerFree=true); 
 
Fixe les modalités d'étirements du contrôle sur la largeur et ou hauteur .
void  InitDialog(CRect &Rect,BOOL bSetIcon=TRUE); 
Initialisation pour une classe CFormView et CDialog. 
mettre bSetIcon=FALSE pour une CFormView et TRUE pour une CDialog 
permettant d'afficher l'icone d'étirement en bas à droite.
void  InitDialogBar(UINT uResId); 
Initialisation d'une CDialogBar. 
uResId et l'identifiant de la CDialogBar permettant de calculer sa taille initiale de référence
Un exemple complet:
http://farscape.developpez.com/Samples/TestMdiLayout.zip
 | 
|  |  | auteur : Farscape |  | Il y a deux  manières de travailler avec des contrôles placés sur une fenêtre :La première méthode consiste à récupérer un pointeur sur la fenêtre du contrôle
Exemple :
 | 
CListBox *pListBox=static_cast<CListBox*>(GetDlgItem(IDC_LISTBOX)) ;
pListBox->AddString("coucou ") ;
CEdit*pEdit=static_cast<CEdit*>(GetDlgItem(IDC_EDIT)) ;
pEdit->SetWindowText("essai") ;
 | 
La deuxième consiste à associer une variable au contrôle, à ce niveau on dispose encore de deux possibilités,La variable associée peut être le contrôle lui-même un CEdit une CListBox etc, ou une variable pour manipuler le contenu du contrôle exemple :
 
 Dans le cas d'un contrôle CEdit il sera pratique de travailler avec une variable CString pour changer ou récupérer le contenu du CEdit .
 
 Cette association  peut se faire directement à partir  de l'éditeur de ressources :
 
 Dans l'éditeur de ressources sur le contrôle en question faire clic droit
 
 Avec Visual 6.0 :
 Sélectionner l'option ClassWizard ,puis l'onglet member variables et enfin le bouton Add Variable.
 Il ne reste plus qu'a renseigner le nom de la variable, indiquer le type de variable : contrôle ou valeur.
 Dans le cas de valeur le type de variable CString ,int ,long c'est suivant le type de contrôle .
 
 Avec Visual .net :
 Sélectionner l'option ajouter une variable.
 L'assistant d'ajout de variables apparaît, il ne reste plus qu'à sélectionner les différentes options : contrôle ou valeur .
 
 Examinons le code généré par Visual :
 Une variable est rajoutée dans la classe fenêtre ou est situé le contrôle :
 Exemple avec une variable de type CEdit et une variable CString attachée à ce même contrôle :
 Dans le .h de la classe :
 
 | 
protected:protected:DECLARE_MESSAGE_MAP()public:
CEdit m_EditCtrl;
CString m_strForEdit;};
 | 
dans le code :
 | 
CsamplenetView::CsamplenetView()
:CFormView(CsamplenetView::IDD)
,m_strForEdit(_T("")){}
 | 
La variable CString est initialisée dans le constructeur.
 | 
voidCsamplenetView::DoDataExchange(CDataExchange*pDX){CFormView::DoDataExchange(pDX);DDX_Control(pDX, IDC_EDITTEST, m_EditCtrl);DDX_Text(pDX, IDC_EDITTEST, m_strForEdit);}
 | 
C'est la fonction DodaExchange  qui établit le lien entre le contrôle Windows et les variables.
 
Cette fonction est appelée par la fonction UpdateData  et le premier appel initialise les liens notamment pour la variable contrôle (m_EditCtrl) qui va subclasser le contrôle windows.
 
Voir:   Comment mettre à jour les contrôles depuis leurs variables et vice-versa ? 
Note :  j'insiste ,le contrôle sera graphiquement prêt après le premier UpdateData(FALSE)  et pas avant,
celui étant fait par les MFC dans la fonction CFormView::OnInitialUpdate  pour une CFormView  ou CDialog::OnInitDialog  pour une CDialog .
| 
voidCFormView::OnInitialUpdate(){ASSERT_VALID(this);if(!UpdateData(FALSE))TRACE(traceAppMsg,0,"UpdateData failed during formview initial update.\n");CScrollView::OnInitialUpdate();}BOOLCDialog::OnInitDialog(){if(!UpdateData(FALSE)){TRACE(traceAppMsg,0,"Warning: UpdateData failed during dialog init.\n");EndDialog(-1);returnFALSE;}}
 | 
Conséquences :Toutes tentatives d'utilisations d'un contrôle avant l'exécution de ces fonctions se solderont par une assertion d'erreur.
 Exemple : faire m_EditCtrl.SetWindowText("coucou") ; dans le constructeur.
 
 Liste des erreurs communes en relation avec la fonction DodataExchange :
 Utiliser une variable dont le lien n'existe pas dans la fonction  provoquera l'erreur.
 
 | 
ASSERT(IsWindow(m_hWnd) );
 | 
Signifiant que le handle de fenêtre n'est pas initialisé.
 Changer par mégarde l'identifiant d'un contrôle sans faire de même dans la fonction provoquera aussi une erreur.
 Supprimer un contrôle dans les ressources et garder le lien dans la fonction provoquera aussi une erreur.
 
 Une fois ces initialisations faites on peut utiliser les deux formes de mise à jour et récupération de valeurs dans un contrôle .
 Récupération  d'une valeur sur un CEdit :
 
 Directement avec la fonction  GetWindowText .
 | 
CString str ;
m_EditCtrl.GetWindowText(str) ;GetDlgItem(IDC_EDITTEST)->GetWindowText(str) ;
 | 
Par la variable :
 Affectation d'une valeur à un CEdit :Directement avec la fonction SetWindowText :
 | 
CString str ="coucou";
m_EditCtrl.SetWindowText(str) ;GetDlgItem(IDC_EDITTEST)->SetWindowText(str) ;
 | 
Par la variable :
 | 
m_strForEdit="coucou";UpdateData(FALSE) ;
 | 
 | 
|  |  | auteur : matazz |  | J'ai vérifié pour les classes suivantes CListCtrl, CListBox, CTreeCtrl, et CComboBox, et cette astuce marche.Il se peut qu'il y ait d'autres contrôles qui le gèrent, à voir...
 
 En fait lors de la construction de la Liste (ou du Tree, ou du Combo), il est possible d'associer l'adresse d'un pointeur d'un objet personnalisé à chaque Item ajouté.
 
 Soit par exemple une de vos classes ClsMyData, avec des variables et des méthodes, un pointeur de cette classe sera stocké sur 32 bits soit un DWORD.
 Il suffit de créer une nouvelle instance de votre classe et de la stocker dans le Contrôle grâce à la méthode SetItemData
 
 
 | ClsMyData *MyObj=newClsMyData();
...CTreeControl::SetItemData(HTREEITEM hItem, DWORD dwItemData );CListBox::SetItemData(intnIndex, DWORD dwItemData );CListCtrl::SetItemData(intnItem, DWORD dwData );CComboBox::SetItemData(intnIndex, DWORD dwItemData );
 | 
Ensuite sur les évènement de clic (CTreeCtrl) ou de sélection (List et Combo) vous pouvez récupérer l'objet de votre classe tout simplement en utilisant GetItemData(...) :
 | 
ClsMyData *MyObj=(ClsMyData*)MyList.GetItemData(MyList.GetCurSel());
MyObj->AfficheCaractéristiques();
....
ClsMyData*MyObj=(ClsMyData*)MyTree.GetItemData(MyTree.GetSelectedItem( ));
MyObj->AfficheCaractéristiques();
....
 | 
 | 
|  |  | auteur : Farscape |  | L'idée de base est d'utiliser le composant graphique groupbox pour définir l'ensemble des composants à grouper.Ensuite ce composant par l'intermédiaire d'une classe spécialisée permettrait des manipulations sur l'ensemble des composants inclus dans sa surface.
 
 Exemple d'implémentation:
 l'include :
 | 
#if !defined(AFX_GROUP_H__AD9C45E9_1C19_44A4_B708_698ED49E178B__INCLUDED_)#define AFX_GROUP_H__AD9C45E9_1C19_44A4_B708_698ED49E178B__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000classCGroup :publicCButton{public:CGroup();public:public:boolShowGroup(intnCmdShow=SW_SHOW);boolEnableGroup(BOOL bEnable=TRUE);boolIsHide();boolIsEnable();public:virtual~CGroup();protected:DECLARE_MESSAGE_MAP()private:boolGetCtrlOnGroup();private:
    CArray<int,int>m_arIdCtrl;
    CArray<CRect,CRect>m_arRectCtrl;};#endif // !defined(AFX_GROUP_H__AD9C45E9_1C19_44A4_B708_698ED49E178B__INCLUDED_)
 | 
le .cpp
 | 
#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endifCGroup::CGroup(){}CGroup::~CGroup(){}boolCGroup::ShowGroup(intnCmdShow){if(!GetCtrlOnGroup())returnfalse;
    CWnd*pDialog=GetParent();for(inti=0;i<m_arIdCtrl.GetSize();i++) pDialog->GetDlgItem(m_arIdCtrl[i])->ShowWindow(nCmdShow);returntrue;}boolCGroup::EnableGroup(BOOL bEnable){if(!GetCtrlOnGroup())returnfalse;
    CWnd*pDialog=GetParent();for(inti=0;i<m_arIdCtrl.GetSize();i++) pDialog->GetDlgItem(m_arIdCtrl[i])->EnableWindow(bEnable);returntrue;}boolCGroup::GetCtrlOnGroup(){ASSERT(m_hWnd);if(m_arIdCtrl.GetSize())returntrue;
    
    CWnd*pDialog=GetParent();
    
    CRect rectGrp;GetWindowRect(&rectGrp);
    
    CWnd*pCtrl=pDialog->GetNextDlgTabItem(this);
    
    CRect rectCtrl,rectUnion;if(!pCtrl)returnfalse;do{pCtrl->GetWindowRect(&rectCtrl);if(rectGrp.PtInRect(CPoint(rectCtrl.left,rectCtrl.top))&&rectGrp.PtInRect(CPoint(rectCtrl.right,rectCtrl.top))&&rectGrp.PtInRect(CPoint(rectCtrl.left,rectCtrl.bottom))&&rectGrp.PtInRect(CPoint(rectCtrl.right,rectCtrl.bottom))){m_arIdCtrl.Add(pCtrl->GetDlgCtrlID());
            m_arRectCtrl.Add(rectCtrl);}elsebreak;
        pCtrl=pDialog->GetNextDlgTabItem(pCtrl);}while(pCtrl );return(m_arIdCtrl.GetSize()>0);}boolCGroup::IsHide(){if(!GetCtrlOnGroup())returnfalse;intnct=0;
    CWnd*pDialog=GetParent();for(inti=0;i<m_arIdCtrl.GetSize();i++) 
        nct+=!(pDialog->GetDlgItem(m_arIdCtrl[i])->IsWindowVisible());return(nct==m_arIdCtrl.GetSize());}boolCGroup::IsEnable(){if(!GetCtrlOnGroup())returnfalse;intnct=0;
    CWnd*pDialog=GetParent();for(inti=0;i<m_arIdCtrl.GetSize();i++) 
        nct+=pDialog->GetDlgItem(m_arIdCtrl[i])->IsWindowEnabled();return(nct==m_arIdCtrl.GetSize());}BEGIN_MESSAGE_MAP(CGroup, CButton)END_MESSAGE_MAP()
 | 
l'utilisation dans une CFormView:
 | 
voidCSampleSDIView::OnButton1(){m_group.EnableGroup(!m_group.IsEnable());}
 | 
Il suffit de mettre un groupbox dans la ressource, d'enlever la propriété visible et de déclarer une variable contrôle dessus en choisissant la classe CGroup.
 Attention aux conditions pour qu'un contrôle fasse partie d'un groupe :
 Le premier contrôle possède le style group et tab stop.
 L'ordre des tab stop doit être réglé au niveau des ressources (tab order).
 
 A adapter selon vos besoins..
 
 | 
|  |  | auteur : Farscape |  | En utilisant la fonction SetWindowPos qui permet de spécifier l'ordre des fenêtres (Z order) Le contrôle dynamique devra néanmoins disposer du style WS_TAB.
 
 Exemple avec un CEdit:
 | 
 CEdit*pEdit=newCEdit;
   pEdit->Create(ES_MULTILINE|WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER,CRect(10,10,100,100),this,1);
pEdit->SetWindowPos(pWndAfter,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
 | 
pWndAfter représente la fenêtre d'insertion dans l'ordre des fenêtres.
 On dispose d'autres modes voir MSDN, parmi les plus utiles:
 
 wndBottom: Place la fenêtre en bas du Z-order
 wndTop:  Place la fenêtre au sommet du Z-order.
 
 
 | 
|  |  | auteur : Farscape |  | Lors de la création dynamique d'un contrôle disposant du style WS_TABSTOP , il devient nécessaire de spécifier son placement dans l'ordre de tabulation (tab order) de la fenêtre. 
On Utilisera la méthode SetWindowPos  comme suit :
| 
CWnd *pWndAfter=GetNextDlgTabItem(NULL);
pWndDynCtrl->SetWindowPos(pWndAfter,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
 | 
dans mon exemple pWndDynCtrl sera placé dans l'ordre de tabulation aprés pWndAfter, qui est ici le premier contrôle dans l'ordre de tabulation. 
 | 
|  |  | auteur : Farscape |  | Parmi les nouveaux contrôles ajoutés aux MFC on trouve le "Command bouton control"L'éditeur de ressources de Visual 2008 permet l'ajout de ce composant directement dans la form .
 En fait un "command button control" est un bouton avec le style BS_COMMANDLINK ou BS_DEFCOMMANDLINK.
 L'association du contrôle à une variable contrôle sera donc du type CButton qui est la classe MFC de base pour gérer les boutons.
 
 Comment procéder :
 On spécifie le libellé du bouton dans l'éditeur de ressources ou par un classique SetWindowText dans le code.
 Une nouvelle méthode SetNote permet de définir le libellé de description.
 Enfin la méthode SetShield permet de changer l'icône pour celle du bouclier utilisée par Vista pour l'elévation des droits.
 
 | 
CString str=_T("ceci est un commentaire\nsur deux lignes");
m_Btn.SetNote(str);
m_BtnAcces.SetShield(TRUE);
 | 
l'exemple en image: 
 | 
|  |  | auteur : Farscape |  | Dans la Faq on trouve un post permettant d'implémenter un message privé   Comment implémenter un message supplémentaire à partir d'un contrôle ? 
 sur un contrôle à destination du parent. 
Un message ON_CONTROL appelle une fonction dans la classe parent sans argument particulier 
Pour illustrer le sujet je vais rajouter une notification double clic sur un contrôle Edit. 
On commencera par créer avec l'assistant une classe héritée de CEdit , puis on implémentera le message à intercepter et à relayer à la fenêtre parent.
| 
#define EDIT_LBUTTONDBLCLK 1 // evenement customvoidCTestEdit::OnLButtonDblClk(UINT nFlags, CPoint point){GetParent()->SendMessage(WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(), EDIT_LBUTTONDBLCLK),(LPARAM)GetSafeHwnd());CEdit::OnLButtonDblClk(nFlags, point);}
 | 
L'utilisation dans la classe parent :
 | 
BEGIN_MESSAGE_MAP(CTESTONCONTROLDlg, CDialog)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_CONTROL(EDIT_LBUTTONDBLCLK,IDC_EDITTEST,OnDblClickEdit)END_MESSAGE_MAP()voidCTESTONCONTROLDlg::OnDblClickEdit(){AfxMessageBox("coucou");}
 | 
 |  | lien :  Comment implémenter un message supplémentaire à partir d'un contrôle ? 
 | 
|  |  | auteur : Farscape |  | Après lecture de l'aide sur MSDN on pourrait penser que le style TBS_DOWNISLEFT puisse faire l'affaire, il n'en est rien.Le moyen le plus simple à ce jour est de faire un appel spécifique à la méthode SetPos comme suit.
 
 | 
MySlider.SetPos(MySlider.GetRangeMax()-x);
 | 
Où X représente la valeur initiale du déplacement souhaité. 
 | 
 
 
						Consultez les autres F.A.Q.
					 
  
 |  |