BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019
-
30 avril 2008 à 00:35
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010
-
12 août 2010 à 11:32
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 12 août 2010 à 11:32
Aucune idée, j'ai jamais touché à ces [mode troll on] conneries [mode troll off]. Renseigne-toi pour savoir comment gérer le graphisme avec cette technologie. Je doute que le GDI soit approprié. Bon courage!
cs_jeron
Messages postés29Date d'inscriptionlundi 30 juin 2003StatutMembreDernière intervention25 juillet 20142 8 août 2010 à 14:16
et si l'on veut incoporer dans ce projet une winform crée avec vsc++2008 ? comment on fait s'il vous plait ?
merci d'avance
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 25 févr. 2009 à 13:23
J'ai regardé ta source. Même si je n'ai jamais fait de MFC, je crois avoir compris l'important : un bitmap est créé au début de l'affichage, il sert à la préparation de l'image, puis il est blité sur le DC de l'application, et enfin il est libéré. Si c'est bien ça, la seule différence avec ma méthode, c'est que le bitmap n'existe que pendant l'affichage. Après, ça dépend de ce qu'on veut faire : si on veut pouvoir modifier l'image à tout moment, on aura intérêt à utiliser ma méthode, si on veux économiser des ressources ce sera plutot la tienne. Mais la mienne à tout de même un avantage certain : on est pas obligé de tout recalculer à chaque affichage, il suffit juste de changer ce que l'on veut. Prenons l'exemple d'un jeu d'échec. Si un joueur bouge une pièce, il suffit de redessiner la case de départ et celle d'arrivée sur le bitmap.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 25 févr. 2009 à 13:12
C'est un double buffering dans le sens qu'on n'affiche pas directement ce qu'on prépare. On prépare (ça peut mettre du temps, j'ai des exemples où on met 1mn à préparer l'image), et on affiche tout d'un coup. C'est exactement le principe des jeux vidéos : l'image en préparation est stockée dans un espace mémoire distinct de la mémoire vidéo affichée.
Pour cette source, ça ne se voit pas (j'ai réduit au minimum), mais si on devais réafficher le fond à chaque appui de touche puis afficher l'ellipse, on voit un scintillement si on n'utilise pas cette méthode.
shorzy
Messages postés94Date d'inscriptionjeudi 23 novembre 2000StatutMembreDernière intervention 1 juin 2013 25 févr. 2009 à 11:14
OKI,Comme je l'ai dis dans mon précédent Post j'ai VC2005
donc je ne peux pas utilisé ton projet (.dsw pour VC2005)
Par contre ton Explication m'a bien aidé :
- AVANT j'avais ouvert le .C puis j'ai Cliqué sur Executé
(Je pense qu'il a choisit par défaut une Execution en mode Console
- MAINTENANT j'ai Crée un Projet Win(Graph) et ça marche!!
Merci! Tu m'as mis sur la Voie !
(Mon bug peux aidé certains)
Pour le Programe :
Visuellement, je ne vois pas où est le Double-Buffering !
En regardant rapidement le code, Je pense qu'il s'agirait plutôt d'un 'Single'-Buffering ???
Je vous invite sur :
http://www.cppfrance.com/codes/DOUBLE-BUFFERING-MFC_48812.aspx C'est en MFC. Pour voir rapidement le Double-Buffering :
Clic Gauche + Glisser la Souris
Presser la Touche 'F5' pour Activé en Direct le Double-Buffering
N'Hésiter pas à laisser un Post sur ce que vous en Pensez
++
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 21 févr. 2009 à 00:04
Project->Properties->Linker->System->Subsystem = Windows
Quand tu crée un projet, il faut que tu spécifie à ton linker si tu veux une application graphique Windows ou une application executable dans la console. Visual Studio te le demande normalement.
Dans ton cas, il s'attend à un point d'entrée de type main() alors qu'en fait il faut WinMain() pour une application Windows.
shorzy
Messages postés94Date d'inscriptionjeudi 23 novembre 2000StatutMembreDernière intervention 1 juin 2013 20 févr. 2009 à 17:17
Problème :
J'utilise VC6 et je présise que je n'aie rien Télécharger (PSDK ATL...)
j'ai un Problème lors du Link !!!!!
"
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/main.exe : fatal error LNK1120: 1 unresolved externals
"
J'ai donc 3 Question :
Dois-je Linker des Fichiers *.Lib avant de Compiler ???
Comment Savoir s'il Faut Ajouter des Fichiers (LINK) ???
Que dois-je Faire pour que ca Marche ???
Si qqun peut me Sauver le Mise, MERCI.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 19 févr. 2009 à 22:07
Voila, ça m'aurais bien étonné de trouvé un seul warning, et effectivement il n'y en a pas.
J'ai même rajouté le projet en prime.
Bon courage avec ton compilateur...
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 19 févr. 2009 à 21:55
Je vois ça tout de suite...
shorzy
Messages postés94Date d'inscriptionjeudi 23 novembre 2000StatutMembreDernière intervention 1 juin 2013 19 févr. 2009 à 21:53
Salut, le Code est peut être très bien, mais il y a due avoir une erreur lorsque tu as fait des Modif ...
J'ai des Erreur de Compil. (WinXP-VC2005)
S'il n'y a vraiment pas d'Erreur quand ti Copie-Colle le Code,
peux tu mettre un Ex_ STP que je voie au moins le Résultat Final..
Merci!
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 juin 2008 à 14:42
Merci pour la note :-)
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 30 juin 2008 à 14:37
Je crois avoir suffisamment dévié en HS ton post ;)
Merci de tes conseils, et bien sur aussi pour ta source, qui m'a fait découvrir les DIB.
Il va falloir que je les utilise absolument !
Je n'ai pas sur mon pc (Vista + core2duo 2Ghz) le problème que tu décris en conclusion.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 juin 2008 à 14:34
"La seconde boucle (avec peekMessage) est mise un peu n'importe où dans mon code, là où j'ai remarqué qu'il y en avait besoin, il n'y a pas de return après, c'est simplement au milieu du code."
Ca a l'air d'être une sacrée usine à gaz. Ces boucles là ne servent à rien à mon humble avis. Des boucles au beau milieu du code permettent peut-être de traiter des messages pendant le traitement d'un autre message (par exemple exiger un raffraichissement de l'écran par WM_PAINT pendant le traitement d'un message WM_SIZE). Mais pour ça il y a SendMessage() qui fonctionne très bien.
Il est toujours possible de tracer dans un fichier tous les messages interceptés.
Ou alors utiliser les hook peut-être.
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 30 juin 2008 à 14:24
"Mais si elle finit, c'est aussi le programme qui finit, non?"
Non, ma boucle principale des messages pour la fenetre mère est la première que j'ai montrée ci dessus (sans peekMessage).
La seconde boucle (avec peekMessage) est mise un peu n'importe où dans mon code, là où j'ai remarqué qu'il y en avait besoin, il n'y a pas de return après, c'est simplement au milieu du code.
C'est cette seconde boucle qui parait-il est l'équivalent du DoEvents de VB.
"De toute façon ... appeler MoveWindow() je pense."
Oui tout à fait, j'ai parlé trop vite, aucun risque de ce côté.
Cette appli a vraiment été codée dans le souci de la performance, je ne peux pas croire qu'une appli relativement simple (toute skinnée + embarque un ActiveX qui joue une vidéo) détraque Windows à ce point.
Il me faudrait trouver un soft qui puisse indiquer la "charge" de la pile des messages windows.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 juin 2008 à 12:03
"PeekMessage retourne zero visiblement, puisque je n'ai qu'un seul thread dans mon appli, et que cette boucle finit très bien, en moyenne en 50ms."
Mais si elle finit, c'est aussi le programme qui finit, non?
Normalement après une boucle de message il y a un return, ce qui fait que dès que la boucle finit (dans ton cas dès que PeekMesage ne trouve pas de message!), alors le programme finit (si c'est la fenêtre principale).
"Par contre j'utilise des SetWindowPos dans le WM_SIZE pour placer mes boutons après un redimensionnement." De toute façon tant que l'on envoie pas de message de façon récursive (envoyer un message WM_SIZE à soit même dans le traitement d'un message WM_SIZE) il ne doit pas y avoir de problème. Les bouttons sont des fenêtres filles, donc tu peut leur envoyer ce que tu veux, même appeler MoveWindow() je pense.
"C'est une méthode horrible, et je serais ravi de m'en passer."
Je n'ai pas dit que c'était horrible, car je ne connait pas cette méthode suffisament. Par contre personnellement je serai ravi de m'en passer.
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 30 juin 2008 à 11:51
PeekMessage retourne zero visiblement, puisque je n'ai qu'un seul thread dans mon appli, et que cette boucle finit très bien, en moyenne en 50ms.
MoveWindow n'est pas sollicité si abondamment que ca, jamais dans une boucle, ni dans le WM_SIZE ou WM_MOVEWINDOW bien sur.
Par contre j'utilise des SetWindowPos dans le WM_SIZE pour placer mes boutons après un redimensionnement.
D'après msdn, SetWindowPos ne renvoie pas de message WM_SIZE à son tour, donc il n'y a à priori aucune restriction à l'utiliser dans WM_SIZE, non ?
C'est une méthode horrible, et je serais ravi de m'en passer.
Mais sans ca, j'ai des résultats aléatoires, même sur des pcs (très) puissants. (core2duo 2Ghz + Vista.)
Je t'aurais montré volontiers mon code source s'il n'était pas confidentiel (pour mon boulot)
J'ai compris et je prends bien note de tes conseils sur le double buffering, et les DIB, et je reverrai le traitement de mon WM_PAINT dès que possible.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 juin 2008 à 10:40
Hahahahaha!!! UN FOU!!! Pas mal le traitement du WM_NCHITEST, je connaissait même pas (DefWindowProc fait le boulot pour moi).
Par contre, c'est pas normal pour les PeekMessage, la boucle que tu donne là finit dès qu'il n'y a plus de messages dans la thread message queue. Donc si je comprend bien ta fenêtre génère des messages en permanence jusqu'à saturer la message queue, ce qui fait que 1) PeekMessage ne retourne jamais zero 2) il y a des messages non traités forcement.
Je te crois quand tu dit que tu utilise MoveWindow à tour de bras.
Tu peut donner la config de ton pc (quel prossesseur et quel OS)?
Et je peut te filer mon adresse msn en mp pour que tu me donne le source de ton programme?
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 30 juin 2008 à 10:05
"En tout cas si tu veux faire toi-même ta partie non cliente, je te souhaite bien du courage, pour gérer le redimentionnement et le déplacement par exemple."
j'utilise cette technique pour redimensionner et déplacer ma fenetre. (j'ai dessiné dans le coin en bas à droite un grip pour le resize)
case WM_NCHITTEST:
if((rect.bottom-cursor.y)<20 && (rect.right-cursor.x<20))
return HTBOTTOMRIGHT;
else
return HTCAPTION;
Ca marche nikel, et sans partie non cliente visible
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 30 juin 2008 à 10:02
ok, je comprends, je m'étais mis en tête que le flickering n'était pas possible entre les beginpaint() et endpaint() pcq le DC n'était rafraichit qu'au moment du endpaint().
Je comprends donc mieux maintenant l'intérêt du double buffering, même si dans certains cas il semble ralentir le temps de traitement du WM_PAINT.
A certains endroits de mon application, si j'insiste un peu trop avec des SetWindowPos et des MoveWindow, c'est flagrant, Windows gère mal les messages et position/dimensionne la fenêtre n'importe comment.
En ajoutant un Sleep(), ca ne change rien.
Si j'enlève qques SetWindowPos, ca marche bien.
Il a donc fallu que j'utilise l'équivalent des DoEvents(), ca permet de faire suivre l'affichage, ca prend jusqu'à 50ms par contre. Voici le code que j'utilise :
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Je suis étonné de devoir utiliser ce genre d'astuces à certains endroits de mon application, sans ca tous les messages ne sont pas traités correctement.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 28 juin 2008 à 12:32
En fait, BeginPaint/EndPaint ne sert pas à raffraichir, ça sert juste à donner des informations de DC à ta fenêtre (PAINTSTRUCT).
C'est d'ailleur un gros problème quand on utilise pas le double buffering (n'ai-je pas déjà évoqué ça?) : si on peint toute la surface de la fenêtre d'une couleur unie et qu'ensuite on dessine un autre contenu (entre BeginPaint/EndPaint), on va voir un scintillement désagréable : le flickering.
Pour ce qui est de SetPixel (ou SetPixelV qui est un peu plus rapide), ça doit être environ 10000 fois moins rapide qu'un accès mémoire (je ne plaisante pas).
Voila pourquoi on peut utiliser les fonctions GDI (par exemple pour faire des ellipses), mais SetPixel le moins possible.
Tu demande aussi si il est plus rapide de faire soit-même sa partie non cliente. Je pense que non, mais tu as toujours le choix de ne pas en avoir du tout (donc pas de style WS_OVERLAPPEDWINDOW), ça donne des programmes un peu dépouillés, mais il y en a qui aiment (pas moi). En tout cas si tu veux faire toi-même ta partie non cliente, je te souhaite bien du courage, pour gérer le redimentionnement et le déplacement par exemple. En plus ton programme final ne pourra pas resembler aux fenêtres standard Windows dans tous les Windows (les fenêtres XP ne ressemblent pas aux fenêtre 98 par exemple).
"J'ai remarqué assez vite des problèmes de performances, et des "pertes de messages windows", qui peuvent être résolues en mettant des DoEvents (la boucle infinie qui traite la pile des messages, la boucle même dont vous parlez avec F_L_A_S_H_B_A_C_K), je suis étonné de devoir en arriver là, ca ne paraît pas très propre.."
En effet ça ne paraît pas très propre... Déjà ce DoEvents, c'est du C ou du VB (My.Application.DoEvents Method) ? Parce que je connaît pas en C et ma doc non plus.
Normalement si il y a des pertes de messages, ça doit venir de toi. Envoie ta boucle de message qui ne fonctionne pas.
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 28 juin 2008 à 11:37
Attendez quelques instants, je me remet le nez dans ces trucs là...
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 27 juin 2008 à 10:14
Pourquoi rafraichirait-il entre deux setpixels consécutifs encapsulés entre un beginpaint et un endpaint ?
Ne rafraichit-il pas uniquement au endpaint ?
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 27 juin 2008 à 10:03
tu peux modifier la taille et disposition de la partie non cliente,
j'ai deja fait ca, et en VB, sans grosse pertes de perfs..
SetPixel est lent: dessine ce pixel en rouge, celui la aussi, celui là, encore.
mais entretemps, surtout raffraichit, hein !
CreateDIBSection va permettre de faire un image stockée en RAM (Device Independant, donc pas d'echange constant avec la carte graphique)
et on affiche le tout en une fois.
clairement plus rapide, donc.
shuttleur
Messages postés33Date d'inscriptionmercredi 12 septembre 2007StatutMembreDernière intervention30 juin 2008 27 juin 2008 à 09:58
Salut _michel
Merci de faire partager le résultat de tes recherches.
Je suis confronté à des problèmes de performances également sur une appli totalement skinnée avec des bitmaps.
Je cherche à savoir quelle est la meilleure combinaison de paramètres dwExStyle et dwStyle dans CreateWindowEx pour les performances.
Par exemple, je ne veut pas de contour ni de barre de titre windows, est ce que je dois demander une fenetre sans partie non cliente, et peindre une fausse barre de titre dans la partie cliente ou demander une barre de titre et des contours, mais surcharger le message PAINT de la partie non cliente pour la faire à mon gout ?
J'ai remarqué assez vite des problèmes de performances, et des "pertes de messages windows", qui peuvent être résolues en mettant des DoEvents (la boucle infinie qui traite la pile des messages, la boucle même dont vous parlez avec F_L_A_S_H_B_A_C_K), je suis étonné de devoir en arriver là, ca ne paraît pas très propre..
Est tu sur que SetPixel est lent ?
Comment le fait d'utiliser CreateDIBSection() et de tout faire à la main peut il être plus rapide que d'utiliser les fonctions windows faites pour ?
Merci d'avance
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 2 mai 2008 à 11:52
Tu as testé chez toi?
J'ai essayé chez moi, en modifiant un peu :
Ca ne marche pas (si en plus on enlève le traitement des WP_PAINT, la fenêtre n'affiche rien).
Je crois pas qu'on puisse dessiner avec BeginPaint()/EndPaint() en dehors d'un WM_PAINT : la zone invalide est vide, donc tous les opérations graphiques qu'on effectue ne servent à rien. En tous cas msdn spécifie qu'il faut utiliser GetDc()/ReleaseDC() en dehors d'un WP_PAINT.
f_l_a_s_h_b_a_c_k
Messages postés56Date d'inscriptionvendredi 14 avril 2006StatutMembreDernière intervention 1 février 2009 1 mai 2008 à 23:07
pas sure de getDC()
je ferais plus ca...
void dess(HWND hwnd)
{
PAINTSTRUCT PaintStruct ;
HDC DC = BeginPaint(hwnd, &PaintStruct);
HDC hMDC = CreateCompatibleDC(DC);
Ca ne change pas mon problème : il y a toujours un manque de syncronisation entre le raffraichissement de l'écran et le raffraichissement de la mémoire.
Le seul changement, c'est que l'image est raffraichie le plus souvent possible, ce qui prend tout le temps processeur. Bien entendu c'est l'optimal pour un jeu en full-screen, mais pour une application qui utilise le GDI et qui n'est pas complemtement axée sur le grapisme, c'est pas ce qu'il faut.
Je pense qu'on peut obtenir le même résultat en n'appelant pas EndPaint() pendant le traitement d'un message WM_PAINT : la fenêtre a toujours une zone invalide et donc Windows envoie sans arret des messages WM_PAINT.
f_l_a_s_h_b_a_c_k
Messages postés56Date d'inscriptionvendredi 14 avril 2006StatutMembreDernière intervention 1 février 2009 30 avril 2008 à 18:54
moi je remplacerais
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/////////////////
un flip();
ou une fonction sur ton BitBlt()
//////////////////
}
ou lieu de le mettre ton bitblt() dans WM_PAINT:
sa devrais eliminer ton 'flicker'
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 avril 2008 à 18:28
J'ai modifié le code pour pouvoir modifier le bitmap par soit même (pas seulement avec les fonctions du GDI).
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 avril 2008 à 13:43
En fait, de manière générale, on ne peut pas selectionner un bmp dans autre chose qu'un memory DC (cf doc de SelectObject).
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 avril 2008 à 12:02
Renfield -> Non je ne crois pas : selectionner un bitmap dans un DC ne le fait pas s'afficher. Il n'y a qu'en passant dpar un memory DC que ça marche.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 30 avril 2008 à 07:31
doit être possible de jouer juste avec SelectObject pour permutter front et backbuffer
en switchant les hBmp
_michel
Messages postés77Date d'inscriptionmardi 27 juin 2006StatutMembreDernière intervention12 août 2010 30 avril 2008 à 00:58
exit() -> dans le traitement de WM_CREATE, la solution est de retourner -1 d'après la doc
pour hDC je l'ai mis en Common Display Device Context plutot que en Private Display Device Context, vu que seul hMDC a besoin d'être accedé courament. Pas de problème constaté.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 30 avril 2008 à 00:35
Enlève exit(), ça n'a rien à faire dans du Windows GUI, remplace par un branchement vers PostQuitMessage(0) de WM_DESTOY, un petit goto judicieux ira parfaitement.
Referme hDC obtenu dans WM_CREATE et utilise le retour de BeginPaint pour dessiner dans WM_PAINT.
12 août 2010 à 11:32
8 août 2010 à 14:16
merci d'avance
25 févr. 2009 à 13:23
25 févr. 2009 à 13:12
Pour cette source, ça ne se voit pas (j'ai réduit au minimum), mais si on devais réafficher le fond à chaque appui de touche puis afficher l'ellipse, on voit un scintillement si on n'utilise pas cette méthode.
25 févr. 2009 à 11:14
donc je ne peux pas utilisé ton projet (.dsw pour VC2005)
Par contre ton Explication m'a bien aidé :
- AVANT j'avais ouvert le .C puis j'ai Cliqué sur Executé
(Je pense qu'il a choisit par défaut une Execution en mode Console
- MAINTENANT j'ai Crée un Projet Win(Graph) et ça marche!!
Merci! Tu m'as mis sur la Voie !
(Mon bug peux aidé certains)
Pour le Programe :
Visuellement, je ne vois pas où est le Double-Buffering !
En regardant rapidement le code, Je pense qu'il s'agirait plutôt d'un 'Single'-Buffering ???
Je vous invite sur :
http://www.cppfrance.com/codes/DOUBLE-BUFFERING-MFC_48812.aspx
C'est en MFC. Pour voir rapidement le Double-Buffering :
Clic Gauche + Glisser la Souris
Presser la Touche 'F5' pour Activé en Direct le Double-Buffering
N'Hésiter pas à laisser un Post sur ce que vous en Pensez
++
21 févr. 2009 à 00:04
Quand tu crée un projet, il faut que tu spécifie à ton linker si tu veux une application graphique Windows ou une application executable dans la console. Visual Studio te le demande normalement.
Dans ton cas, il s'attend à un point d'entrée de type main() alors qu'en fait il faut WinMain() pour une application Windows.
20 févr. 2009 à 17:17
J'utilise VC6 et je présise que je n'aie rien Télécharger (PSDK ATL...)
j'ai un Problème lors du Link !!!!!
"
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/main.exe : fatal error LNK1120: 1 unresolved externals
"
J'ai donc 3 Question :
Dois-je Linker des Fichiers *.Lib avant de Compiler ???
Comment Savoir s'il Faut Ajouter des Fichiers (LINK) ???
Que dois-je Faire pour que ca Marche ???
Si qqun peut me Sauver le Mise, MERCI.
19 févr. 2009 à 22:07
J'ai même rajouté le projet en prime.
Bon courage avec ton compilateur...
19 févr. 2009 à 21:55
19 févr. 2009 à 21:53
J'ai des Erreur de Compil. (WinXP-VC2005)
S'il n'y a vraiment pas d'Erreur quand ti Copie-Colle le Code,
peux tu mettre un Ex_ STP que je voie au moins le Résultat Final..
Merci!
30 juin 2008 à 14:42
30 juin 2008 à 14:37
Merci de tes conseils, et bien sur aussi pour ta source, qui m'a fait découvrir les DIB.
Il va falloir que je les utilise absolument !
Je n'ai pas sur mon pc (Vista + core2duo 2Ghz) le problème que tu décris en conclusion.
30 juin 2008 à 14:34
Ca a l'air d'être une sacrée usine à gaz. Ces boucles là ne servent à rien à mon humble avis. Des boucles au beau milieu du code permettent peut-être de traiter des messages pendant le traitement d'un autre message (par exemple exiger un raffraichissement de l'écran par WM_PAINT pendant le traitement d'un message WM_SIZE). Mais pour ça il y a SendMessage() qui fonctionne très bien.
Il est toujours possible de tracer dans un fichier tous les messages interceptés.
Ou alors utiliser les hook peut-être.
30 juin 2008 à 14:24
Non, ma boucle principale des messages pour la fenetre mère est la première que j'ai montrée ci dessus (sans peekMessage).
La seconde boucle (avec peekMessage) est mise un peu n'importe où dans mon code, là où j'ai remarqué qu'il y en avait besoin, il n'y a pas de return après, c'est simplement au milieu du code.
C'est cette seconde boucle qui parait-il est l'équivalent du DoEvents de VB.
"De toute façon ... appeler MoveWindow() je pense."
Oui tout à fait, j'ai parlé trop vite, aucun risque de ce côté.
Cette appli a vraiment été codée dans le souci de la performance, je ne peux pas croire qu'une appli relativement simple (toute skinnée + embarque un ActiveX qui joue une vidéo) détraque Windows à ce point.
Il me faudrait trouver un soft qui puisse indiquer la "charge" de la pile des messages windows.
30 juin 2008 à 12:03
Mais si elle finit, c'est aussi le programme qui finit, non?
Normalement après une boucle de message il y a un return, ce qui fait que dès que la boucle finit (dans ton cas dès que PeekMesage ne trouve pas de message!), alors le programme finit (si c'est la fenêtre principale).
"Par contre j'utilise des SetWindowPos dans le WM_SIZE pour placer mes boutons après un redimensionnement." De toute façon tant que l'on envoie pas de message de façon récursive (envoyer un message WM_SIZE à soit même dans le traitement d'un message WM_SIZE) il ne doit pas y avoir de problème. Les bouttons sont des fenêtres filles, donc tu peut leur envoyer ce que tu veux, même appeler MoveWindow() je pense.
"C'est une méthode horrible, et je serais ravi de m'en passer."
Je n'ai pas dit que c'était horrible, car je ne connait pas cette méthode suffisament. Par contre personnellement je serai ravi de m'en passer.
30 juin 2008 à 11:51
MoveWindow n'est pas sollicité si abondamment que ca, jamais dans une boucle, ni dans le WM_SIZE ou WM_MOVEWINDOW bien sur.
Par contre j'utilise des SetWindowPos dans le WM_SIZE pour placer mes boutons après un redimensionnement.
D'après msdn, SetWindowPos ne renvoie pas de message WM_SIZE à son tour, donc il n'y a à priori aucune restriction à l'utiliser dans WM_SIZE, non ?
C'est une méthode horrible, et je serais ravi de m'en passer.
Mais sans ca, j'ai des résultats aléatoires, même sur des pcs (très) puissants. (core2duo 2Ghz + Vista.)
Je t'aurais montré volontiers mon code source s'il n'était pas confidentiel (pour mon boulot)
J'ai compris et je prends bien note de tes conseils sur le double buffering, et les DIB, et je reverrai le traitement de mon WM_PAINT dès que possible.
30 juin 2008 à 10:40
Par contre, c'est pas normal pour les PeekMessage, la boucle que tu donne là finit dès qu'il n'y a plus de messages dans la thread message queue. Donc si je comprend bien ta fenêtre génère des messages en permanence jusqu'à saturer la message queue, ce qui fait que 1) PeekMessage ne retourne jamais zero 2) il y a des messages non traités forcement.
Je te crois quand tu dit que tu utilise MoveWindow à tour de bras.
Tu peut donner la config de ton pc (quel prossesseur et quel OS)?
Et je peut te filer mon adresse msn en mp pour que tu me donne le source de ton programme?
30 juin 2008 à 10:05
j'utilise cette technique pour redimensionner et déplacer ma fenetre. (j'ai dessiné dans le coin en bas à droite un grip pour le resize)
case WM_NCHITTEST:
if((rect.bottom-cursor.y)<20 && (rect.right-cursor.x<20))
return HTBOTTOMRIGHT;
else
return HTCAPTION;
Ca marche nikel, et sans partie non cliente visible
30 juin 2008 à 10:02
Je comprends donc mieux maintenant l'intérêt du double buffering, même si dans certains cas il semble ralentir le temps de traitement du WM_PAINT.
Voici ma boucle de messages :
MSG Msg;
while( GetMessage(&Msg, 0, 0, 0))
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
A certains endroits de mon application, si j'insiste un peu trop avec des SetWindowPos et des MoveWindow, c'est flagrant, Windows gère mal les messages et position/dimensionne la fenêtre n'importe comment.
En ajoutant un Sleep(), ca ne change rien.
Si j'enlève qques SetWindowPos, ca marche bien.
Il a donc fallu que j'utilise l'équivalent des DoEvents(), ca permet de faire suivre l'affichage, ca prend jusqu'à 50ms par contre. Voici le code que j'utilise :
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Je suis étonné de devoir utiliser ce genre d'astuces à certains endroits de mon application, sans ca tous les messages ne sont pas traités correctement.
28 juin 2008 à 12:32
C'est d'ailleur un gros problème quand on utilise pas le double buffering (n'ai-je pas déjà évoqué ça?) : si on peint toute la surface de la fenêtre d'une couleur unie et qu'ensuite on dessine un autre contenu (entre BeginPaint/EndPaint), on va voir un scintillement désagréable : le flickering.
Pour ce qui est de SetPixel (ou SetPixelV qui est un peu plus rapide), ça doit être environ 10000 fois moins rapide qu'un accès mémoire (je ne plaisante pas).
Voila pourquoi on peut utiliser les fonctions GDI (par exemple pour faire des ellipses), mais SetPixel le moins possible.
Tu demande aussi si il est plus rapide de faire soit-même sa partie non cliente. Je pense que non, mais tu as toujours le choix de ne pas en avoir du tout (donc pas de style WS_OVERLAPPEDWINDOW), ça donne des programmes un peu dépouillés, mais il y en a qui aiment (pas moi). En tout cas si tu veux faire toi-même ta partie non cliente, je te souhaite bien du courage, pour gérer le redimentionnement et le déplacement par exemple. En plus ton programme final ne pourra pas resembler aux fenêtres standard Windows dans tous les Windows (les fenêtres XP ne ressemblent pas aux fenêtre 98 par exemple).
"J'ai remarqué assez vite des problèmes de performances, et des "pertes de messages windows", qui peuvent être résolues en mettant des DoEvents (la boucle infinie qui traite la pile des messages, la boucle même dont vous parlez avec F_L_A_S_H_B_A_C_K), je suis étonné de devoir en arriver là, ca ne paraît pas très propre.."
En effet ça ne paraît pas très propre... Déjà ce DoEvents, c'est du C ou du VB (My.Application.DoEvents Method) ? Parce que je connaît pas en C et ma doc non plus.
Normalement si il y a des pertes de messages, ça doit venir de toi. Envoie ta boucle de message qui ne fonctionne pas.
28 juin 2008 à 11:37
27 juin 2008 à 10:14
Ne rafraichit-il pas uniquement au endpaint ?
27 juin 2008 à 10:03
j'ai deja fait ca, et en VB, sans grosse pertes de perfs..
SetPixel est lent: dessine ce pixel en rouge, celui la aussi, celui là, encore.
mais entretemps, surtout raffraichit, hein !
CreateDIBSection va permettre de faire un image stockée en RAM (Device Independant, donc pas d'echange constant avec la carte graphique)
et on affiche le tout en une fois.
clairement plus rapide, donc.
27 juin 2008 à 09:58
Merci de faire partager le résultat de tes recherches.
Je suis confronté à des problèmes de performances également sur une appli totalement skinnée avec des bitmaps.
Je cherche à savoir quelle est la meilleure combinaison de paramètres dwExStyle et dwStyle dans CreateWindowEx pour les performances.
Par exemple, je ne veut pas de contour ni de barre de titre windows, est ce que je dois demander une fenetre sans partie non cliente, et peindre une fausse barre de titre dans la partie cliente ou demander une barre de titre et des contours, mais surcharger le message PAINT de la partie non cliente pour la faire à mon gout ?
J'ai remarqué assez vite des problèmes de performances, et des "pertes de messages windows", qui peuvent être résolues en mettant des DoEvents (la boucle infinie qui traite la pile des messages, la boucle même dont vous parlez avec F_L_A_S_H_B_A_C_K), je suis étonné de devoir en arriver là, ca ne paraît pas très propre..
Est tu sur que SetPixel est lent ?
Comment le fait d'utiliser CreateDIBSection() et de tout faire à la main peut il être plus rapide que d'utiliser les fonctions windows faites pour ?
Merci d'avance
2 mai 2008 à 11:52
J'ai essayé chez moi, en modifiant un peu :
void Dess(HWND hwnd)
{
PAINTSTRUCT PaintStruct ;
HDC DC;
DC = BeginPaint(hwnd, &PaintStruct);
BitBlt (DC, 0, 0, LARGEUR, HAUTEUR, hMDC, 0, 0, SRCCOPY);
EndPaint(hwnd, &PaintStruct);
}
Ca ne marche pas (si en plus on enlève le traitement des WP_PAINT, la fenêtre n'affiche rien).
Je crois pas qu'on puisse dessiner avec BeginPaint()/EndPaint() en dehors d'un WM_PAINT : la zone invalide est vide, donc tous les opérations graphiques qu'on effectue ne servent à rien. En tous cas msdn spécifie qu'il faut utiliser GetDc()/ReleaseDC() en dehors d'un WP_PAINT.
1 mai 2008 à 23:07
je ferais plus ca...
void dess(HWND hwnd)
{
PAINTSTRUCT PaintStruct ;
HDC DC = BeginPaint(hwnd, &PaintStruct);
HDC hMDC = CreateCompatibleDC(DC);
HBITMAP OldBmp = SelectBitmap(hMDC, le_bitmap);
BitBlt (hDC, 0, 0, LARGEUR, HAUTEUR, hMDC, 0, 0, SRCCOPY);
DeleteDC(PicDC);
EndPaint(hwnd, &PaintStruct);
}
for(;;) {
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( !GetMessage( &msg, NULL, 0, 0 ) ) return msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else { Dess(hwnd); }
}
30 avril 2008 à 21:53
for(;;) {
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( !GetMessage( &msg, NULL, 0, 0 ) ) return msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
HDC hDC = GetDC (hwnd);
BitBlt (hDC, 0, 0, LARGEUR, HAUTEUR, hMDC, 0, 0, SRCCOPY);
ReleaseDC (hwnd, hDC);
}
}
Ca ne change pas mon problème : il y a toujours un manque de syncronisation entre le raffraichissement de l'écran et le raffraichissement de la mémoire.
Le seul changement, c'est que l'image est raffraichie le plus souvent possible, ce qui prend tout le temps processeur. Bien entendu c'est l'optimal pour un jeu en full-screen, mais pour une application qui utilise le GDI et qui n'est pas complemtement axée sur le grapisme, c'est pas ce qu'il faut.
Je pense qu'on peut obtenir le même résultat en n'appelant pas EndPaint() pendant le traitement d'un message WM_PAINT : la fenêtre a toujours une zone invalide et donc Windows envoie sans arret des messages WM_PAINT.
30 avril 2008 à 18:54
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
par
while( 1 ) {
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( !GetMessage( &msg, NULL, 0, 0 ) ) return msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
/////////////////
un flip();
ou une fonction sur ton BitBlt()
//////////////////
}
ou lieu de le mettre ton bitblt() dans WM_PAINT:
sa devrais eliminer ton 'flicker'
30 avril 2008 à 18:28
30 avril 2008 à 13:43
30 avril 2008 à 12:02
30 avril 2008 à 07:31
en switchant les hBmp
30 avril 2008 à 00:58
pour hDC je l'ai mis en Common Display Device Context plutot que en Private Display Device Context, vu que seul hMDC a besoin d'être accedé courament. Pas de problème constaté.
30 avril 2008 à 00:35
Referme hDC obtenu dans WM_CREATE et utilise le retour de BeginPaint pour dessiner dans WM_PAINT.