Arreter le fonctionnement d'un bouton (boucle while )

Résolu/Fermé
abyass Messages postés 18 Date d'inscription vendredi 30 juin 2017 Statut Membre Dernière intervention 21 août 2017 - Modifié le 16 août 2017 à 15:28
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 18 août 2017 à 17:55
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

[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
18 août 2017 à 12:21
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
abyass Messages postés 18 Date d'inscription vendredi 30 juin 2017 Statut Membre Dernière intervention 21 août 2017
18 août 2017 à 13:34
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 :)

.
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié le 18 août 2017 à 18:20
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.
0