Zeichnen in Window

Anfängerfragen zum Programmieren mit PureBasic.
MacThommes
Beiträge: 21
Registriert: 11.11.2025 15:38

Re: Zeichnen in Window

Beitrag von MacThommes »

um zurück zum Thema zu kommen: So sähe es mit einem ImageGadget aus:
Hab grad mal probiert....
Das funktioniert....
Heissa. Du bist mein Held!!
Ich liebe dieses Forum. So schnell, wie einem hier geholfen wird.
Das werde ich mir mal gleich ansehen um zu verstehen, wo da der Haken ist.
Also erst mal DANKE!!
Benutzeravatar
Kiffi
Beiträge: 10718
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Zeichnen in Window

Beitrag von Kiffi »

wie Axolotl schon erwähnte:
Axolotl hat geschrieben: 11.11.2025 17:50Generell ist es besser ein Gadget zu verwenden, da die Rekonstruktion dann vom Gadget übernommen wird.
Geeignet wären hier ImageGadget oder CanvasGadget, abhängig davon wohin die Reise gehen soll.
a²+b²=mc²
Benutzeravatar
Shardik
Beiträge: 749
Registriert: 25.01.2005 12:19

Re: Zeichnen in Window

Beitrag von Shardik »

Axolotls modifiziertes Beispiel (mit #PB_Event_Repaint) läuft bis MacOS 10.13 'High Sierra' ebenfalls problemlos. Ab MacOS 10.14 'Mojave' hat Apple jedoch interne Änderungen vorgenommen, sodass ein direktes Zeichnen mit StartDrawing(WindowOutput()) seitdem nicht mehr funktioniert (und wovon ja sowieso abgeraten wird). Ab MacOS 'Mojave' hat ein NSWindow-Fenster immer automatisch den NSBackingStoreType NSBackingStoreNonretained, was bewirkt, dass Grafikoperationen direkt auf einem Fenster nicht mehr erscheinen. Das Fenster-Attribut NSBackingStoreNonretained kann leider nicht deaktiviert werden.

Mit API-Befehlen kann man aber auch in neueren MacOS-Versionen (erfolgreich getestet auf MacOS 15.7.1 'Sequoia') durch Einfügen eines Subview als Layer direkt in die Fensterfläche zeichnen. Hier ist ein Beispiel:

Code: Alles auswählen

EnableExplicit

Procedure DrawBox()
  Protected ContentView.I
  Protected Frame.NSRect
  Protected Layer.I
  Protected View.I

  Frame\origin\x = 100
  Frame\origin\y = 30
  Frame\size\width = 100
  Frame\size\height = 100
  View = CocoaMessage(0, CocoaMessage(0, 0, "NSView alloc"),
    "initWithFrame:@", @Frame)
  CocoaMessage(0, View, "setWantsLayer:", #YES)
  Layer = CocoaMessage(0, View, "layer")
  CocoaMessage(0, Layer,
    "setBackgroundColor:", CocoaMessage(0, CocoaMessage(0, 0,
    "NSColor redColor"), "CGColor"))
  ContentView = CocoaMessage(0, WindowID(0), "contentView")
  CocoaMessage(0, ContentView, "addSubview:", View)
EndProcedure

OpenWindow(0, 170, 100, 300, 200, "WindowOutput Example")
ButtonGadget(0, (WindowWidth(0) - 200) / 2, (WindowHeight(0) - 30) - 10, 200,
  30, "Draw red box into Window")

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0
        DrawBox()
        DisableGadget(0, #True)
      EndIf
  EndSelect
ForEver
Benutzeravatar
mk-soft
Beiträge: 3869
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Zeichnen in Window

Beitrag von mk-soft »

Mit einer älteren macOS Version ging es noch, dann wurde an der OS etwas geändert.
Es ist immer besser eine ImageGadget oder ein CanvasGadget zu nehmen. Dann muss man sich nicht selber um das neu Zeichnen zu kümmern.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
MacThommes
Beiträge: 21
Registriert: 11.11.2025 15:38

Re: Zeichnen in Window

Beitrag von MacThommes »

Mit API-Befehlen kann man aber auch in neueren MacOS-Versionen (erfolgreich getestet auf MacOS 15.7.1 'Sequoia') durch Einfügen eines Subview als Layer direkt in die Fensterfläche zeichnen. Hier ist ein Beispiel:
Auch nicht schlecht. Funktioniert und bringt mich - so wie das andere Beispiel - schon mal viel weiter.
Danke an alle hier!
Ich denke, wir können das Thema schließen.
Aber keine Angst... Da kommen bestimmt noch einige Fragen von mir. :)
MacThommes
Beiträge: 21
Registriert: 11.11.2025 15:38

Re: Zeichnen in Window

Beitrag von MacThommes »

Hab da was seltsames gefunden:

Code: Alles auswählen

If OpenWindow(0, 800, 400, 800, 400, "Testfenster", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  ButtonGadget(0, 340, 370, 100, 20, "OK", #PB_Button_Default)
  SetWindowColor(0,RGB(30,30,30))
  If CreateImage(1, 800, 400) And StartDrawing(ImageOutput(1))
    Box(0, 0, 800, 400, RGB(255, 0, 0))
    
    ImageGadget(0, 0, 0, 800, 400, ImageID(1))
  EndIf
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget, #PB_Event_CloseWindow ; Gadget wurde angeklickt oder Fenster geschlossen
        out = 1
    EndSelect   
  Until out = 1  
  End
EndIf
Hier soll Fensterfüllend ein Viereck gezeichnet werden. Es wird aber nur die Hälfte gezeichnet.
Das Heisst: Dieses Viereck ist nur halb so hoch und halb so breit.
Aufgefallen ist mir das, als ich das Progrämmchen, was ich gerade schreibe, mal unter Linux compiliert habe. Da stimmt nichts mehr.
Eigentlich gehe ich davon aus, das die Werte, die bei den Befehleb wie Box, Circle usw. angegeben werden die Pixel sind.
Aber auf dem Mac ist das irgendwie nur die Hälfte.
Verdopple ich die Werte, funktioniert es....

Code: Alles auswählen

If OpenWindow(0, 800, 400, 800, 400, "Testfenster", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  ButtonGadget(0, 340, 370, 100, 20, "OK", #PB_Button_Default)
  SetWindowColor(0,RGB(30,30,30))
  If CreateImage(1, 1600, 800) And StartDrawing(ImageOutput(1)) ; Doppelte Werte
    Box(0, 0, 1600, 800, RGB(255, 0, 0)) ; Doppelte Werte
    
    ImageGadget(0, 0, 0, 1600, 800, ImageID(1)); Doppelte Werte
  EndIf
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget, #PB_Event_CloseWindow ; Gadget wurde angeklickt oder Fenster geschlossen
        out = 1
    EndSelect   
  Until out = 1  
  End
EndIf
Oder hab ich da einen Denkfehler?
Ich bin da jetzt sehr irritiert oder zu blöde?.
Benutzeravatar
mk-soft
Beiträge: 3869
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Zeichnen in Window

Beitrag von mk-soft »

Es fehlt auf dem fall StopDrawing

Was hast du für einen Monitor und Welche Auflösung hast du. macOS Auflösung ist nicht unbedingt die Pixel Auflösung

Code: Alles auswählen

If OpenWindow(0, 800, 400, 800, 400, "Testfenster", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  ButtonGadget(0, 340, 370, 100, 20, "OK", #PB_Button_Default)
  SetWindowColor(0,RGB(30,30,30))
  If CreateImage(1, 1600, 800)
    If StartDrawing(ImageOutput(1)) ; Doppelte Werte
      Box(0, 0, 1600, 800, RGB(255, 0, 0)) ; Doppelte Werte
      StopDrawing()
    EndIf
    ImageGadget(0, 0, 0, 1600, 800, ImageID(1)); Doppelte Werte
  EndIf
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget, #PB_Event_CloseWindow ; Gadget wurde angeklickt oder Fenster geschlossen
        out = 1
    EndSelect   
  Until out = 1  
  End
EndIf
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
MacThommes
Beiträge: 21
Registriert: 11.11.2025 15:38

Re: Zeichnen in Window

Beitrag von MacThommes »

Hab die Auflösungen auf 2560 x 1440 stehen.
Beide Systeme laufen auf dem selben Rechner mit der selben Auflösung...
StopDrawing ist da. Vielleicht an der falschen Stelle, aber das Viereck wird gezeichnet.
MacThommes
Beiträge: 21
Registriert: 11.11.2025 15:38

Re: Zeichnen in Window

Beitrag von MacThommes »

Was ich nicht verstehe:
Wenn ich ein Fenster mit den Maßen 800 x 400 öffne und mir da ein Image von 800 x 400 erstelle (egal wie groß jetzt die Auflösung des Display ist, dann sollte dort auch ein Viereck von 800 x 400 die selbe Größe haben, oder?
Ich muß (!) die Werte bei CreateImage(), bei Box() und bei ImageGadget() verdoppeln - also 1600 x 800 - damit das Fenster ausgefüllt wird.
Unter Linux nicht....
Unter Windows 11 (Mit Parallels) ist es noch schlimmer. Da muß ich den Wert mehr wie verdreifachen, damit es passt.

Code: Alles auswählen

 
 out = 0
 ScreenBreite = DesktopWidth(0)
 ScreenHoehe = DesktopHeight(0)
 InfoBreite = 800
 InfoHoehe = 400
    
 If OpenWindow(1, (ScreenBreite/2)-400, (ScreenHoehe/2)-200, InfoBreite, InfoHoehe, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
      SetWindowColor(1,RGB(30,30,30))
      If CreateImage(1, InfoBreite, InfoHoehe) ; 800 Pixel breit und 400 Pixel hoch....
        Debug Str(InfoBreite)+ "   "+Str(InfoHoehe) ; Werden hier auch ausgegeben.
        StartDrawing(ImageOutput(1))
        Box(0,0,InfoBreite,InfoHoehe, RGB(255,0,0))  ; Soll eine Box von 800 x 400 in Rot zeichnen
        ImageGadget(1, 0, 0, 800, 400, ImageID(1)).    ; 800 x 400.... darstellen
        StopDrawing()
      EndIf
      ButtonGadget(5, 350, 370, 100, 20, "OK", #PB_Button_Default) ; noch einen Button drüberbügeln....
      Repeat
        Event = WaitWindowEvent()
        Select Event
          Case #PB_Event_Gadget, #PB_Event_CloseWindow ; Gadget wurde angeklickt oder Fenster geschlossen
            out = 1
        EndSelect   
      Until out = 1  
    CloseWindow(1)
    End
  EndIf
Benutzeravatar
Bisonte
Beiträge: 2474
Registriert: 01.04.2007 20:18

Re: Zeichnen in Window

Beitrag von Bisonte »

Das riecht gewaltig nach Skalierung ;)
Schau mal in den OS Einstellungen ob da eine Skalierung eingestellt ist...

Dann sind DesktopScaleX() usw. einen näheren Blick in die Hilfe Wert ...
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Antworten