Arreter le fonctionnement d'un bouton (boucle while ) [Résolu/Fermé]

Signaler
Messages postés
18
Date d'inscription
vendredi 30 juin 2017
Statut
Membre
Dernière intervention
21 août 2017
-
Messages postés
5478
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
3 mars 2021
-
Bonjour,
J'ai besoin de vos aides SVP.

Je suis entrain de développer une interface graphique avec les API win312 dont j'ai un bouton "Start" qui lance une communication UART avec une carte électronique en boucle infinie (while (1)) . En fait, l'appuie sur ce bouton ouvre le port et envoie et reçoit des messages. Et j'ai un deuxième bouton "Stop" que je veux qu'il arrête la communication et ferme le port dés qu'on appuie dessus.

D'après mes connaissances, ce sont des threads à traiter.

Voilà à peu prés le code (modifié car à la base il est plus long):

#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <tchar.h>
#include <setupapi.h>
#include <locale.h>


#define ID_B_START 0
#define ID_B_Stop 1
#define ID_B_Exit 2

HINSTANCE instance;

LRESULT CALLBACK procedureFenetrePrincipale(HWND, UINT, WPARAM, LPARAM);
void Communication (HANDLE hCom, DCB dcb);/*fonction qui ouvre le port ensuite lance une lecture dans une boucle while */
void Fermeture (HANDLE hCom, DCB dcb);


int WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeDAffichage)
{
HWND fenetrePrincipale;
MSG message;
WNDCLASS classeFenetre;
HMENU menu;

instance = cetteInstance;

menu = CreateMenu();
AppendMenu(menu, MF_POPUP, (UINT)sousMenu, L"File");



classeFenetre.style = 0;
classeFenetre.lpfnWndProc = procedureFenetrePrincipale; //fct callback
classeFenetre.cbClsExtra = 0;
classeFenetre.cbWndExtra = 0;

classeFenetre.hInstance = NULL;
classeFenetre.hIcon = LoadIcon(NULL, IDI_APPLICATION);
classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
classeFenetre.lpszMenuName = NULL;
classeFenetre.lpszClassName = L"classeF";

// On prévoit quand même le cas où ça échoue
if(!RegisterClass(&classeFenetre))
return FALSE;

fenetrePrincipale = CreateWindow(
L"classeF",
L"Interface STPM34 !",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
400,
NULL,
menu /* NULL si on n'a pas de menu sinon le non du menu Ou LoadMenu(instance, "ID_MENU")*/ ,
cetteInstance,
NULL);

if (!fenetrePrincipale)
return FALSE;

ShowWindow(fenetrePrincipale, modeDAffichage);
UpdateWindow(fenetrePrincipale);


while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}

LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetrePrincipale, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND bouton0 = {NULL};
static HWND bouton1 = {NULL};
static HWND bouton2 = {NULL};
static DCB dcb;
static HANDLE hCom;


switch (message)
{
case WM_CREATE:
bouton0= CreateWindow(
L"BUTTON",
L"Start",
WS_CHILD | WS_VISIBLE,
5,
125,
383,
30,
fenetrePrincipale,
(HMENU)ID_B_START,
instance,
NULL);

bouton1 = CreateWindow(
L"BUTTON",
L"Stop",
WS_CHILD | WS_VISIBLE,
5,
165,
383,
30,
fenetrePrincipale,
(HMENU)ID_B_Stop,
instance,
NULL);

bouton2 = CreateWindow(
L"BUTTON",
L"Exit",
WS_CHILD | WS_VISIBLE,
5,
205,
383,
30,
fenetrePrincipale,
(HMENU)ID_B_Exit,
instance,
NULL);
return 0;

case WM_COMMAND:
switch(LOWORD(wParam))
{


case ID_B_START:

Communication (hCom, dcb);
break;
case ID_B_Stop: /*Je veux dés que j'appuie sur ce bouton la commuincation s'arrete */
Fermeture ( hCom, dcb);
break;
case ID_B_Exit:
SendMessage(fenetrePrincipale, WM_DESTROY, 0, 0);
break;
}
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(fenetrePrincipale, message, wParam, lParam);
}
}





Quelqu'un pourra m'aider SVP pour gérer ceci.
Merci d'avance.


1 réponse

Messages postés
5478
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
3 mars 2021
928
Bonjour,

Ton code ne compile pas et tu n'expliques pas quel est ton problème.

Dans ces conditions, il est difficile de savoir par où commencer pour t'aider.

Chez moi, ce code corrigé compile avec mingw, sans erreurs, ni warnings, et affiche des messagebox lorsque l'on clique sur les boutons.

#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <tchar.h>
#include <setupapi.h>
#include <locale.h>


#define ID_B_START 0
#define ID_B_Stop 1
#define ID_B_Exit 2

/* prtotypes */

LRESULT CALLBACK procedureFenetrePrincipale(HWND, UINT, WPARAM, LPARAM);
void Communication (HANDLE hCom,  DCB dcb); /* fonction qui ouvre le port 
					       ensuite lance une lecture 
					       dans une boucle while */
void Fermeture (HANDLE hCom,  DCB dcb);

/* Dummy ffunctions */

void Communication (HANDLE hCom,  DCB dcb) {
	MessageBox(NULL, "Commmunicating", "Communication status",
			MB_ICONINFORMATION);
}

void Fermeture (HANDLE hCom,  DCB dcb) {
	MessageBox(NULL, "Stopped commmunicating", "Communication status",
			MB_ICONINFORMATION);
}

/* entry point */

int APIENTRY WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance, 
		LPSTR lignesDeCommande, int modeDAffichage)
{
	HWND fenetrePrincipale;
	MSG message;
	WNDCLASS classeFenetre;
	HMENU menu;

	menu = CreateMenu();
	HMENU sousMenu = CreatePopupMenu();
	AppendMenu(menu, MF_POPUP, (UINT)sousMenu, "File");



	classeFenetre.style = 0;
	classeFenetre.lpfnWndProc = procedureFenetrePrincipale; //fct callback
	classeFenetre.cbClsExtra = 0;
	classeFenetre.cbWndExtra = 0;

	classeFenetre.hInstance = NULL;
	classeFenetre.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
	classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
	classeFenetre.lpszMenuName = NULL;
	classeFenetre.lpszClassName = "classeF";

	// On préit quand mê le cas oùéoue
	if(!RegisterClass(&classeFenetre))
		return FALSE;

	fenetrePrincipale = CreateWindow( "classeF", "Interface STPM34 !",
			WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 
			400, 400, NULL,
			menu /* NULL si on n'a pas de menu sinon le non du 
				menu Ou LoadMenu(instance, "ID_MENU")*/ , 
			cetteInstance, NULL);

	if (!fenetrePrincipale) 
		return FALSE;
	CreateWindow("BUTTON", "Start", 
			WS_CHILD | WS_VISIBLE, 5, 125, 383, 30,
			fenetrePrincipale, (HMENU)ID_B_START,
			cetteinstance, NULL);

	CreateWindow("BUTTON", "Stop", 
			WS_CHILD | WS_VISIBLE, 5, 165, 383, 30,
			fenetrePrincipale, (HMENU)ID_B_Stop,
			cetteinstance, NULL);

	CreateWindow("BUTTON", "Exit", 
			WS_CHILD | WS_VISIBLE, 5, 205, 383, 30,
			fenetrePrincipale, (HMENU)ID_B_Exit,
			cetteinstance, NULL);

	ShowWindow(fenetrePrincipale, modeDAffichage);
	UpdateWindow(fenetrePrincipale);


	while (GetMessage(&message, NULL, 0, 0)) {
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	return message.wParam;
}

/* callback */

LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetrePrincipale, 
		UINT message, WPARAM wParam, LPARAM lParam)
{
	static DCB dcb;
	static HANDLE hCom;


	switch (message) {
	case WM_COMMAND:
		switch(LOWORD(wParam)) {
			case ID_B_START:
				Communication (hCom,   dcb);
				break;
			case ID_B_Stop: /*Je veux déque j'appuie sur c
					  e bouton la commuincation s'arrete */
				Fermeture (hCom, dcb);
				break;
			case ID_B_Exit:
				SendMessage(fenetrePrincipale, WM_DESTROY, 0, 0);
				break;
		}
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	default:
		return DefWindowProc(fenetrePrincipale, message, 
				wParam, lParam);
	}
}

Dal
1
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 65492 internautes nous ont dit merci ce mois-ci

Messages postés
18
Date d'inscription
vendredi 30 juin 2017
Statut
Membre
Dernière intervention
21 août 2017

Merci pour votre réponse.

Le code ne compile pas parce que je n'ai pas écrit la fonction Communication et Fermeture. En plus, je l'ai tiré d'un gros code qui contient d'autres fonctions donc ça peut que j'ai oublié des paramètres ou un truc pareil.


En fait, je suis entrain de développer une interface graphique avec les API win32. J'ai un premier bouton "Start" dont son appuie ouvre la communication sur le port UART avec une carte électronique ainsi que l'écriture et la lecture des messages.
En effet, à travers cette communication je traite des données et je les stocke ensuite dans une base de donnée. Je veux que communication soit en boucle infinie et ne s'arrête que lorsque j'appuie sur le deuxième bouton qui doit stopper ainsi cette boucle et ferme le port .
Donc mon problème est comment arrêter cette boucle while lorsque j'appuie sur STOP.


Comme j'ai dit, d'après ce que j'ai vu et mes connaissances de bases, il s'agit d'une manipulation des threads.
J'ai compris que lorsque j'appuie sur le premier bouton, je dois lancer un thread qui va exécuter ce while(1) et vérifier l'état d'une variable qui va permettre d'interrompre la boucle infinie.
Lorsque j'appuie sur le second bouton, je dois changer l'état de cette variable pour sortir de cette boucle infinie.

Mes connaissances en Thread est vraiment basique et c'est pour ça que je suis bloquée.

Merci d'avance :)

.
Messages postés
5478
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
3 mars 2021
928
Je ne suis pas très copain avec les threads Windows, mais j'imagine que tu peux allouer cette variable sur le tas (avec malloc), et passer son pointeur à _beginthread, comme proposé là :

https://stackoverflow.com/questions/3169009/passing-arguments-to-beginthread-whats-wrong

ou utiliser une variable globale, comme dans l'exemple décrivant l'usage de _beginthread et _endthread ici : https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/beginthread-beginthreadex?redirectedfrom=MSDN&view=msvc-160&viewFallbackFrom=vs-2019#Anchor_5

et faire en sorte que ton thread se termine lorsque la variable change à la valeur signifiant d'interrompre la communication.

Autrement, on devrait pouvoir faire sans threads, en utilisant la boucle de la pompe à messages de Windows et en écrivant ou en lisant sur le port série de façon non bloquante.