Ma fenêtre veut pas s'ouvrir... (MFC)

Résolu
Signaler
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009
-
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009
-
Bonjour à tous, je suis actuellement sur un projet qui vise à piloter le port série à l'aide d'une petite interface utilisateur.
Cette interface est réalisée à l'aide de la MFC de Visual C++ (je travaille avec la version 6.0).

J'en arrive à mon problème :

Dans mon programme (qui est en fait un temporisateur), je dois vérifier l'heure de l'horloge et si celle-ci est égale à l'heure rentrée par l'utilisateur dans la fenêtre, on envoie un "1" sur une des broches de mon port COM.
Je teste donc l'heure en continu avec ce bout de programme :

code :
<hr size="2" width="100%" />
while (true) {
        curTime = CTime::GetCurrentTime();
        heure = curTime.GetHour(); //séparation heures-minutes
        minute = curTime.GetMinute();
                if (heure m_heurefermeture && minute m_minutefermeture) {            
          // Mise à 0 DTR
  EscapeCommFunction(g_hCOM, CLRDTR);
 PurgeComm(g_hCOM, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
        UpdateData(TRUE);
        } else if (heure m_heureouverture && minute m_minuteouverture) {
         //Mise à 1 DTR    
     PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
    EscapeCommFunction(g_hCOM, SETDTR);       
        }
        m_heure = heure;        //affichage pour test            
        m_minute = minute;
        UpdateData(FALSE);
        Sleep(30000);}
    return TRUE;  // return TRUE  unless you set the focus to a control
}
<hr size="2" width="100%" />Vous l'avez donc compris, la boucle se répète en continu toutes les 30 secondes.

Mais le problème est là : J'ai l'impression que mon programme essaie de finir la boucle avant d'ouvrir ma fenêtre alors que celle-ci ne se termine jamais.

Je sais pas comment faire, j'ai entendu parler de threads mais c'est encore un peu compliqué pour moi.

Si quelqu'un trouve quelquechose d'autre, qu'il n'hésite pas. Sinon, un lien vers un tuto sur les threads serait le bienvenu (en français si c'est possible).

A tous merci d'avance, si quelqu'un arrive à me sortir de là, je lui en serais (vraiment très reconnaissant).

22 réponses

Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
tu fais void* __cdecl CFenetre1Dlg::boucle(void *pFenetre1Dlg)
et pour modif des paramètres c'est comme pour appeler ::UpdateData() :
CFenetre1Dlg* pFen1=(CFenetre1Dlg*)pFenetre1Dlg;
pFen1->m_heure, pFen1->m_minute
Messages postés
793
Date d'inscription
mardi 8 juillet 2003
Statut
Membre
Dernière intervention
10 février 2021
8
pourquoi n'utilises tu pas les timers?

louis14
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Salut Louis, à vrai dire si je n'utilise pas les timers, c'est parce que je ne connaissais pas. Quand tu parles de timers, tu parles de fonction du type SetTimer(blabla, durée, NULL);  et KillTimer(blabla); ?

Si c'est de ça que tu parles, on ne peut utiliser ces fonctions (si j'ai bien compris), que pour travailler avec des intervalles de temps : et dans mon programme, l'utilisateur peut changer d'heure chaque jour, donc l'intervalle peut changer. De plus, l'utilisateur rentre une heure et pas un intervalle de temps.

Si c'était pas de ça dont tu parlais ou si tu n'es pas d'accord avec ce que j'ai dit, je suis évidemment ouvert à toutes critiques/suggestions.

Merci à tous d'avance.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Bon, je viens de tester quelque petites choses : la fenêtre ne s'ouvre toujours pas (ça serait trop beau) mais TOUT le reste du programme a l'air de fonctionner, si tant est qu'on rentre les heures d'ouverture et de fermeture directement dans le code.

En effet, si j'initialise (par exemple) heure d'ouverture à 10h10 et heure de fermeture à 10h11, et bien mon électrovanne s'ouvre bien à 10h10 pour se fermer à 10h11.

Il me manque plus que ma fenêtre pour pouvoir entrer les heures sans passer par la source......

De grâce..... J'y suis presque.

Merci d'avance.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

J'avance plus, j'ai entendu parler de pompes à messages et de thread de travail à utiliser, si quelqu'un pouvait me mettre sur la voie de ce côté là ou même me trouver quelque chose d'autre, merci à lui de se manifester .

Voila, en attendant vos réponses qui, je l'espère seront nombreuses, <strike>veuillez agréer madame, mons....,</strike> une bonne journée à tous.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Bon, bah ça marche, ma fenêtre s'ouvre et en même temps la boucle tourne.

J'ai toujours un probleme cependant, quand j'appelle UpdateData(FALSE ou TRUE) dans le thread j'ai ça qui sort :

error C2065: 'UpdateData' : undeclared identifier

Alors que quand j'appelle dans le main, pas d'erreur.
Quelqu'un sait il pourquoi ?

Bon, si quelqu'un veut avoir plus de détail sur comment j'ai fais, envoyez moi un mp plutôt que de poster ici. Encore que comme ça ça fera un peu moins monologue.

Allez ++ et bonne journée a tous.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

J'ai trouvé pourquoi j'avais le problème de UpdateData : undeclared identifier.

En fait cette fonction est une fonction de CWnd, la fonction qui l'appelle doit donc être membre de CWnd ou d'une classe dérivant de CWnd.

Bon, j'ai toujours un problème, je pense que j'aurais toujours pas de réponses mais bon (c'est mon 6ème post d'affilée) , je vous montre quand même les qques parties du programme qui posent problème :

voilà ma déclaration de la fonction dans la classe CFenetre1Dlg:
<hr size="2" width="100%" />
class CFenetre1Dlg : public CDialog
{
// Construction
public:
CFenetre1Dlg(CWnd* pParent = NULL); // standard constructor
 
void *__cdecl boucle(void*);
[...]
};
 

<hr size="2" width="100%" />Ma fonction dans le main :
<hr size="2" width="100%" />void* CFenetre1Dlg:: boucle(void*)
{
[...]//ma fonction boucle
};

<hr size="2" width="100%" />
Et enfin la déclaration de ma fonction dans le thread :
<hr size="2" width="100%" />
pthread_create(&thread, NULL, __cdecl CFenetre1Dlg:: boucle, NULL);

<hr size="2" width="100%" />
Alors, avec ça, j'ai l'erreur suivante :


error C2059: syntax error : '__cdecl'

Donc, voilà, si quelqu'un sait comment régler le problème... Merci à lui de se manifester, bonne journée à tous ^^
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

J'ai relu un truc qui m'a fait corriger l'erreur précédente, en fait
pthread_create exige une fonction libre ou une fonction membre
statique. Donc j'ai redeclaré comme suit :
Code : C
staticvoid*__cdeclboucle(void*);


L'erreur n'est plus là mais une nouvelle est apparue ...


La voici :

error C2352: 'CWnd::UpdateData' : illegal call of non-static member function

see declaration of 'UpdateData'


Voilà... Merci mille fois si vous pouvez m'aider.
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
je suppose que ta fonction UpdateData tu l'appelles depuis boucle()?
dans ce cas ça ne peut pas marcher puisque UpdateData() est fonction membre donc il faut une instance de classe (convention __thiscall), alors que boucle() est static donc ne concerne pas d'instance.
Pour régler ce problème, ce que tu peux faire par exemple est passer un pointeur sur une instance de classe comme paramètre à ton thread et l'utiliser ainsi.

Si c'était pas ça du tout mets un peu plus de code...
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

En effet, j'appelle UpdateData depuis boucle, bah j'ai pas trop compris ce qu'il fallait que je change alors je te met le code de la fonction boucle et de l'appel par le thread ainsi que mon .h, c'est parti :

Fonction boucle:
<hr size="2" width="100%" />void* CFenetre1Dlg:: boucle(void*Fenetre1Dlg)
{
    while (true) {
int    heure,m_heurefermeture,minute,m_minutefermeture,m_heureouverture,m_minuteouverture,m_heure,m_minute;

AfxMessageBox("mise a jour 30 secondes",NULL);
            CTime curTime = CTime::GetCurrentTime();
        heure = curTime.GetHour(); //séparation heures-minutes
        minute = curTime.GetMinute();
                if (heure m_heurefermeture && minute m_minutefermeture) {           
       EscapeCommFunction(g_hCOM, CLRDTR);
 PurgeComm(g_hCOM, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
  AfxMessageBox("fermeture électrovanne", MB_ICONSTOP);      

         } else if (heure m_heureouverture && minute m_minuteouverture) {
            PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
    EscapeCommFunction(g_hCOM, SETDTR);
     AfxMessageBox("ouverture électrovanne", MB_ICONSTOP);      

        }

m_heure = heure;        //affichage pour test           
        m_minute = minute;

Sleep(30000);
    }
UpdateData(TRUE);

return 0;
}
<hr size="2" width="100%" />
Ensuite, l'appel de la fonction par le thread :
<hr size="2" width="100%" />pthread_t thread;

pthread_create(&thread, NULL, CFenetre1Dlg:: boucle, NULL);
<hr size="2" width="100%" />
Et pour finir le code du .h
<hr size="2" width="100%" />#if !defined(AFX_FENETRE1DLG_H__72AE1160_5639_400E_8E40_87DB8B00238F__INCLUDED_)
#define AFX_FENETRE1DLG_H__72AE1160_5639_400E_8E40_87DB8B00238F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// CFenetre1Dlg dialog

           

class CFenetre1Dlg : public CDialog
{
// Construction
public:
    CFenetre1Dlg(CWnd* pParent = NULL);    // standard constructor

static void *__cdecl boucle(void*);

// Dialog Data
    //{{AFX_DATA(CFenetre1Dlg)
    enum { IDD = IDD_FENETRE1_DIALOG };
    BOOL    m_activer;
    int        m_heurefermeture;
    int        m_minutefermeture;
    int        m_heureouverture;
    int        m_minuteouverture;
    int        m_heure;
    int        m_minute;
    //}}AFX_DATA

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CFenetre1Dlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL

// Implementation
   
protected:
    HICON m_hIcon;

    // Generated message map functions
    //{{AFX_MSG(CFenetre1Dlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    virtual void OnCancel();
    afx_msg void Onapropos();
    afx_msg void OnCheck1();
    afx_msg void OnButton2();
    afx_msg void OnButton3();
    afx_msg void Onhautheurefermeture();
    afx_msg void Onbahheurefermeture();
    afx_msg void Onhautminutefermeture();
    afx_msg void Onhautminuteouverture();
    afx_msg void Onbasminuteouverture();
    afx_msg void Onhautheureouverture();
    afx_msg void Onbasheureouverture();
    afx_msg void Onbasfermeturemin();
    afx_msg void OnOuvrirelectrovanne();
    afx_msg void OnFermerelectrovanne();
    afx_msg void Onheureouvertureh();
    afx_msg void Onheureouverturemin();
    afx_msg void Onheurefermetureh();
    afx_msg void Onheurefermeturemin();
    afx_msg void OnChangeEdit5();
    afx_msg void OnChangeEdit6();
    afx_msg void OnButton9();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_FENETRE1DLG_H__72AE1160_5639_400E_8E40_87DB8B00238F__INCLUDED_)
<hr size="2" width="100%" />
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Voilà, j'espère que ça pourra t'aider à m'aider. ^^
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
Le principe est simple :
la fonction UpdateClass() est membre de classe, c'est-à-dire qu'elle agit sur une certaine instance de classe que tu références à l'intérieur par le pointeur this. Ce pointeur est passé implicitement par le compilateur en premier paramètre de la méthode.

exemple :
class A{int i; void Set(int _i)};

void A::Set(int _i){i=_i; return;} // Set() est de convention d'appel __thiscall
en réalité transcrit en void A::Set(A* const this,int _i){this->i=_i;return;} // Set() est de convention __cdecl

Donc forcément, pour pouvoir appeler une fonction membre de classe, il faut que le compilateur sache de quelle instance on est en train de parler...d'où la syntaxe :
A clsA;
clsA.Set(2);
en réalité transcrit en A::Set(&clsA,2); // ou quelque chose comme ça...


Par contre, une fonction static n'agit sur aucune instance en particulier; il s'agit d'une fonction quasiment normale, et
le compilateur ne lui passe pas de pointeur en argument implicite : effectivement on ne peut pas utiliser this dans une fonction static.

Pour en revenir à ton problème, j'espère que tu vois d'où ça vient à présent :
tu est obligé d'utiliser une fonction static pour créer le thread car pthread_create demande une fonction __cdecl et les fonctions membre sont __thiscall...Mais pour utiliser UpdateData(), qui est une fonction membre, tu as besoin d'une instance de classe à l'intérieur du thread. C'est logique en soit : tu lui demandes de mettre à jour une fenêtre, faut bien lui dire laquelle...

Solution : tu passes en argument du thread un pointeur sur la classe:
en fait ça dépend d'où tu l'appelles, si tu est dans une fonction membre de CFenetre1Dlg tu peux utiliser this :
void CFenetre1Dlg::LauchTread(void)
{
...
pthread_create(&thread,NULL,CFenetre1Dlg::boucle,this);
...
}

ou alors si tu n'est pas dans une fonction membre, genre dans static ou dans main :


CFenetre1Dlg cfDlg;
pthread_create(&thread,NULL,CFenetre1Dlg::boucle,&cfDlg);

puis tu déclares ta fonction boucle comme tu l'as fait :
void* __cdecl CFenetre1Dlg::boucle(void* pFenetre1Dlg)
{
...
// et enfin :
((CFenetre1Dlg*)pFenetre1Dlg)->UpdateData();
}
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Bon, bah déjà, merci beaucoup pour le temps que tu passes à m'aider.

Il n'y a plus aucune erreur mais je ne comprends pas, j'avais utilisé UpdateData() pour mettre les valeurs de certaines de mes editbox à jour, c'est bien la fonction à utiliser?

Je m'explique, j'ai des editbox qui affichent les heures et les minutes courantes, et quand j'ouvre ma fenêtre, je voudrais que ces heures et minutes suivent le temps, c'est a dire qu'elles avancent au même rythme (a peu près à cause du sleep(30s)) que l'horloge.

Je pensais qu'avec UpdateData(); ça marcherait mais non...

En plus je dois faire ça pour plusieurs autre edit pour lesquelles c'est l'utilistateur qui décide de leur valeur.

Bah voilà, si quelqu'un a une idée.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

En fait, je m'étais planté, j'utilisais un UpdateData(TRUE) pour rafraichir un truc à l'écran alors que c'est FALSE qu'il faut envoyer à UpdateData pour faire ça...
Quand je m'en suis rendu compte, j'y ai cru et j'ai modifié de cette manière :

<hr size="2" width="100%" />
        void* __cdecl CFenetre1Dlg::boucle(void* pFenetre1Dlg)
{
    while (true) {
int    heure,m_heurefermeture,minute,m_minutefermeture,m_heureouverture,m_minuteouverture,m_heure,m_minute;

            CTime curTime = CTime::GetCurrentTime();
        heure = curTime.GetHour(); //séparation heures-minutes
        minute = curTime.GetMinute();
        if (heure m_heurefermeture && minute m_minutefermeture) {           
       EscapeCommFunction(g_hCOM, CLRDTR);
 PurgeComm(g_hCOM, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
  AfxMessageBox("fermeture électrovanne", MB_ICONSTOP);      
((CFenetre1Dlg*)pFenetre1Dlg)->UpdateData(TRUE);
         } else if (heure m_heureouverture && minute m_minuteouverture) {
            PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
    EscapeCommFunction(g_hCOM, SETDTR);
((CFenetre1Dlg*)pFenetre1Dlg)->UpdateData(TRUE);
        }

m_heure = heure;        //affichage pour test           
        m_minute = minute;
((CFenetre1Dlg*)pFenetre1Dlg)->UpdateData(FALSE);
Sleep(30000);
    }

}
<hr size="2" width="100%" />Mais au bout de 30 sec il m'envoie une messagebox dont je te mets le contenu ci-dessous :

<hr size="2" width="100%" />
Runtime error

Program : ...\Fenetre1.exe


This application has requested the runtime to terminate it in an unusual way.

Please contact blablabla.<hr size="2" width="100%" />J'ai fait quoi pour qu'il s'énerve comme ça?
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Un peu de nouveau, j'ai essayé ce code :

<hr size="2" width="100%" />        void* __cdecl CFenetre1Dlg::boucle(void* pFenetre1Dlg)
{
    CFenetre1Dlg * pFen = static_cast<CFenetre1Dlg *>(pFenetre1Dlg);
    while (true) {
        int heure, minute;

            CTime curTime = CTime::GetCurrentTime();
        heure = curTime.GetHour(); //séparation heures-minutes
        minute = curTime.GetMinute();
        if (heure pFen->m_heurefermeture && minute pFen->m_minutefermeture) {           
       EscapeCommFunction(g_hCOM, CLRDTR);
 PurgeComm(g_hCOM, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
  AfxMessageBox("fermeture électrovanne", MB_ICONSTOP);      
pFen->UpdateData(TRUE);
         } else if (heure pFen->m_heureouverture && minute pFen->m_minuteouverture) {
            PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
    EscapeCommFunction(g_hCOM, SETDTR);
pFen->UpdateData(TRUE);
        }

pFen->m_heure = heure;        //affichage pour test           
        pFen->m_minute = minute;
pFen->UpdateData(FALSE);
Sleep(30000);
    }

}
<hr size="2" width="100%" />Bon, 0 erreurs à la compilation et 0 erreurs au link par contre, il m'envoie dès le début du programme un petite fenêtre : "Fenetre1.exe a rencontré un erreur et doit fermer, blablabla, envoyer le rapport d'erreurs, blabla", j'ai fait quoi là encore?
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

J'ai un gros problème, je sais pas ce que j'ai fait mais j'ai une erreur que je sais pas du tout comment résoudre :

fatal error C1083: Cannot open precompiled header file: 'Release/Fenetre 1.pch': No such file or directory

C'est quoi? Ca me renvoie sur la ligne : #include "stdafx.h" et quand je fais un rebuild all, il me trouve 19 erreurs diverses et variées, je les mets pas pour l'instant, dites moi si vous en avez besoin mais le problème à la compilation génère peut-être toutes les autres erreurs.

Aidez-moi s'il vous plait... J'en peux plus.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Bon, j'ai plus cette erreur avec Fenetre1.pch, mais j'en ai une autre :

fatalerrorC1083:Cannotopenincludefile:'bios.h':Nosuchfileordirectory


Quelqu'un peut m'aider? Ah au fait, pour résoudre l'autre erreur, j'ai
recopié le fichier des include d'une version sauvegardée de VC++6.
Maintenant, je sais pas pourquoi j'ai un problème avec bios.h.


De l'aide serait la bienvenue.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Bon, ça marche, j'en ai chier comme on dit, mais ça marche.

Je vais tester avec le this en dernier paramètre du thread et je dirais tantôt si ça marche, a bientôt ^^
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Bon, ça marche pas, en fait je voudrais déjà que l'heure avance sur ma fenêtre au même rythme que l'heure de l'horloge (a 30 secondes près). Je pensais qu'en utilisant des UpdateData(FALSE) apres mes

m_heure = heure;        //affichage pour test           
        m_minute = minute;

Ca marcherait. Si quelqu'un a une idée, qu'il n'hésite pas, merci d'avance.
Messages postés
48
Date d'inscription
vendredi 8 décembre 2000
Statut
Membre
Dernière intervention
2 juillet 2009

Je viens de remarquer à l'instant qu'il y a un gros problème...

En fait, dans ma fonction boucle, les variables m_heurefermeture, m_minuteouverture, etc ne sont pas les mêmes que celles du main, donc celles associées aux edit... Du coup, évidemment que ça marche pas.
Comment on fait avec ma fonction pour qu'elle prenne en paramètre ces 4 variables? Avec une fonction libre c'est pas compliqué mais vu la tête de la déclaration de ma fonction :

void* __cdecl CFenetre1Dlg::boucle(void* pFenetre1Dlg)
{...}


Je mets ou mes paramètres la-dedans?
Merci à tous ceux qui pourront m'aider.