Auswahlrechteck mit Maus aufziehen

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Auswahlrechteck mit Maus aufziehen

Beitrag von SMaag »

Wie Auswahlrechteck mit Maus aufziehen?
Gibt es dafür eine Standardfunktion?

Ich erinnere mich dunkel, dass es dafür in Windows eine API gibt. Diese aber in PB zu verwenden
ist nicht die Lösung, da das dann nur in Windows funktioinert!

Wie macht ihr das?
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von Macros »

Die Frage ist, was willst du auswählen, und worauf?

Im Prinzip brauchst du eine Funktion um das darunter zu zeichnen.

Dann hängst du einen Aufruf an ein Rechteck zu zeichnen.
Koordinaten: Da wo es das Event gab, dass die Maustaste gedrückt wurde. (in Variable speichern)
Koordinaten 2: Aktuelle Mausposition.

Verwendest du die Vektorbibliothek ist es auch einfach den typischen gestrichelten Rahmen zu zeigen. DashPath()
Über die beiden Koordinaten kannst du dann auch bestimmen welche Objekte ausgewählt wurden, sobald der Nutzer die Maus wieder loslässt.

Optimieren kann man natürlich einiges. Z.B. bei weiterer Mausbewegung nur den Teil neuzeichnen,
wo das Rechteck zuvor drüber war und dann das neue Rechteck. Aber meistens sollte das nicht notwendig sein.
Oder z.B. aus dem darunter ein Bild generieren, falls es aufwendig zu zeichnen ist, und dann das Rechteck jeweils über das Bild zeichnen.
Bild
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von SMaag »

Also hand made! Kann mir immer noch nicht vorstellen, dass es dafür keine Standardlösung gibt!

Wenn man das Flackerfrei haben möchte, dann wohl mit OpenScreen und FlipBuffers()

Das mit dem Bild generieren hab ich mir auch schon überlegt.
- Kopie der aktuellen Ausgabe in einen Puffer sichern
- Auf Ausgabe Rechteck zeichnen
- Bei Mausbewegung Puffer wieder in Ausgabe kopieren und neues Rechteck zeichnen
(Puffer wieder in Ausgabe kopieren evtl. mit DrawVectorImage() und instransparentem Alpha)
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von ccode_new »

Beispiel:

Du reagierst auf ein Maustaste-Links-gedrückt-Event und speicherst die aktuelle Mausposition ab.
Dann checkst du ob die Maustaste gedrückt gehalten wird und zeichnest nur dann dein Auswahlrechteck.
Dabei ist die gespeicherte Mausposition dein Startpunkt und deine aktuelle Mausposition der Endpunkt.
Nun reagierst du noch auf ein Loslassen der gedrückten Maustaste und schließt die Auswahl ab. Diese Zustände kannst du mit "Merker"-Variablen auswerten.
Am besten speicherst du die Rechteckkoordinaten direkt in eine Rechteck-Struktur.
So nun kann beim Zeichnen auf Kollision mit deinem Rechteck geprüft werden.
Alle Dinge deren Koordinaten innerhalb des Rechtecks liegen hast du dann theoretisch ausgewählt.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Lord
Beiträge: 324
Registriert: 21.01.2008 19:11

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von Lord »

Hier mal ein erster Denkansatz:

Code: Alles auswählen

EnableExplicit
Define.i Event

Procedure CanvasEvents()
  Static.i LMB, x1, y1, x2, y2, x2merk, y2merk
  Protected EventType
  EventType=EventType()
  Select EventType
    Case #PB_EventType_MouseEnter
      SetGadgetAttribute(1, #PB_Canvas_Cursor, #PB_Cursor_Cross)
    Case #PB_EventType_MouseLeave
      SetGadgetAttribute(1, #PB_Canvas_Cursor, #PB_Cursor_Default)
    Case #PB_EventType_LeftDoubleClick  
    Case #PB_EventType_RightButtonDown
      StartDrawing(CanvasOutput(1))
        DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_XOr)
        Box(x1, y1, x2-x1, y2-y1, 255)
      StopDrawing()
    Case #PB_EventType_LeftButtonDown
      LMB=#True
      x1=GetGadgetAttribute(1, #PB_Canvas_MouseX):x2merk=x1
      y1=GetGadgetAttribute(1, #PB_Canvas_MouseY):y2merk=y1
    Case #PB_EventType_LeftButtonUp
      LMB=#False
       StartDrawing(CanvasOutput(1))
        DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_XOr)
        Box(x1, y1, x2-x1, y2-y1, 255)
      StopDrawing()
    Case #PB_EventType_MouseMove
      If LMB=#True
        x2=GetGadgetAttribute(1, #PB_Canvas_MouseX)
        y2=GetGadgetAttribute(1, #PB_Canvas_MouseY)
        StartDrawing(CanvasOutput(1))
          DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_XOr)
          Box(x1, y1, x2merk-x1, y2merk-y1, 255)
        StopDrawing()
        StartDrawing(CanvasOutput(1))
          DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_XOr)
          Box(x1, y1, x2-x1, y2-y1, 255)
        StopDrawing()
        x2merk=x2:y2merk=y2
      EndIf
    Default
      StartDrawing(CanvasOutput(1))
        DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_XOr)
        Box(x1, y1, x2-x1, y2-y1, 255)
      StopDrawing()
    EndSelect
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
CanvasGadget(1, 0, 0, WindowWidth(1), WindowHeight(1), #PB_Canvas_Keyboard|#PB_Canvas_ClipMouse)
If StartDrawing(CanvasOutput(1))
    Box(10, 10, 200, 100, #Green)
    DrawingMode(#PB_2DDrawing_XOr)
    Box(100, 50, 500, 400, #Blue)
    DrawingMode(#PB_2DDrawing_Default)
    Circle(350, 250, 100, #Red)
  StopDrawing()
EndIf
BindGadgetEvent(1, @CanvasEvents())

Repeat
  Event=WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Bild
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von Macros »

Danke für die Vorlage Lord.

Hier mal flott wie ich mir das mit der Vektorbibliothek vorgestellt hatte:

Code: Alles auswählen

EnableExplicit
Define.i Event

Procedure CanvasEvents()
  Static.i LMB, x1, y1, x2, y2, temp_image
  Select EventType()
    Case #PB_EventType_LeftButtonDown
      ; Bild sichern
      StartDrawing(CanvasOutput(1))
      temp_image=GrabDrawingImage(#PB_Any,0,0,OutputWidth(),OutputHeight())
      StopDrawing()
      ; Mausposition merken
      LMB=#True
      x1=GetGadgetAttribute(1, #PB_Canvas_MouseX)
      y1=GetGadgetAttribute(1, #PB_Canvas_MouseY)
    Case #PB_EventType_MouseMove
      If LMB=#True
        ; neue Mausposition
        x2=GetGadgetAttribute(1, #PB_Canvas_MouseX)
        y2=GetGadgetAttribute(1, #PB_Canvas_MouseY)
        ;Zuerst das vorige Bild, dann den typischen Strichelrahmen
        StartVectorDrawing(CanvasVectorOutput(1))
        DrawVectorImage(ImageID(temp_image))
        AddPathBox(x1, y1, x2-x1, y2-y1)
        VectorSourceColor($ffFF0000)
        DashPath(2,5)
        StopVectorDrawing()
      EndIf
    Case #PB_EventType_LeftButtonUp
      LMB=#False
      ; Aufräumen wenn Maus losgelassen, wir zeichnen wieder das Ursprungsbild
      StartVectorDrawing(CanvasVectorOutput(1))
      DrawVectorImage(ImageID(temp_image))
      StopVectorDrawing()
      FreeImage(temp_image)
      ; Nun berechnet man, was innerhalb der Koordinaten von x1,x2,y1,y2 liegt und merkt es sich,
      ; natürlich sollte es auch dem Nutzer kenntlich gemacht werden.
      ; Alternativ auch schon während MouseMove, besser für den Nutzer, aber dann kann man nicht einfach das alte Bild drunterzeichen,
      ; sondern müsste aus dem Block unten zwischen StartDrawing und Stopdrawing eine Funktion machen, die stattdessen aufgerufen wird.
    EndSelect
EndProcedure

OpenWindow(1, 10, 10, 640, 480, "")
CanvasGadget(1, 0, 0, WindowWidth(1), WindowHeight(1), #PB_Canvas_Keyboard|#PB_Canvas_ClipMouse)
SetGadgetAttribute(1, #PB_Canvas_Cursor, #PB_Cursor_Cross)
If StartDrawing(CanvasOutput(1))
    Box(10, 10, 200, 100, #Green)
    DrawingMode(#PB_2DDrawing_XOr)
    Box(100, 50, 500, 400, #Blue)
    DrawingMode(#PB_2DDrawing_Default)
    Circle(350, 250, 100, #Red)
  StopDrawing()
EndIf
BindGadgetEvent(1, @CanvasEvents())

Repeat
  Event=WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
Bild
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von SMaag »

That's it!

Genau nach so etwas wie den Trick mit dem XOR-Modus hab ich gesucht!
man zeichnet die Box, bevor man die neue zeichnet, überzeichnet man die alte und dann ist sie
einfach weg.

Mir ist zwar noch nicht bis ins Detail klar warum das funktioniert aber das ist erst mal egal!

hab hier was dazu gefunden!
https://www.codeproject.com/Articles/16 ... ine-in-GDI

Was ich bei dem XOR nicht verstehe ist folgendes!

Wenn ich die RGB Color-Werte XOR Verknüpfe, müsste sich doch bei dem Rechteck in jedem Pixel
die Farbe (je nach Hintergrund) ändern, so dass ein kunterbunter Mix dabei rauskommt.
Warum bleibt die Farbe des Rechtecks konstant??
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von SMaag »

gerade aufgefallen!

Das Beispiel mit dem VektorDrawing verwendet nicht den XOR-Modus.
hab jetzt kurz recherchiert und festgestellt, dass es das bei VecotrDrawing anscheinend nicht gibt.
Wenn ich die RGB Color-Werte XOR Verknüpfe, müsste sich doch bei dem Rechteck in jedem Pixel
die Farbe (je nach Hintergrund) ändern, so dass ein kunterbunter Mix dabei rauskommt.
Warum bleibt die Farbe des Rechtecks konstant??
Ich hab's gesehen, die Farbe bleibt auch nicht konstant, sondern ändert sich mit dem Hintergrund!
SMaag
Beiträge: 184
Registriert: 08.05.2022 12:58

Re: Auswahlrechteck mit Maus aufziehen

Beitrag von SMaag »

jeweils eine dickes Dankeschön an Lord und Macros

ich hab's vollständig kapiert!

was man dazu noch brauchen kann:
BeginVectorLayer: Beginnt einen neuen leeren Layer (Schicht) oberhalb der aktuellen Vektorzeichnen-Ausgabe. Alle nachfolgenden Zeichenoperationen werden auf diesem Layer ausgeführt.

SaveVectorState(): Speichert den aktuellen Vektorzeichnen-Status, um ihn später wieder herzustellen.

Diese Funktionen waren mir noch gar nicht aufgefallen!

Ich hatte schon vor einiger Zeit hier mal eine Frage aufgeworfen: überlagertes Zeichnen!
Das geht genau mit den Funktionen
Antworten