Pb avec les skinages des fenêtres

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Pb avec les skinages des fenêtres

Message par lionel_om »

Je viens de rentré de vac (dans 2 semaines sans le Net) et je voudrais soliciter votre aide :
J'utilise plusieurs fenêtres skinnées et avec des gadgets skinnés également.
J'utilise donc un WindowCallBack() pour réafficher tout celà.

Or le pb est est que lorsque j'utilise la fonction Point() dans cette fct, elle prend la couleur du point de la fenêtre principale et non pas de la fenêtre concernée. Donc les couleurs affichées par mon WinCB() sont fausses.

Voilà un aperçu de cette fameuse fct :

Code : Tout sélectionner

;{--
;- Window CallBack()
Procedure WindowCallback(WindowID,Message,wParam,lParam)
  Protected id.l
 
  result = #PB_ProcessPureBasicEvents
  id = GetDlgCtrlID_(lParam)
 
  Select Message
  
    ;{-- Les gadgets simples
    Case #WM_CTLCOLORSTATIC

      Select lParam
      
        Case GadgetID(#BUTTON_LABEL)
        Case GadgetID(#BUTTON_PL_TITLE)
        Case GadgetID(#BUTTON_SK_TITLE)
          
        Default
          ProcedureReturn result

      EndSelect
    
      StartDrawing(ImageOutput())
        SelectElement(mesBt(), id)
        ;UseWindow(mesBt()\win)
        ;ActivateWindow()
        result = CreateSolidBrush_(Point(GadgetX(id), GadgetY(id)))
        SetBkColor_(wParam, Point(GadgetX(id), GadgetY(id)) )
        SetTextColor_(wParam, textColor)
      StopDrawing() 
    ; --}    
    
    
    ;{-- Les listes déroulantes
    Case #WM_CTLCOLORLISTBOX
      Select lParam
        Case GadgetID(#BUTTON_SK_LISTE)
        Case GadgetID(#BUTTON_PL_LISTE)
        
        Default
          ProcedureReturn result
    
      EndSelect
      
      SetBkMode_(wParam,#TRANSPARENT)
      SetTextColor_(wParam,textColor)
      StartDrawing(ImageOutput())
        result = CreateSolidBrush_(Point(GadgetX(id), GadgetY(id)))
      StopDrawing() 
    ; --}
    
  EndSelect


  ProcedureReturn result
 
EndProcedure
; --}
Merci d'avance. :oops:
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Voici une illustration de ce que j'avance
Image

J'ai essayé avec des UseWindow(), etc., mais ça ne change rien...

Merci d'avance.
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Peut-être que le problème vient de là

La fonction Point() d'après la doc :
Renvoie dans la variable 'Couleur' la couleur affichée à la position x,y de la surface de dessin en cours. La valeur retournée dans Couleur est un nombre codé sur 24 bits qui contient la combinaison des trois couleurs de base (Rouge, Vert, Bleu) codées chacune sur 8 bits (valeur 0 à 255).
Donc, les coordonnées X/Y doivent être des coordonnées par rapport à ton image et toi tu passes des coordonnées X/Y du Gadget qui sont des coordonnées client par rapport au bort supérieur gauche de la fenêtre, donc tu es décalé (je suppose car je ne sais pas à quoi correspond l'image utilisée par StartDrawing()

Il faut convertir les coordonnées du gadget en coordonnées par rapport à ton image si tant est que ton gadget fasse partie de l'image.
Si je comprend ton code, PB va utiliser comme image pour StartDrawing() la dernière image en cours, dont le Handle est ImageID()
Peut-être que ton code peut marcher avec StartDrawing(WindowOutput()) mais je n'en suis pas sur.

Voilà ce qui m'est venu à l'esprit, mais il y a peut-être un autre loup :roll:

Pour avoir du code stable, il faut absolument tester le résultat de la fonction StartDrawing() et retourner dans result la valeur par défaut si la fonction échoue.

A chaque création d'une Brush avec l'API CreateSolidBrush_(), tu dois la détruire mais je ne vois pas dans ton code le DeleteObject_() correspondant.
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Merci denis pour le WindowOutput(), ca a réglé une petite partie des Bugs :

Image
(Ce qui est en gris foncé devrai être en gris clair...)

Sinon pour le DeleteObject_(), je ne sais pas comment faire.
Car je récupère l'obj dans ma variable 'resultat', or si je fais un DeleteObject_(resultat), l'objet ne sera pas coloré :?
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

tu le détruis à la fin de ton programme ou a chaque changement de skin, enfin je sais pas trop comment ton code est organisé j'ai pas fouillé dedans...

Dri
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Je comprend pas trop.

Voilà le code récent du WinCB (l'autre daté de deux semaines) :

Code : Tout sélectionner

;{--
;- Window CallBack()
Procedure WindowCallback( WindowID, Message, wParam, lParam )
  Protected id.l, num.b, pt.l
 
  result = #PB_ProcessPureBasicEvents
  id = GetDlgCtrlID_(lParam)
 
  Select Message
  
    ;{--
    Case #WM_CTLCOLORSTATIC

      Select lParam
      
        Case GadgetID(#BUTTON_LABEL1)
          num = 0
        Case GadgetID(#BUTTON_LABEL2)
          num = 0
        Case GadgetID(#BUTTON_LABEL3)
          num = 0
        
        Case GadgetID(#BUTTON_PL_TITLE)
          num = 1
        Case GadgetID(#BUTTON_SK_TITLE)
          num = 1
        
        Case GadgetID(#BUTTON_CF_TITLE)
          num = 1
        Case GadgetID(#BUTTON_CF_FLD_LBL)
          num = 1
        Case GadgetID(#BUTTON_CF_EXT_LBL)
          num = 1
        Case GadgetID(#BUTTON_CF_LNG_LBL)
          num = 1
          
        Default
          ProcedureReturn result

      EndSelect
    
      If StartDrawing(WindowOutput())
        pt = Point(GadgetX(id), GadgetY(id))
        result = CreateSolidBrush_(pt)
        SetBkColor_(wParam, pt)
        SetTextColor_(wParam, *allInfoALP\font[num]\couleur)
        ; DeleteObject_(result)
        StopDrawing()
      EndIf
    ; --}    
    
    
    ;{--
    Case #WM_CTLCOLORLISTBOX
      Select lParam
        Case GadgetID(#BUTTON_SK_LISTE)
        Case GadgetID(#BUTTON_PL_LISTE)
        Case GadgetID(#BUTTON_CF_FLD_LIST)
        Case GadgetID(#BUTTON_CF_EXT_LIST)
        Case GadgetID(#BUTTON_CF_LNG_LIST)
        
        Default
          ProcedureReturn result
    
      EndSelect
      
      SetBkMode_(wParam,#TRANSPARENT)
      SetTextColor_(wParam,*allInfoALP\font[2]\couleur)
      StartDrawing(WindowOutput())
        result = CreateSolidBrush_(Point(GadgetX(id), GadgetY(id)))
      StopDrawing() 
    ; --}
    
  EndSelect

  ProcedureReturn result
 
EndProcedure
; --}
Je ne vois pas trop comment faire pr les supprimer ces SolidBrush. Faudrai que je cre un tableau et que je garde toutes les solidBrush ?
Comme ça j'utilise un SelectObject_() ?
Puis lors du changement de Skin, je supprime les anciennes et je recrée des nouvelles ?
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

un tableau ou une liste... tant que tu ne crée pas de fuite de mémoire c'est bon...

Dri
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Tu peut faire comme ceci, c'est une piste

Tu créé une liste chainée basée sur une structutre qui ressembe à ça

Code : Tout sélectionner

Structure Gadget
  IDstatic.l   ; c'est l'identifiant #Gadget
  BrushCourante   ; c'est la Brush associé au Gadget
Le principe est simple

Dans la callback, tu récupère ton ID static
Tu parcours la liste chaînée pour voir si le gadget est dans la liste chaînée

2 cas
1)
il y est, alors on teste BrushCourante
- Si BrushCourante vaut 0, c'est que le Gadget n'a pas de Brush, on créé la Brush et on stocke l'indentifiant de la Brush dans BrushCourante

- Si BrushCourante est différent de 0, on supprime la Brush comme ceci

Code : Tout sélectionner

result = CreateSolidBrush_(Point(GadgetX(id), GadgetY(id))) 
Brush = result 
Puis on créé la Brush et on stocke l'indentifiant de la Brush dans BrushCourante

2)
L'ID static n'est pas dans la liste, il n'a donc pas de Brush associé
Tu ajoutes un élément à la liste
Tu mets dans IDstatic de ton nouvel élément, L'ID static de ce Gadget
Tu créé la Brush et tu stockes l'indentifiant de la Brush dans BrushCourante

A la fin de ton programme avant de quitter, tu parcours la Liste Chaînée et tu détruits les Brush qui sont encore présentes

Pour le reste des couleurs, c'est difficile de dire ce qui cloche comme ça (enfin moi je ne vois pas), tout dépend si la fenêtre est recouverte ou non etc et peut-être autre chose...

Sinon, pour les Brush, soit tu as skiné la fenêtre et tu connais la couleur de fond et tu testes les gadgets qui sont sur cette fenêtre et tu retournes la bonne Brsuh, soit tu ne l'as pas skiné et tu retournes les couleurs systèmes. Encore une chose, Pour XP, il n'est pas possible de colorier la plupart des gadgets simplement (en particulier pour le fond) sauf à retirer le style XP pour chaque Gadget voir directement pour ton exe avec une API soit en faisant un exe sans support des Themes XP.
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

C'est vraiment utile de créer une liste chainée ? Car chaque Brush est utilisée puis peut être détruite qq ms plutard.

Donc garder juste une globale : sBrush.l
et faire comme tu m'avais noté :

Code : Tout sélectionner

If sBrush
  DeleteObject_(sBrush)
  sBrush = 0
EndIf
(en entré de CallBack())

et rajouter :

Code : Tout sélectionner

result = CreateSolidBrush_(...)
sBrush = result
Par contre, malgré que mon CallBack() gères tous les objets texturés, il arrive que certains Label ou List ait un fond noir. Comme si le CallBack() avait oublié de s'en chargé.

Voir : http://luchezl.free.fr/Temp/ALP_0.8.rar
Ce problème concerne la plupart des fenêtre, mais surtout celle de configuration.
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Si tu pouvais réduire ton code à l'essentiel concernant ton problème, tu pourrais le soumettre et on pourrait t'aider à résoudre ton problème.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Si on utilise une seule variable globale, on va effacer des Brush qui ne correspondent pas forcément.

Pour la liste chaînée, ça marche très bien car je l'utilise dans mes libs et dans les callback, c'est très rapide et nécessite peu de ligne de codes.

Pour les fonds noir, si le fond est modifié, c'est que la callback à retournée une Brush noire, le résultat de Point() retourne 0 soit car c'est vraiment la couleur qui est au croisement des coordonnées sur ton image soit Point() échoue et retourne 0 (?) mais sur ce point je ne sais pas je n'ai pas fait de tests.
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Code : Tout sélectionner

Global sBrush.l
Global couleur.l
couleur = ...

;{--
;- Window CallBack()
Procedure WindowCallback( WindowID, Message, wParam, lParam )
  Protected id.l, num.b, pt.l
 
  If sBrush
    DeleteObject_(sBrush)
    sBrush = 0
  EndIf
  
  result = #PB_ProcessPureBasicEvents
  id = GetDlgCtrlID_(lParam)
 
  Select Message
  
    ;{--
    Case #WM_CTLCOLORSTATIC

      Select lParam
      
        Case GadgetID(#BUTTON_LABEL1)
        Case GadgetID(#BUTTON_LABEL2)
        Case GadgetID(#BUTTON_LABEL3)
          
        Default
          ; si ce n'est pas un gadget skiné, on laisse tomber !!!
          ProcedureReturn result

      EndSelect
    
      If StartDrawing(WindowOutput())
        pt = Point(GadgetX(id), GadgetY(id))
        result = CreateSolidBrush_(pt)
        sBrush = result
        SetBkColor_(wParam, pt)
        SetTextColor_(wParam, couleur)
        StopDrawing()
      EndIf
    ; --}    
    
     
  EndSelect

  ProcedureReturn result
 
EndProcedure
; --}
Voila.

Par contre mes nouveaux problèmes de skinnage vienent du fais d'utiliser WindowOutput() à la place de ImageOutput. Je vais donc voir si je peux changer les choses...
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

nico a écrit :Si tu pouvais réduire ton code à l'essentiel concernant ton problème, tu pourrais le soumettre et on pourrait t'aider à résoudre ton problème.
Comme le dit Nico, sans code c'est difficile de répondre, je m'étais d'ailleurs promis de ne plus répondre tant que les codes n'étaient pas données mais comme je l'ai déjà écrit, ma bonté me perdra :mrgreen:
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Réduire le code serait quasiment impossible, j'ai 180Ko de code.
Je veux bien à la limite, vous l'envoyer par mail.
Sinon, sur mon dernier post, j'ai réduit au max ma fonction CallBack().
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Car je récupère l'obj dans ma variable 'resultat', or si je fais un DeleteObject_(resultat), l'objet ne sera pas coloré
Il faut juste garder en mméoire la dernière valeur du brush et la détruire au moment de la création de la nouvelle brush.

Comme le dit Denis, les bouts de code pour résoudre des problèmes merci bien; qu'est ce que tu crois qu'on fait quand on a ce genre de problème, et bien on essaye d'isoler les parties du code concernées en enlevant les parties du code qui ne sont pas censées intervenir.

Pour le problème de coloration de static, tu aurais pu soumettre un code complet; si ça se trouve ; ça t'aurais permis toi-même de le résoudre.
Répondre