Citation:
C'est comme si m_rect était modifié par le reste du code pendant que la fonction trace_rect_rect2(CDC* pDC) était executée
Pour moi, c'est très très improbable car les applications MFC sont, par défaut, mono-threadé et ne supportent pas plusieurs threads dans les composants graphiques.
MFC utilise une pompe à message pour la gestion des évènements. Pendant la gestion d'un évènement, aucun autre évènement n'est traité.
Je ne vois pas dans le nommage des variables un attention particulière faite aux coordonnées lors du précédent affichage.
Pour que le XOR fonctionne, vous devez appeler 2 fois l'affichage :
- une première fois, sur les anciennes coordonnées, pour effacer le précédent rectangle
- une seconde fois, sur les "nouvelles" coordonnées pour afficher le rectangle aux nouvelles coordonnées.
Utilisez les primitives de trace des MFC 'TRACEx" pour voir les valeurs des coordonnées du vieux rectangle et du nouveau rectangle.
S'ils ne s'affichent pas par paire identiques (les nouvelles coordonnées deviennent les anciennes, etc...), c'est qu'il y a un problème dans votre code.
Je suis très circonspect sur la réponse de @fred1599. J'ai l'impression qu'il n'a pas pris en compte les spécificités des MFC et en particulier son modèle de threading.
Citation:
Je passe par référence et non par valeur (avec le '&') - et ça fonctionne
Absolument pas. Quand vous utilisez un "&" (esperluette) lors d'un appel, vous ne faite pas un appel par référence mais vous passez un pointeur sur l'objet.
Comme la fonction Rectangle prend aussi bien un LPCRECT (https://learn.microsoft.com/en-us/cp...-170#rectangle) qu'un quadruplé de int et que la classe CRect doit avoir un opérateur de cast de CRect* vers LPCRECT, ça passe (à moins que des warnings s'allument sur ces lignes un peu dégueu).
Mais c'est pas un passage par référence ni pas valeur, mais par "pointeur nus".
Citation:
D'après vous, la solution serait donc de passer m_rect par valeur et non pas par référence
Cela pourrait corriger un cas d'erreur que je trouve très très improbable.
Pour moi, le cas le plus probable, c'est que les appels d'affichage et d'effacement ne sont pas correctement "apparaillés". cf.urilisation de TRACEx ci-avant.
Citation:
Concernant la "vraie" solution, c'est à dire le mutex, comme vous dites c'est du C++ "moderne"
Et justement, le programme sur lequel je travaille est un vieux projet open source C++ WIN32 obsolète que j'ai repris, je ne sais pas si le mutex sera accepté,
et si ça marche j'ai peur de créer d'autres bugs ailleurs que je ne verais pas tout de suite
Le framework des MFC fait que vous n'avez pas besoin de ces "nouvelles" fonctionnalités.
Citation:
Cela me rappelle de mauvais souvenir avec Visual Basic.
En Visual Basic on arrivait à gérer ces problèmes de façon plus ou moins sale avec DoEvents, et aussi en verrouillant "manuellement" les fonctions avec une variable globale "autorisation_paint" gérée de la manière suivante :
- au debut de chaque fonction, un test pour voir si autorisation_paint est VRAI, sinon on quitte la fonction
- juste après, une instruction met autorisation_paint à FALSE
- à la fin de la fonction, la dernière instruction remet autorisation_paint à TRUE
Ce n'était pas facile, selon les possibilités d'édition à la souris du programme, il fallait plusieurs variables "autorisation_xxx" et la fonction MouseMove n'était pas traité de la même manière que MouseDown et MouseUp, car "rater" un MouseMove n'était pas grave (et même souhaitable) en revanche il ne fallait pas rater un appel de MouseDown ou MouseUp.
De quel "Visual Basic" on parle ?
De VB6 ?
VB6, c'est comme les MFC, c'est mono-thread de base, plus précisément STA (Single Thread Appartment) donc avec des protections contre les autres threads.
Votre histoire de "autorisation_paint", ça semble une bonne vieille rustine pourrie pour appeler la fonction DoEvents n'importe comment et esquiver les appels récursifs qu'implique l'appel sauvage de DoEvents.
Il y a des appels de fonction dans des contrôles standard pour désactiver le calcul d'affichage tant qu'on n'a pas fini le chargement de données dedans, mais c'est juste pour faire des optimisations, pas pour autoriser des DoEvents de barbares.
Je ne vois pas comment vous pouviez "looper" des MouseDown etc..., c'est l'OS qui s'en occupe et VB a le même type de pompe à message que MFC ou le SDL Win32.
Citation:
Ces variables "autorisation_xxx" permettaient aussi d'éviter les ralentissements du à une succession d'appel de fonction d'affichages quand une action unique de l'utilisateur sur l'interface engendre plusieurs évenements (typiquement, le redimenssionnement de la fenêtre qui ajuste le mini, le maxi et la valeur des barres de défilement)
cf. "Il y a des appels de fonction dans des contrôles standard pour désactiver le calcul d'affichage ..." ci-avant.
Citation:
Je n'ai jamais compris pourquoi WINDOWS et/ou les langages IDE Visual Basic / Visual C++ :
- n'empêchaient pas de nouveaux appels de MouveMove tant que les précédents ne sont pas terminés
- ne mettaient pas en attente l'appel de MouseDown ou MouseUp tant qu'un appel précédent de MouseMove n'était pas terminé
Bin, tous les framework courants sous Windows, à base de pompe à messages, n'ont aucuns des inconvénients que vous mentionnez.
Ils sérialisent tout, messages après messages.
Citation:
A cause de la manière dont le système d'exploitation gère les évenements de l'interface graphique, on se retrouve à devoir gérer des problèmes de Thread dans un programme qui ne les utilise pas à l'origine
Ces bugs sont très emmerdants car ils n'apparaissent pas tout de suite.
Quand le programme est simple (donc rapide) et que l'utilisateur est lent tout fonctionne correctement.1
Mais quand le programme s'enrichi en fonctionnalités et que le code dans les fonctions devient plus gros et plus lent, et qu'en même temps l'utilisateur maitrise le logiciel et va plus vite, les soucis apparaissent...
Ne serait-ce pas plutôt des bugs latents que la vitesse d'exécution révèle ?
Il n'y a pas de problèmes de thread quand on utilise "simplement" les Framework de base de Windows.
Vous mentionnez des Thread dans un programme "simple". Pourquoi avez-vous besoin de thread dans des cas simples, sachant que les Framework s'arrangent pour n'utiliser que le thread créateur de la première fenêtre.
Citation:
Au risque de choquer les gens, la programmation "à l'ancienne" sous MS-DOS (ou sur un microcontrôleur), où il fallait gérer manuellement une souris, une manette de jeux ou un clavier avec une boucle, était presque plus simple.
Une interruption mettait à jours les coordonnées souris ou actions de l'utilisateur. On pouvait même faire une pile pour enregistrer plusieurs frappes rapides au clavier successives.
La boucle principale du programme scrutait si les valeurs avaient changés, et si oui, les traitait.
Pas de problème de recouvrement.
C'est encore plus simple en Windows car vous n'avez pas à gérer des interruptions. Vous n'avez pas à gérer les différents périphériques car les évènements postés dans la pompe à message colportent l'ensemble des informations nécessaires (états de boutons du clavier, de la souris, etc...) et chaque changement d'état fait potentiellement l'objet d'un post dans la file de message de la fenêtre qui va bien.
Franchement, je ne vois pas en quoi la programmation MS-DOS, avec ces terribles programmes résidents TSR qui foutaient la grouille en moins de 2 était plus simple.
Dans le code de @Informt2025, on voit bien que les coordonnés nouvelles (FMovePt) ne sont pas mélangées avec les coordonnées anciennes (PrvPt) et que l'appel de DrawRect2 avec les anciennes cordonnées précède toujours celles avec les nouvelles.
Citation:
Le code source est assez lourd, je ne peux même pas publier le code du fichier .cpp de la fenêtre sur le forum car il dépasse la limite de caractères imposée par le forum
GitHub ou GitLab sont nos amis.
Citation:
Ce code est beaucoup plus complexe, notamment parceque l'objet 'm_rect' est utilisé un peu partout.
Je crois que c'est le nœud du problème.
Je pense que tenter un passage d'IA pour traduire le code en anglais et ajouter des commentaires, ça se tente, pour améliorer drastiquement la maintenabilité du bidule.
Si "m_rect" est mal utilisé, vous êtes bon pour le corriger. Mais je vois pas trop le problème pour le corriger.
Pour compléter la réponse très pertinente de @Informt2025 le "18/07/2026, 00h03", il existe des classes de "haut niveau" pour gérer ce type de fonctionnalité, comme la classe CRectTracker :
https://learn.microsoft.com/en-us/cp...?view=msvc-170
@electroremy, si tu as du mal à "couper dans le vif", prépare un jeu de test de non-régression et tu seras bien plus "relaxe".
Citation:
C'est intéressant, mais, difficulté supplémentaire : je modifie ce projet obsolète avec une version beaucoup plus récente de l'IDE : Visual Studio 2015
Pourquoi rester en VS2015 quand il existe pléthore de versions plus récentes ?
Vous avez pris un risque pour le passer en VS2015, pourquoi ne pas le prendre pour avoir une version plus actuelle ?
cf. Test de non-régression
Citation:
Pour modifier l'interface graphique, c'est la galère, il faut bidouiller les fichiers de ressource, puis recompiler des DLL pour que ça soit pris en compte dans la version Release (voir mon autre post sur ce problème là)
Déjà répondu, c'est un projet MFC, vous devez disposer d'un Designer Graphique, sauf si vos modifications l'ont cassé. (Peut-être que l'ancien mainteneur l'avait déjà "cassé")
Citation:
Autre aspect du problème : le programme fonctionne encore très bien sous Windows 11, mais j'ai peur qu'il ne fonctionne plus avec les futures mises à jour.
Pour le coup, c'est plutôt les MFC qui font craindre un problème d'obsolescence car c'est plus une bibliothèque très soutenue pas M$.
Vous deviez tenter une migration vers des bibliothèques plus récentes. Mais l'architecture du projet est peut-être mal fichue pour résister à ce type de migration.
GDI32 est bien plus pérenne que les MFC.
Vous engrangez de la dette technique, et, un jour, faut passer à la caisse.
N'engrangez pas cette dette en utilisant toujours les outils à jours. Quand des composants deviennent obsolètes, migrez avant qu'il soit trop tard et que vous soyez au pied du mur.
Citation:
Je continue à maintenir un logiciel que j'avais terminé en... 2003, créé avec Visual Basic 5, il s'appelle CiDess
http://cidess.free.fr/index-fr.html
Pour qu'il tourne encore sous Windows 10 et Windows 11, j'ai dû le modifier pour ne plus utiliser des contrôles OCX
OCX est encore "maintenu", c'est plutôt VB5 qui est "mort".
Pourquoi ne pas faire sa migration vers du VB.NET ou autres ?
Les IA comme Claude Code font des miracles au niveau des migrations, même depuis des antiquités.
Citation:
Donc pour ShiftN, il faut que je reste avec des fonctions de base de GDI32.
Vous n'êtes pas en GDI32 "de base", vous êtes en MFC, et c'est plus problématique.
Citation:
Si j'utilise des astuces trop poussées, ça risque de ne plus fonctionner du tout.
Git et les tests de non-régressions sont nos amis, les IA aussi.
Citation:
Je devrait être tranquille, car étant donné le nombre d'anciens logiciels encore utilisés dans beaucoup d'entreprises, Microsoft ne devrait pas prendre le risque de supprimer la rétrocompatibilité avec les programmes WIN32
Il faut que M$ y trouve son compte, et votre programme est MFC, pas WIN32.
MFC, ça fait des décennies qu'ils indiquent qu'elle va crever, ils vous auront pas pris en traitre :aie:.
Citation:
Il faut arrêter avec la "mise-à-jourite aigue", il existe des tas de logiciels anciens qui font parfaitement le job et qui n'ont pas besoin d'être améliorés.
Sauf qu'eux, ils ont des trous de sécurité et des problèmes de compatibilité à patch et qu'ils ne peuvent pas avoir de dette technique abyssale.
Citation:
Il y a un gros sujet dans l'industrie avec les logiciels qui pilotent des machines automatiques ou des machines outils à commande numérique.
Des machines des années 2000, 1990 ou même plus anciennes encore sont en parfait état de marche mais ont des systèmes informatiques obsolètes.
Il serait absurde d'un point de vue économique et écologique de les remplacer uniquement à cause de l'obsolescence du système informatique.
Et un rétrofit est une tâche très ardue...
Toi, t'as pas entendu parler de Stuxnet. 8O
Citation:
Et surtout : le fait que les logiciels ne sont achetable définitivement, mais qu'il faille payer un loyer, avec un serveur de licence, qui lorsqu'il ferme, rend le logiciel inutilisable.
Ce genre de truc devrait être illégal
T'as signé la pétition européenne sur le sujet ?
Citation:
Il n'y a plus grand chose à inventer en matière de système d'exploitation multitâche avec interface graphique depuis longtemps.
On se demande pourquoi MacOS et Linux prennent des parts de marché.