Das Ende einer Grössenveränderung feststellen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Das Ende einer Grössenveränderung feststellen

Beitrag von Bisonte »

Hallo.

Ich habe ein ImageGadget und natürlich ein Image darin, in dem ein Text zentriert dargestellt wird.

Nun soll das Gadget in der Grösse verändert werden und der Text auf meinem Image soll natürlich zentriert
bleiben. Also denk ich mir, ermittel ich die neue Gadgetgrösse mit GadgetWidth() und GadgetHeight(),
um das Image in der Grösse zu ändern (ResizeImage()) und zeichne dann den Text wieder zentriert drauf.

Dann ein SetGadgetState um das Gadget mit dem Image zu aktualisieren und fertig.

Das Problem dabei ist, dass das ganze zu heftig das Programm verlangsamt.
Dabei ist der schuldige nicht das ResizeImage oder ResizeGadget sondern das SetGadgetState.

Wie bekomm ich das hin, dass erst, wenn die Grössenveränderung vollzogen ist, das Setgadgetstate ausgeführt wird,
und dann auch nur einmal ...

Ich hab da irgendwie grad eine kleine Blockade...
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​​
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: Das Ende einer Grössenveränderung feststellen

Beitrag von c4s »

#WM_EXITSIZEMOVE könnte helfen.
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: Das Ende einer Grössenveränderung feststellen

Beitrag von Bisonte »

Danke. Das wars (für eine HauptEventschleife oder WindowCallback)
Leider funktioniert das in einem "umgebogenen" CB nicht...

Code: Alles auswählen

Procedure TextCallBack(hWnd,uMsg,wParam,lParam)
  
  Protected *p.text_struct = GetProp_(hwnd, "TextCB")
  
  If uMsg = #WM_EXITSIZEMOVE 
    ResizeImage(*p\Image, GadgetWidth(*p\Gadget), GadgetHeight(*p\Gadget))
    TextGadgetExUpdate(*p) ; <- hier wird neu gezeichnet (StartDrawing....
    SetGadgetState(*p\Gadget, ImageID(*p\Image))
  EndIf
  ProcedureReturn CallWindowProc_(*p\OldProc,hWnd,uMsg,wParam,lParam)  
EndProcedure
Da wird das Event leider nicht ausgelöst
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​​
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Das Ende einer Grössenveränderung feststellen

Beitrag von Kiffi »

Achtung, Holzhammermethode!
(Zartbesaitete bitte jetzt wegschauen)

Code: Alles auswählen

#MainWindow = 0 
#MainWindowTimer = 0 

OpenWindow(#MainWindow, #PB_Ignore, #PB_Ignore, 300, 300, "", #PB_Window_SystemMenu | #PB_Window_SizeGadget)

Repeat
  
  WWE=WaitWindowEvent()
  
  Select WWE
      
    Case #PB_Event_SizeWindow
      
      If EventWindow()=#MainWindow
        If StartTimer ; Das erste Feuern des Events (nach Öffnen des Fensters) überspringen
          AddWindowTimer(#MainWindow, #MainWindowTimer, 200) ; n bißchen mit dem Timeout experimentieren
        EndIf
        StartTimer = #True
      EndIf
      
    Case #PB_Event_Timer
      
      If EventTimer()=#MainWindowTimer
        Debug "Resize End"
        RemoveWindowTimer(#MainWindow, #MainWindowTimer)
      EndIf
      
  EndSelect
  
Until WWE = #PB_Event_CloseWindow
Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: Das Ende einer Grössenveränderung feststellen

Beitrag von Bisonte »

ok ... Dafür bin ich dann doch zu zartbesaitet.

Es geht ja darum, dass ich das ganze NICHT innerhalb des WindowCallbacks oder der HauptEventschleife
versuche, sondern in einer "Callback" Prozedur, die standardisiert ist. (geht um Einbau in eine Userlib)
Damit der Endnutzer sich darum nicht mehr kümmern muss...
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​​
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Das Ende einer Grössenveränderung feststellen

Beitrag von Danilo »

Bisonte hat geschrieben:Es geht ja darum, dass ich das ganze NICHT innerhalb des WindowCallbacks oder der HauptEventschleife
versuche, sondern in einer "Callback" Prozedur, die standardisiert ist. (geht um Einbau in eine Userlib)
Damit der Endnutzer sich darum nicht mehr kümmern muss...
Wenn die Größe des Hauptfensters vom Benutzer verändert wird, dann bekommt
auch nur dieses Hauptfenster diese Nachricht, nicht die darauf liegenden Gadgets.

Du mußt Deinen Callback beim Hauptfenster installieren.

Eine kleine Anregung:

Code: Alles auswählen

;
; DeineLib.pbi
;
Structure myGadgetData
    gadget.i
    callback.i
EndStructure

Structure myGadgetCallbacks
    List gadgets.myGadgetData()
EndStructure

Procedure myGadget_WindowCallback(hWnd,msg,wParam,lParam)
  oldCallback = GetProp_(hWnd,"myGadget_oldCallback")
  ;If msg = #WM_SIZE
  If msg = #WM_EXITSIZEMOVE
    *s.myGadgetCallbacks = GetProp_(hWnd,"myGadget_ResizeCallbacks")
    If *s
        ForEach *s\gadgets()
            CallFunctionFast( *s\gadgets()\callback , *s\gadgets()\gadget, hWnd )
        Next
    EndIf
  EndIf
  If oldCallback
    ProcedureReturn CallWindowProc_(oldCallback,hWnd,msg,wParam,lParam) 
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure drawMyGadgetPicture(gadget)
    img = GetGadgetData(gadget)
    w = GadgetWidth(gadget)
    h = GadgetHeight(gadget)
    x = w * 0.5 - ImageWidth(img) *0.5
    y = h * 0.5 - ImageHeight(img)*0.5
    If img And StartDrawing(CanvasOutput(gadget))
        Box(0,0,w,h,GetSysColor_(#COLOR_BTNFACE))
        DrawImage(ImageID(img),x,y)
        StopDrawing()
    EndIf
EndProcedure

Procedure myGadget_ResizeCallback(gadget, hWnd)
    GetClientRect_(hWnd,@r.RECT)
    ResizeGadget(gadget,GadgetX(gadget),GadgetY(gadget),r\right-20,r\bottom-20)
    drawMyGadgetPicture(gadget)
EndProcedure

Procedure getCurrentGadgetWindow()  ; Aktuelles Fenster ermitteln
    Protected WindowID              ; auf dem Gadgets angelegt werden
    !extrn _PB_Gadget_Globals
    !MOV eax, [_PB_Gadget_Globals]
    !MOV eax, [eax]
    !Mov [p.v_WindowID], eax
    ProcedureReturn WindowID
EndProcedure

Procedure myGadget(gadget,x,y,w,h,img)
    hWnd = getCurrentGadgetWindow()
    If hWnd
        result = CanvasGadget(gadget,x,y,w,h)
        If gadget=#PB_Any:gadget=result:EndIf
        SetGadgetData(gadget,img)
        drawMyGadgetPicture(gadget)
        
        callback = GetProp_(hWnd,"myGadgetCallback")
        If Not callback                               ; Window Callback installieren, falls noch nicht geschehen
            oldCallback = SetWindowLongPtr_(hWnd,#GWLP_WNDPROC,@myGadget_WindowCallback())
            SetProp_(hWnd,"myGadget_oldCallback",oldCallback)
        EndIf
        *s.myGadgetCallbacks = GetProp_(hWnd,"myGadget_ResizeCallbacks")
        If Not *s                                     ; Callbackliste installieren, fall noch nicht geschehen
            *s = AllocateMemory(SizeOf(myGadgetCallbacks))
            If *s
                InitializeStructure(*s,myGadgetCallbacks)
                SetProp_(hWnd,"myGadget_ResizeCallbacks",*s)
            EndIf
        EndIf
        If *s                                         ; neues CallbackElement dazu
            If AddElement(*s\gadgets())
                *s\gadgets()\gadget = gadget
                *s\gadgets()\callback = @myGadget_ResizeCallback()
            EndIf
        EndIf
    EndIf
    ProcedureReturn result
EndProcedure
;
; Ende DeineLib.pbi
;
;----------------------------------------------------------------------------------------------

;#XIncludeFile "DeineLib.pbi"

OpenWindow(0, #PB_Ignore, #PB_Ignore, 300, 300, "x", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
    myGadget(0,10,10,280,280,LoadImage(#PB_Any,#PB_Compiler_Home+"Examples\Sources\Data\PureBasicLogo.bmp"))


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Re: Das Ende einer Grössenveränderung feststellen

Beitrag von Bisonte »

Danke.

Es hat zwar ne Weile gedauert, das zu begreifen, aber nu sitzt's.

Wobei ich anmerken muss :
Die Funktion getCurrentGadgetWindow() hat bei mir immer einen Fehler produziert (unmodifizierte Copy&Paste Aktion)
Nachdem ich verstanden hatte, was das Ding genau macht (vom Sinn her, weil bei ASM hörte es zu 64er Zeiten auf ;) )
hab ich das dann durch

Code: Alles auswählen

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Import ""
  CompilerElse
    ImportC ""
    CompilerEndIf
    PB_Object_GetThreadMemory(MemoryID)
    PB_Gadget_Globals.i
  EndImport
Procedure GetCurrentGadgetWindow()  ; Aktuelles Fenster ermitteln
  Protected *Globals = PB_Object_GetThreadMemory(PB_Gadget_Globals)
  ProcedureReturn PeekI(*Globals)
EndProcedure
ersetzt... unter anderem habe ich dann auch den CallFunctionFastAufruf durch einen Prototype ersetzt.
Und da du im Beispiel ein Canvas nutzt, anstelle eines ImageGadgets, kamen natürlich weitere Anpassungen ;)

Nunja... Da stellt sich mir die Frage, ob ich nun auch noch, wie bei meinem vorherigen Versuch, einen Callback
haben kann, der nur auf das Gadget reagiert, oder ob das jetzt alles in einem "WindowCallback" landen muss,
von dem aus ich dann alles verteile...
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