Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009
-
24 avril 2008 à 15:29
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009
-
21 mai 2008 à 12:44
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).
cs_juju12
Messages postés966Date d'inscriptionsamedi 3 avril 2004StatutMembreDernière intervention 4 mars 20104 21 mai 2008 à 12:11
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
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 25 avril 2008 à 09:23
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.
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 25 avril 2008 à 11:18
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.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 5 mai 2008 à 09:38
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.
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 5 mai 2008 à 15:10
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.
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 16 mai 2008 à 11:29
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);
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 16 mai 2008 à 13:55
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
cs_juju12
Messages postés966Date d'inscriptionsamedi 3 avril 2004StatutMembreDernière intervention 4 mars 20104 16 mai 2008 à 15:58
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...
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 16 mai 2008 à 16:06
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;
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
cs_juju12
Messages postés966Date d'inscriptionsamedi 3 avril 2004StatutMembreDernière intervention 4 mars 20104 16 mai 2008 à 17:15
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 :
puis tu déclares ta fonction boucle comme tu l'as fait :
void* __cdecl CFenetre1Dlg::boucle(void* pFenetre1Dlg)
{
...
// et enfin :
((CFenetre1Dlg*)pFenetre1Dlg)->UpdateData();
}
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 19 mai 2008 à 09:46
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.
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 19 mai 2008 à 12:01
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;
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?
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 20 mai 2008 à 11:05
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.
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.
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 21 mai 2008 à 11:22
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.
Taurnil
Messages postés48Date d'inscriptionvendredi 8 décembre 2000StatutMembreDernière intervention 2 juillet 2009 21 mai 2008 à 11:34
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 :