mausabfrage/setpixel funktioniert nicht ganz...



  • Hallo zusmamen,

    ich beschäftige mich seit kurzem mit WINAPI. ich habe mir da nun mal was zusammengebastelt. Funktioniert eigentlich. Nun wollte ich mal was anderes probieren und stecke fest. würde mich freuen,w enn mir jemand weiter helfen könnte.
    ich möchte ein Fenster öffnen (Klappt auch) in desem Fenster möchte ich mit der Maus klicken. An der Stelle, wo ich dann mit der MAus klicke, soll dann ein Pixel farbig gessetzt werden. Wenn ich das ganze in

    case WM_LBUTTONDOWN:
    

    mache, funktioniert das auch. da habe ich nur das problem, dass wenn man die fenstergröße ändert, das gezeichnete weg ist.
    nun wollte ich das wie folgt anstellen. das programm läuft auch, nur wenn man klickt, wird nichts gezeichnet 😞

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
       static RECT     rect;
       static POINT    point;
    
       switch (message)
       {
          case WM_SIZE:
          {
             rect.left    = 0;
             rect.top     = 0;
             rect.right  = LOWORD(lParam);
             rect.bottom = HIWORD(lParam);
             return 0;
          }
          case WM_CREATE:
          {
             point.x  = -1;
             point.y  = -1;
             return 0;
          }
          case WM_DESTROY:
          {
             PostQuitMessage(0);
             return 0;
          }
          case WM_LBUTTONDOWN:
          {
             HDC  hDC = GetDC(hWnd);
             //SetPixel(hDC, LOWORD(lParam), HIWORD(lParam), RGB(0, 0, 255));
             //ReleaseDC(hWnd, hDC);
    
             //Daten in der POINT Struktur speichern
             point.x  = LOWORD(lParam);
             point.y  = HIWORD(lParam);
             return 0;
          }
          case WM_PAINT:
          {
             PAINTSTRUCT   ps;
             HDC           hDC;
    
             hDC = BeginPaint(hWnd, &ps);
             {
    	    SetPixel(hDC, point.x, point.y, RGB(0, 0, 255));
                ReleaseDC(hWnd, hDC);
    	 }
    	 EndPaint(hWnd, &ps);
             return 0;
          }
       }
       return DefWindowProc(hWnd, message, wParam, lParam);
    }
    


  • Das deine Zeichnung immer verschwindet liegt wohl an den Fenstereigenschaften. Das Fenster zeichnet sich jedesmal neu beim Resizen und daher wird die Zeichnung übermalt. Direkt auf einem Fenster zu malen ist allerdings nie eine gute Idee.

    Ansonsten musst du die Sache so machen:
    Beim setzen des Pixels in WM_LBUTTONDOWN: musst du die Koordinaten abspeichern in eine Art Verknüpfte Liste, ein Array oder sonstwas, damit du sie später wieder hast. Dann setzt du den Pixel per SetPixel().
    Im WM_PAINT: gehst du nun alle deine Pixelkoordinaten der Reihe nach durch und setzt sie erneut. Denn wenn WM_PAINT: aufgerufen wird wurde das Fenster ja teils zerstört und wird neu aufgebaut. Daher werden auch die gesetzten Pixel "übermalt". Diese musst du also neu setzen.

    So wie du das jetzt regelst sieht es so aus, als wenn du die Koordinaten eines Pixels zwar bei WM_MBUTTONDOWN speicherst, aber damit nur den zuletzt gesetzten Pixel eben, und nicht alle vorherigen. Damit wird dann bei WM_PAINT: nur ein Pixel neu gesetzt. Und jedesmal wenn ein weiterer dazu kommt muss vor dem Anzeigen erst WM_PAINT aufgerufen werden (was alle anderen Pixel wieder löscht) und wieder nur ein Pixel da erscheinen lässt.
    Ich empfehle daher die oben genannte Methode mit der Verknüpften Liste. 😉



  • hallo,
    vielen dank. ich habe es zum test erst einmal so gemacht, das ich nur ein pixel speichere, es beim mausklick setzte und dann wenn die fenstergröße geändert wird, neu zeichne.

    Direkt auf einem Fenster zu malen ist allerdings nie eine gute Idee.

    wie sollte man es denn besser machen?



  • Das kommt nun darauf an, was du genau machen möchtest. Wenn es eine Art Zeichenprogramm werden soll, wieso "malst" du dann nicht praktisch in einen Speicherbereich und zeigst dies als bitmap an? Also anstatt über SetPixel die einzelnen Pixel zu setzen erstellst du dir ein char array mit den Dimensionen deines Malbereichs und änderst in diesem Speicherbereich die Byte in die gewünschte Farbe um. Dann am Ende noch mit entsprechender Funktion (etwa SetDIBitsToDevice) auf dem Fenster anzeigen und dies auch in der WM_PAINT: Message machen, damit beim Erneuern des Fensters das Bitmap neu gezeichnet wird.



  • Wow, das hört sich abgefahren an ;-), zumindest für mich als anfänger. ich glaube so was ist eher was für einen fortgeschrittenen. mal sehen.

    Soll kein malprogramm werden. der user soll nur in der lage sein durch mausklick ein paar punkte zu setzen. klingt im moment vielleicht etwas wenig, ist aber nur der anfang.

    habe jetzt festgestellt, dass wenn ich das fenster maximiere und links oben in der ecke einen punkt sezte, das fenster dann kleiner mache, der punkt nicht mehr da ist und wenn ich es dann wieder maximiere ist er wieder da. zauberei 😉
    wenn ich das fenster klein habe, dann am fensterrand einen kreis setze, das fenster maximiere, ist der kreis quasi mitten im fenster.
    Lasse übrigens jetzt schon mal kleine kreise zeichnen.

    muss ich die koordinaten irgendwie besonders angeben, damit die Punkte/kreise immer angezeigt werden?


Anmelden zum Antworten