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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

Adapter la taille d'une ChildFrame à celle de la vue qu'elle contient


Sujet :

MFC

  1. #1
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut Adapter la taille d'une ChildFrame à celle de la vue qu'elle contient
    Bonjour à tous,

    Dans un projet Visual Studio 2005 basé sur les MFC et dans un contexte MDI, je voudrais adapter la taille de la ChildFrame à celle de la vue qu'elle contient dès son ouverture.

    J'ai trouvé dans la FAQ un code proposé par Farscape, à placer dans le OnInitialUpdate de la vue et qui est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();
    Ce code fonctionne bien pour une vue de petite taille, mais il semble que dès que la vue atteint une certaine limite de taille, la ChildFrame adopte une taille inférieure à celle de la vue. Dans ce cas les ascenseurs apparaissent, mais la ChildFrame pourrait pourtant être plus grande à l'intérieur de la MainFrame maximisée.

    Quelqu'un sait-il comment résoudre ce problème ?
    Merci d'avance !

  2. #2
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    ça semble bizarre en effet ,
    mais c'est vrai que je ne me rend peut etre plus compte, vue que je memorise les tailles et position des fenetres que j'utilise...
    http://c.developpez.com/faq/vc/?page...SaveWindowsPos

  3. #3
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    Effectivement, une fois mémorisée la taille des fenêtres ne doit plus poser de problème. La mémorisation se fait donc dans le .ini de l'application ? Mais comment cela se passe-t-il quand x utilisateurs pointent tous sur le même .ini, sur lequel ils n'ont pas accès en écriture ? Je suppose qu'on peut aussi mémoriser dans la base de registre, mais je n'ai le temps de mettre ce mécanisme en place...

  4. #4
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    non si c'est le point ini de l'application il est unique par machine ...
    puisque stocké dans le repertoire windows.

  5. #5
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    Mais mon application et son .ini se trouvent dans un répertoire réseau, pas sur les machines des utilisateurs...

  6. #6
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    si tu n'as pas changé le chemin du .ini et si l'ecriture dans le .ini est active(dans initinstance)
    il doit s'enregistrer dans le repertoire windows du poste quelque soit l'emplacement de l'executable.

  7. #7
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    J'avoue que je ne comprends pas tout...
    La seule ligne de code concernant le .ini dans mon InitInstance est celle-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LoadStdProfileSettings(0)
    J'ai cherché sur mon propre poste, mais je n'ai pas retrouvé le .ini de l'application. Je crois que je n'utilise que celui du réseau...

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Êtes-vous sûrs que ces paramètres ne sont pas stockés dans la base de registre, avec des versions récentes de MFC ?

  9. #9
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    pour que l'ecriture dans le .ini de l'application soit active,
    il faut :
    désactiver:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // Change the registry key under which our settings are stored.
        // TODO: You should modify this string to be something appropriate
        // such as the name of your company or organization.
        SetRegistryKey(_T("Local AppWizard-Generated Applications"));
    dans InitInstance.
    et utiliser les fonctions de la classe d'application :GetProfileString etc...
    c'est le cas ?

  10. #10
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    Dans mon cas la méthode SetRegistryKey est appelée, mais pas celles du type GetProfileString.
    Si je comprends bien, en désactivant SetRegistryKey une copie locale du .ini est créée et même modifiée si on choisi la mémorisation du positionnement des fenêtres. C'est bien ça ?

  11. #11
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    Si l'appel SetRegistryKey est enlevé, les opérations réalisées avec GetProfileString etc, seront faites dans un .ini portant le nom de l'application et stockées dans le répertoire Windows du poste.
    Sinon ces informations sont stockées dans la section de la base de registre mentionnée par la fonction SetRegistryKey.

    le post ou je propose de sauvegarder les informations de positionnement ou taille des fenêtres stocke ses informations avec la fonction writeProfilexxxx
    suivant le paramétrage elle seront stockées dans la base de registre du poste ou dans le .ini ..
    c'est plus clair ?

  12. #12
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    J'ai compris. Je ne connaissais pas toutes ces possibilités. Merci de me les avoir expliquées. Je m'en servirait sans doute un jour, mais je dois reconnaître que pour l'instant je n'en ai pas vraiment le temps.

    Dans l'immédiat, ce qui me ferait plaisir ce serait de comprendre pourquoi la méthode ResizeParentToFit ne fonctionne pas dans tous les cas.

    Avec le débugueur je suis entré dans cette méthode pour l'une de mes vues qui posent problème.
    Le début de la méthode se présente comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    void CScrollView::ResizeParentToFit(BOOL bShrinkOnly)
    {
    	// adjust parent rect so client rect is appropriate size
    	ASSERT(m_nMapMode != MM_NONE);  // mapping mode must be known
    
    	// determine current size of the client area as if no scrollbars present
    	CRect rectClient;
    	GetWindowRect(rectClient);
    	CRect rect = rectClient;
    	CalcWindowRect(rect);
    	rectClient.left += rectClient.left - rect.left;
    	rectClient.top += rectClient.top - rect.top;
    	rectClient.right -= rect.right - rectClient.right;
    	rectClient.bottom -= rect.bottom - rectClient.bottom;
    	rectClient.OffsetRect(-rectClient.left, -rectClient.top);
    	ASSERT(rectClient.left == 0 && rectClient.top == 0);
    
    	// determine desired size of the view
    	CRect rectView(0, 0, m_totalDev.cx, m_totalDev.cy);
    	if (bShrinkOnly)
    	{
    		if (rectClient.right <= m_totalDev.cx)
    			rectView.right = rectClient.right;
    		if (rectClient.bottom <= m_totalDev.cy)
    			rectView.bottom = rectClient.bottom;
    	}
    ...
    Alors que la taille de la vue est largement inférieure à celle de la MainFrame qui est maximisée, il la limite dans le dernier test de cet extrait de code. J'ai essayé d'appeler la méthode en mettant le paramètre à FALSE, ce qui résoud le problème quand la MainFrame est maximisée, mais pas quand sa taille est réduite (dans ce cas, la vue est plus grande mais elle est coupée et les ascenseurs n'apparaissent pas).

    Mon problème vient donc de cette variable rectClient, à l'origine de la limitation de la taille de la ChildFrame. Pourquoi donc les dimensions de rectClient sont-elles inférieures à celles de rectView avant le test ?

    rectClient est issue de GetWindowRect(rectClient)...

    Quelqu'un comprend-t-il quelque chose ?

  13. #13
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    J'ai trouvé une solution !

    Comme je le disais, la méthode ResizeParentToFit fonctionnait tant que les dimensions de le vue étaient inférieures aux dimensions par défaut de la ChildFrame.
    Ne sachant pas du tout d'où provenait cette dimension par défaut qui n'était pas adaptée à la taille de la fenêtre principale, j'ai décidé d'en imposer une autre à la création de la ChildFrame. J'ai donc redéfini la méthode Create de ma ChildFrame comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    BOOL CChildFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle , const RECT& rect , CMDIFrameWnd* pParentWnd , CCreateContext* pContext)
    {
    	CRect r = rectDefault;
    	AfxGetMainWnd()->GetWindowRect(r);
    	r.DeflateRect(10, 10, 15, 80);
    	return CMDIChildWnd::Create(lpszClassName, lpszWindowName, dwStyle, r, pParentWnd, pContext);
    }
    En fait, je récupère les dimensions de la fenêtre principale, auxquelles je retire une bordure (notamment en bas pour l'affichage de la barre d'état) et je donne ces dimensions là à ma ChildFrame.

    Au moment de l'appel à ResizeParentToFit dans l'OnInitialUpdate de ma vue, la taille limite étant celle que j'ai définie, qui est largement supérieure à celle de ma vue (en mode maximisé), la méthode impose bien la taille de la vue à la ChildFrame.

  14. #14
    Membre éclairé
    Avatar de PetitPapaNoël
    Développeur informatique
    Inscrit en
    Septembre 2006
    Messages
    559
    Détails du profil
    Informations personnelles :
    Âge : 48

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 559
    Points : 749
    Points
    749
    Par défaut
    Après réflexion, la méthode proposée précedemment ne me convient pas entièrement. En effet, toutes les vues sont ouvertes dans le coin en haut à gauche et ne se décalent les unes par rapport aux autres lors de leur ouverture.

    J'ai donc supprimé la redéfinition de la méthode Create dans ma ChildFrame et j'ai complété la méthode ResizeParentToFit dans le OnInitialUpdate de mes vues de la façon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    	// Récupération du cadre de la MainFrame.
    	CRect rectMainF;
    	AfxGetMainWnd()->GetWindowRect(rectMainF);
     
    	// On en déduit les dimensions maximum possibles du cadre de la ChildFrame.
    	CRect rectMax(0, 0, rectMainF.Width() - 15, rectMainF.Height() - 80);
     
    	// Initialisation du cadre aux dimensions maximum obtenues.
    	GetParentFrame()->SetWindowPos(NULL, 0, 0, rectMax.Width(), rectMax.Height(), SWP_NOMOVE | SWP_NOZORDER);
     
    	// Adaptation du cadre aux dimensions de la vue.
    	GetParentFrame()->RecalcLayout();
    	ResizeParentToFit();
     
    	// Repositionnement éventuel de la vue.
    	CRect rectC;
    	GetParentFrame()->GetWindowRect(rectC);
    	AfxGetMainWnd()->ScreenToClient(rectC);
     
    	int versGauche, versHaut;
    	versGauche = versHaut = 0;
     
    	if (rectC.right > rectMax.right)
    		versGauche = (int) min(rectC.right - rectMax.right, rectC.left - rectMax.left);
     
    	if (rectC.bottom > rectMax.bottom)
    		versHaut = (int) min(rectC.bottom - rectMax.bottom, rectC.top - rectMax.top);
     
    	if (versGauche || versHaut)
    		GetParentFrame()->SetWindowPos(NULL, rectC.left - versGauche, rectC.top - versHaut, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    Ce n'est pas très élégant, mais ça marche très bien.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 30/11/2007, 12h40
  2. Adapter la taille d'une image en background d'un tableau
    Par Poutchou dans le forum Balisage (X)HTML et validation W3C
    Réponses: 10
    Dernier message: 27/04/2006, 16h53
  3. adapter la taille d'une fenêtre sur un JPanel
    Par Zorgloub dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 29/03/2006, 16h19
  4. [Débutant] Comment adapter la taille d'une image ?
    Par taupeniveau dans le forum Composants VCL
    Réponses: 3
    Dernier message: 14/02/2006, 18h00
  5. : Adapter la taille d'une grille
    Par SteelBox dans le forum C++Builder
    Réponses: 3
    Dernier message: 31/07/2003, 07h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo