Seite 1 von 1

Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 00:45
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...

Re: Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 01:22
von c4s
#WM_EXITSIZEMOVE könnte helfen.

Re: Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 01:38
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

Re: Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 01:58
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

Re: Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 02:17
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...

Re: Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 09:08
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

Re: Das Ende einer Grössenveränderung feststellen

Verfasst: 10.12.2011 16:53
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...