[C] Programmation Windows

Programmation Windows [C] - Programmation

Marsh Posté le 10-06-2001 à 15:12:32    

Bon, je commence à apprendre la programmation sous Windows. J'arrive à créer une fenêtre et à afficher une phrase, mais pour ça je passe par un une fonction BeginPaint() quand l'application reçoit le message WM_PAINT.
 
Et puis bon, DrawText(hdc, "Bonjour", -1, &rect, DT_SINGLELINE); juste pour afficher "Bonjour" c'est lourd je trouve... Y a pas de moyen plus rapide?

 

[edit]--Message édité par Alload--[/edit]

Reply

Marsh Posté le 10-06-2001 à 15:12:32   

Reply

Marsh Posté le 10-06-2001 à 21:54:51    

A priori ce que tu programmes, c'est l'API Windows, donc du C.
Ca semble peut etre un peu lourd au debut, mais tu controles tout.
Tres rapidement tu vas progresser, ecrire tes propres fonctions encapsulant les fonctions de la SDK...
 
Y'a d'autres trucs qui existent (Les MFC par exemple) pour simplifier la tache, mais bon, personellement, je preferre utiliser les APIs.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 10-06-2001 à 21:59:42    

Oki, ben je vais voir alors. Le bouquin d'où j'apprend aborde les MFC maintenant, je vais voir à quoi ça sert.
:)
 
Merci.

Reply

Marsh Posté le 10-06-2001 à 22:09:33    

Les MFC, c'est un framework C++.
Ca marche assez bien, mais c'est une implem assez peu logique.
Faut que tu suive betement tout un tas de regles precises (qui vont generer un paquet de macros lors de la compil) pour que ca fonctionne.
Un conseil, soit tu programmes en MFC, soit tu programmes avec les APIs, mais dans un premier temps n'essayes pas de melanger les deux.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 10-06-2001 à 22:28:18    

J'arrive pas à faire changer le texte affiché par ma fenêtre lorsque que quelqu'un double clique gauche dessus. Où est l'erreur dans mon code?
 
#include <windows.h>
 
 
long WINAPI WndProc(HWND hwnd, UINT message, UINT wParam, long lParam)
{
 HDC hdc;
 PAINTSTRUCT ps;
 RECT rect;
 
 switch (message)
 {
 case WM_PAINT:
  {
   hdc = BeginPaint(hwnd, &ps);
   GetClientRect(hwnd, &rect);
   DrawText(hdc, "Window Project", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
   EndPaint(hwnd, &ps);
 
   return 0;
  }
 
 case WM_LBUTTONDBLCLK:
  {
   hdc = BeginPaint(hwnd, &ps);
   GetClientRect(hwnd, &rect);
   DrawText(hdc, "Vous avez double-cliqué sur la fenêtre.", -1, &rect, DT_SINGLELINE | DT_CENTER |DT_VCENTER);
   EndPaint(hwnd, &ps);
 
   return 0;
  }
 
 case WM_DESTROY:
  {
   PostQuitMessage(0);
 
   return 0;
  }
 
 default:
  {
   return (DefWindowProc(hwnd, message, wParam, lParam));
  }
 }
}
 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
 HWND hwnd;
 WNDCLASSEX wndclassex;
 MSG msg;
 
 
 const char szClassName[] = "Window Class";
 
 wndclassex.lpszClassName = szClassName;
 wndclassex.cbSize = sizeof(wndclassex);
 wndclassex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
 wndclassex.hInstance = hInstance;
 wndclassex.lpfnWndProc = WndProc;
 wndclassex.cbClsExtra = 0;
 wndclassex.cbWndExtra = 0;
 wndclassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 wndclassex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
 wndclassex.hCursor = LoadCursor(NULL, IDC_ARROW);
 wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 wndclassex.lpszMenuName = NULL;
 
 if (!RegisterClassEx(&wndclassex))
  return 1;
 
 
 hwnd = CreateWindowEx( NULL,
       szClassName,
       "Window Project",
       WS_OVERLAPPEDWINDOW | WS_VISIBLE,
       100,
       100,
       640,
       480,
       NULL,
       NULL,
       hInstance,
       NULL);
 
 
 while (GetMessage(&msg, NULL, 0, 0))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
 
 return 0;
}

Reply

Marsh Posté le 11-06-2001 à 01:43:23    

Ton probleme vient du traitement du WM_PAINT:
A chaque redraw de la window, tu reecris Window Project dans ta fenetre... De plus tu n'indiquais pas a la fenetre qu'elle devait etre redessinee.
Je te donne un exemple de ce que tu pourrais utilises.
Le truc de base: tu indiques la zone a redessiner par InvalidateRect, et tu indiques qu'il faut redessiner, par UpdateWindow. Tu redessines ce qu'il faut redessiner
(donc: BeginPaint/.../EndPaint) dans le WM_PAINT
Dans ce cas precis, le parametre de la zone a redessiner etant NULL, a priori, le UpdateWindow qui suit est a redondant et sans doute inutile. Je l'ai laisse pour que tu voies une sequence standard.
Je t'ai mis en rouge deux trucs qui manquaient/incorrects a priori.
Le ShowWindow suit le CreateWindowEx, c'est le standard; ca a l'air de marcher sans, sans doute avec des parametres par defaut. Autrefois ca n'aurait pas ete le cas, et c'etait la premiere erreur des debutants (pourquoi je ne vois pas la fenetre...)
Ca coute rien de la rajouter.
 
 
#include <windows.h>
 
static char buffer[256];
 
long WINAPI WndProc(HWND hwnd, UINT message, UINT wParam, long lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
 
switch (message)
{
 
case WM_CREATE:
 {
   wsprintf(buffer,"Window Project." );  
   return 0;
 }
case WM_PAINT:
  {
   hdc = BeginPaint(hwnd, &ps);
   GetClientRect(hwnd, &rect);
   DrawText(hdc, buffer, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
   EndPaint(hwnd, &ps);
   wsprintf(buffer,"Window Project." );  
   return 0;
  }
 
case WM_LBUTTONDBLCLK:
  {
   wsprintf(buffer,"Vous avez double-cliqué sur la fenêtre." );
   InvalidateRect(hwnd, NULL, TRUE);
   UpdateWindow(hwnd);
   return 0;
  }
 
case WM_DESTROY:
  {
   PostQuitMessage(0);
   return 0;
  }
 
default:
  {
   return (DefWindowProc(hwnd, message, wParam, lParam));
  }
}
}
 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HWND hwnd;
WNDCLASSEX wndclassex;
MSG msg;
 
   
const char szClassName[] = "Window Class";
 
wndclassex.lpszClassName = szClassName;
wndclassex.cbSize = sizeof(wndclassex);
wndclassex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wndclassex.hInstance = hInstance;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclassex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassex.lpszMenuName = NULL;
 
if (!RegisterClassEx(&wndclassex))
  return 1;
 
 
hwnd = CreateWindowEx( 0,
       szClassName,
       "Window Project",
       WS_OVERLAPPEDWINDOW | WS_VISIBLE,
       100,
       100,
       640,
       480,
       NULL,
       NULL,
       hInstance,
       NULL);
 
ShowWindow(hwnd, nShowCmd);
 
while (GetMessage(&msg, NULL, 0, 0))
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}
 
return 0;
}


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-06-2001 à 12:08:36    

Encore un truc, quelle est la différence entre GetMessage(&msg, NULL, 0, 0) et PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)?
 
Je sais que le PeekMessage dans ce cas détruit le message traité, qu'en est-il pour GetMessage? Quelle est la meilleure de ces deux fonctions? Ont-elles des utilisations propres?

Reply

Marsh Posté le 11-06-2001 à 13:36:54    

Il y a une grosse difference: GetMessage est bloquant: la fonction ne retourne que lorsque elle a un message a retourner (au niveau de l'OS, elle rend la main au systeme, lequel inspecte periodiquement sa file de message pour voir s'il lui rend la main).  
PeekMessage n'est pas bloquant, et retourne s'il ne trouve pas de message dans la file d'attente.
 
Tu comprends donc pourquoi la boucle principale se fait sur un while (GetMessage(&msg, NULL, 0, 0)): Soit le programme traite un message, soit il est bloque en attente d'un message. (Lorsqu'il est bloque, le systeme fait tourner les autres programmes. Le systeme alloue aussi le temps d'execution par programme par tranche, evitant qu'un programme qui s'execute sans rendre la main (justement en attendant des messages) bloque les autres. Quand il n'y a pas ce quota temporel par programme, on a ce que l'on apelle le multitache cooperatif, qui fut longtemps le modele pour la programmation Mac).
PeekMessage est utile lorsqu'on veut traiter un message particulier en premier avant de donner la main a GetMessage.
Note: les messages WM_PAINT sont traites a part pour ces deux fonctions en particulier pour permettre de bloquer un programme qui attend un message specifique (typiquement un message d'un autre programme), tout en ayant la fenetre de l'application correctement repeinte si une fenetre d'un autre programme vient a la recouvrir.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-06-2001 à 21:13:20    

euh
 
j'ai essayé de complier l'exemple que vous avez donné sous Visual C++6, et ça me donne
 
Compiling...
test.cpp
d:\test.cpp(101) : fatal error C1010: unexpected end of file while looking for precompiled header directive
Error executing cl.exe.
 
test.exe - 1 error(s), 0 warning(s)
 
 
Où y en a une erreur ?


---------------
JeanBeulz, chercheur coincheur
Reply

Marsh Posté le 11-06-2001 à 21:40:40    

Excepté le site de crosoft et l'aide de VC++ connaissez vous un bon bouquin pour se familiariser avec les fonctions de l'API de  
windows ?
Peut on attaquer toutes ses fonctions en C ?
Pour terminer, Est ce bien portable ces fonctions ?
 
Merci

Reply

Marsh Posté le 11-06-2001 à 21:40:40   

Reply

Marsh Posté le 11-06-2001 à 21:53:55    

Programmer sous Windows de Charles Petzold chez Microsoft Edition
il est bien.
c la bible du programmeur :D

Reply

Marsh Posté le 11-06-2001 à 22:32:14    

Nibbles1 a écrit a écrit :

euh
 
j'ai essayé de complier l'exemple que vous avez donné sous Visual C++6, et ça me donne
 
Compiling...
test.cpp
d:\test.cpp(101) : fatal error C1010: unexpected end of file while looking for precompiled header directive
Error executing cl.exe.
 
test.exe - 1 error(s), 0 warning(s)
 
 
Où y en a une erreur ?




Le code de gilou marche impec chez moi.

Reply

Marsh Posté le 11-06-2001 à 22:38:16    

c bon  
moi aussi  
 :pt1cable:


---------------
JeanBeulz, chercheur coincheur
Reply

Marsh Posté le 11-06-2001 à 22:39:05    

au fait alload, t'es en où en DDraw ?
tu pe mfiler ce kta fé ?


---------------
JeanBeulz, chercheur coincheur
Reply

Marsh Posté le 11-06-2001 à 23:34:44    

Alload> Je te conseille d'utiliser le fichier "windowsx.h" pour écrire tes procédures de fenêtre en API. Ce fichier définit des tas de macros (les window message crackers) pour encapsuler les procédures de fenêtre, ce qui permet d'une part d'avoir une procédure de fenêtre super courte (un appel de macro sur une ligne par message traité), et d'autre part une fonction spécifique pour chaque message traité par la procédure de fenêtre, façon méthode de classe (chaque fonction ayant un prototype prédéfini en fonction du message qu'elle traite ; autre avantage : ses paramètres sont typés, car la macro a déjà extrait tout ce qu'il fallait des paramètres wParam et lParam).
 
Par exemple :

Code :
  1. #include <windows.h>
  2. #include <windowsx.h>
  3. static char buffer[256];
  4. BOOL Wnd_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
  5. {
  6.     wsprintf(buffer, "Window Project." ); 
  7.     return 0;
  8. }
  9. void Wnd_OnPaint(HWND hwnd)
  10. {
  11.     PAINTSTRUCT  ps;
  12.     RECT         rect;
  13.     HDC          hdc = BeginPaint(hwnd, &ps);
  14.     GetClientRect(hwnd, &rect);
  15.     DrawText(hdc, buffer, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  16.     EndPaint(hwnd, &ps);
  17.     wsprintf(buffer,"Window Project." ); 
  18.     return 0;
  19. }
  20. void Wnd_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  21. {
  22.     if (fDoubleClick) {
  23.         wsprintf(buffer,"Vous avez double-cliqué sur la fenêtre." );
  24.         InvalidateRect(hwnd, NULL, TRUE);
  25.         UpdateWindow(hwnd);
  26.     }
  27.     return 0;
  28. }
  29. void Wnd_OnDestroy(HWND hwnd) {
  30.     PostQuitMessage(0);
  31.     return 0;
  32. }
  33. long WINAPI WndProc(HWND hwnd, UINT message, UINT wParam, long lParam)
  34. {
  35.     switch (message) {
  36.         return HANDLE_WM_CREATE     (hwnd, wParam, lParam, Wnd_OnCreate);
  37.         return HANDLE_WM_PAINT      (hwnd, wParam, lParam, Wnd_OnPaint);
  38.         return HANDLE_WM_LBUTTONDOWN(hwnd, wParam, lParam, Wnd_OnLButtonDown);
  39.         return HANDLE_WM_DESTROY    (hwnd, wParam, lParam, Wnd_OnDestroy);
  40.         defaultreturn DefWindowProc(hwnd, message, wParam, lParam);
  41.     }
  42. }
  43. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  44. {
  45.     HWND        hwnd;
  46.     WNDCLASSEX  wndclassex;
  47.     MSG         msg;
  48.  
  49.     const char szClassName[] = "Window Class";
  50.     wndclassex.lpszClassName = szClassName;
  51.     wndclassex.cbSize        = sizeof(wndclassex);
  52.     wndclassex.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  53.     wndclassex.hInstance     = hInstance;
  54.     wndclassex.lpfnWndProc   = WndProc;
  55.     wndclassex.cbClsExtra    = 0;
  56.     wndclassex.cbWndExtra    = 0;
  57.     wndclassex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  58.     wndclassex.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
  59.     wndclassex.hCursor       = LoadCursor(NULL, IDC_ARROW);
  60.     wndclassex.hbrBackground = GetStockBrush(WHITE_BRUSH);
  61.     wndclassex.lpszMenuName  = NULL;
  62.     if (!RegisterClassEx(&wndclassex))
  63.         return 1;
  64.     hwnd = CreateWindowEx(0,
  65.                           szClassName,
  66.                           "Window Project",
  67.                           WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  68.                           100,
  69.                           100,
  70.                           640,
  71.                           480,
  72.                           NULL,
  73.                           NULL,
  74.                           hInstance,
  75.                           NULL);
  76.     ShowWindow(hwnd, nShowCmd);
  77.     while (GetMessage(&msg, NULL, 0, 0)) {
  78.         TranslateMessage(&msg);
  79.         DispatchMessage(&msg);
  80.     }
  81.     return 0;
  82. }


 
En plus de tous ces message crackers, "windowsx.h" définit toute une liste de macros de manipulation des contrôles graphiques standard (bouton, liste déroulante, zone de texte, ....) ou qui encapsulent les fonctions noyau et qui sont utiles pour éclaicir le code.
Des trucs tout cons du genre :

Code :
  1. IsRestored(hwnd)


au lieu de devoir écrire

Code :
  1. ((GetWindowStyle(hwnd) & (WS_MINIMIZE | WS_MAXIMIZE)) == 0L)


 ou encore

Code :
  1. IsLButtonDown()


au lieu de

Code :
  1. (GetKeyState(VK_LBUTTON) < 0)


qui sont bien moins clairs à relire.

 

[edit]--Message édité par BifaceMcLeOD--[/edit]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed