1
votes

tracer une ligne ne fonctionne pas, quel pourrait être le problème?

Je veux dessiner la ligne en cliquant avec la souris sur la première coordonnée où la ligne doit commencer et la deuxième coordonnée où la ligne doit se terminer. Lorsque je lance mon projet, rien ne se passe. Je ne trouve pas ce que mon code manque.

LONG WINAPI WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{

    HDC hdc;
    BOOL fDraw = FALSE;
    POINT ptPrevious = { 0 };
    HPEN Pen = CreatePen(PS_SOLID, 3, RGB(0, 0, 255));


    switch (Message) {
        case WM_LBUTTONDOWN: {
            fDraw = TRUE;
            ptPrevious.x = LOWORD(lParam);
            ptPrevious.y = HIWORD(lParam);
            break;
        }

        case WM_LBUTTONUP: {
            if (fDraw)
            {
                hdc = GetDC(hWnd);
                MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                LineTo(hdc, LOWORD(lParam), HIWORD(lParam));
                ReleaseDC(hWnd, hdc);
            }
            fDraw = FALSE;
            break;
        }


        case WM_MOUSEMOVE: {
            if (fDraw)
            {
                hdc = GetDC(hWnd);
                MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                LineTo(hdc, ptPrevious.x = LOWORD(lParam),
                    ptPrevious.y = HIWORD(lParam));
                ReleaseDC(hWnd, hdc);
            }
            break;
        }


        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, Message, wParam, lParam);
    }
    return 0;
}


1 commentaires

Dessinez une image bitmap hors écran, puis peignez-la sur l'écran WM_PAINT.


3 Réponses :


1
votes

Ne récupérez pas le DC trois fois, récupérez-le une fois et relâchez-le en levant la souris. De plus, votre dessin sera finalement validé, vous devez donc enregistrer le mouvement de la souris et répéter ce truc dans le gestionnaire WM_PAINT.


2 commentaires

Alors puis-je déclarer une déclaration de commutateur externe DC? puis-je simplement utiliser WM_PAINT au lieu de WM_MOUSEMOVE?


Dans les applications Windows génériques, le dessin est effectué en réponse à WM_PAINT. Le dessin ne persiste pas. Cela signifie que si votre fenêtre est réduite, la prochaine maximisation ne montrera pas ce que vous avez dessiné précédemment. C'est pourquoi vous le dessinez lorsque Windows le demande, c'est-à-dire dans WM_PAINT. Lorsque vous faites un dessin en temps réel, vous pouvez utiliser GetDC () pour obtenir le contrôleur de domaine, mais aussi vous enregistrez ce que vous avez dessiné (dans votre cas, le début / fin xy), et le répétez avec un contrôleur de domaine de mémoire en réponse à WM_PAINT. Vous pouvez donc utiliser GetDC () sur WM_LBUTTONDOWN, mais enregistrez le dc jusqu'à WM_LBUTTONUP. Enregistrez ensuite ce que vous avez dessiné pour le redessiner dans WM_PAINT.



2
votes

Fondamentalement, le problème vient du fait qu'aucune de vos données n'est persistante. Comme ce sont toutes des variables locales, leur contenu disparaît lorsque WndProc revient. fDraw est défini sur FALSE sur chaque message, et ne sera jamais vrai pour les messages WM_LBUTTONDOWN ou WM_MOUSEMOVE. Rien ne se passe donc.

Vous voudrez créer une sorte de classe pour contenir fDraw , ptPrevious et une structure pour contenir les coordonnées de la ou des lignes à dessiner. Utilisez InvalidateRect dans les messages WM_MOUSEMOVE et WM_LBUTTONUP. Ensuite, dessinez-les uniquement en réponse à un message WM_PAINT (en utilisant le DC fourni dans le message de peinture).

Utilisation de La classe CWnd MFC peut grandement simplifier ces tâches.


0 commentaires

1
votes

Puisque les variables déclarées sont des variables locales, les variables peuvent être déclarées avec Static.

   LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
   HDC hdc;
   PAINTSTRUCT ps;
   static BOOL fDraw = FALSE;
   static BOOL fDraw_begin = FALSE;
   static POINT ptPrevious;
   static RECT rcClient; 
   static POINT pt;
   static HPEN Pen;

   switch (message)
   {
   case WM_CREATE:
   {
          Pen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
          break;
   }

   case WM_LBUTTONDOWN:
   {
          ptPrevious.x = (LONG)LOWORD(lParam);
          ptPrevious.y = (LONG)HIWORD(lParam);
          return 0;
   }

   case WM_LBUTTONUP:
   {
          if (fDraw = TRUE)
          {
                 fDraw = FALSE;
                 fDraw_begin = TRUE;
                 InvalidateRect(hwnd, &rcClient, TRUE);
                 UpdateWindow(hwnd);

          }
          return 0;
   }

   case WM_MOUSEMOVE: 
   {
          if (wParam && MK_LBUTTON)
          {
                 GetClientRect(hwnd, &rcClient);
                 hdc = GetDC(hwnd);
                 SetROP2(hdc, R2_NOTXORPEN);
                 if (!IsRectEmpty(&rcClient))      // Detecting whether the rectangular area is empty
                 {
                       MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                       LineTo(hdc, (LONG)LOWORD(lParam),
                              (LONG)HIWORD(lParam));
                 }
                 MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                 LineTo(hdc, (LONG)LOWORD(lParam),
                       (LONG)HIWORD(lParam));
                 pt.x = (LONG)LOWORD(lParam);
                 pt.y = (LONG)HIWORD(lParam);
                 fDraw = TRUE;

                 ReleaseDC(hwnd, hdc);
          }      
          return 0;
   }

   case WM_PAINT:
   {
          hdc = BeginPaint(hwnd, &ps);
          SelectObject(hdc, Pen);
          if (fDraw_begin)
          {
                 fDraw_begin = FALSE;
                 MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL);
                 LineTo(hdc, pt.x,
                       pt.y);
          }
          EndPaint(hwnd, &ps);
          ReleaseDC(hwnd, hdc);
          return 0;
   }

   case WM_DESTROY:
   {
          DeleteObject(Pen);
          PostQuitMessage(0);
          return 0;
   }

   }
   return DefWindowProc(hwnd, message, wParam, lParam);
   }

De plus, vous oubliez d'utiliser la fonction SelectObject pour sélectionner le stylo dans DC.

Vous pouvez également utiliser le rafraîchissement de WM_PAINT pour améliorer votre code:

Exemple:

   static BOOL fDraw = FALSE;
   static POINT ptPrevious = { 0 };


0 commentaires