IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

Comment modifier la couleur du header du TListView ?


Sujet :

Composants VCL Delphi

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut Comment modifier la couleur du header du TListView ?
    Bonjour,

    J'essaie de changer la couleur des en-têtes des colonnes dans un TListview. Je sais que pour y arriver je dois "override" la procédure WndProc et traiter les événements WM_PAINT ou WM_DRAWITEM (si j'ai compris un peu)

    Mais le problème est que je ne comprends pas très bien comment s'occuper des "handles2 et des messages pour être capable de changer la couleur où faire quelque chose d'autre.

    Je serais heureux si quelqu'un pouvait me donner un exemple ou me donner des liens sur un tutorial. Je remercie d'avance cette personne pour son aide.

    J'ai trouvé peu de choses sur internet sur ce cas. quelques exemples où les font étaient changés. D'autres où ils redessinaient les cellules du listview. Mais rien me donnant vraiment un exemple comment redessiner sur un WM_PAINT ou WM_DRAWITEM et comment gérer correctement ces messages.

  2. #2
    Expert confirmé
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    4 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 126
    Par défaut
    SAlut
    Je vais regarder mais appriori tu n'a pas besoin de faire ca, il suffit d'utiliser le'evenement Ondrawitem tout simplement et de modifier la couleur de ton brush lors du dessin sur le canvas.
    [Edit] Heuuu apres 2-3 recherches je suis deja bien moins optimiste ... [/Edit]
    A++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  3. #3
    Expert confirmé
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    4 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 126
    Par défaut
    Re
    Voila deja un debut ... ca met en gras le text des headers

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    procedure TForm1.Button1Click(Sender: TObject);
    const
      LVM_GETHEADER = LVM_FIRST + 31;
    var
      LF: TLogFont;
      hHeader, hCurrFont, hOldFont, hHeaderFont: THandle;
    begin
      {to get the windows handle for header}
      hHeader := SendMessage(ListView1.Handle, LVM_GETHEADER, 0, 0);
     
      {to get the handle for header font}
      hCurrFont := SendMessage(hHeader, WM_GETFONT, 0, 0);
     
      {to get the LOGFONT with font details}
      if GetObject(hCurrFont, SizeOf(LF), Addr(LF)) > 0 then
      begin
        {set our custom attributes. I set a bold and underlined font style}
        LF.lfWeight := FW_BOLD;
        LF.lfUnderline := 1;
     
        {create a new font for the header control to use.
         This font must NOT be deleted until it is no
         longer required by the control, typically when
         the application will be closed or when a new font
         will be applied to header}
        hHeaderFont := CreateFontIndirect(LF);
     
        {to select the new font}
        hOldFont := SelectObject(hHeader, hHeaderFont);
     
        {to notify the listview header about changes}
        SendMessage(hHeader, WM_SETFONT, hHeaderFont, 1);
      end;
     
    end;
    Faut mettre CommCtrl dans les uses

    [Edit2]Un pas de plus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      {to get the current style attributes for the header}
      style := GetWindowLong(hHeader, GWL_STYLE);
    avec style : dWord

    + une piste

    http://support.microsoft.com/kb/178491/fr
    [/Edit2]

    [Edit3]
    Désolé je trouve pas
    [/Edit3]

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Tout d'abord merci pour tes réponses. L'article que tu cites (le code). Je l'avais trouvé, mais changé la fonte, la couleur du texte ne m'intéresse pas. Ce que je veux, est être capable de changer la couleur de mon header.

    Je pense avoir une solution, si ça marche (pas encore testé), je la posterai ici. D'autres propositions sont toujours les bienvenues.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Hmmm ma solution ne semble pas fonctionner. cela consistait à effectuer des opérations avec le message WM_DRAWITEM dans la procédure wndProc. Mais je dois m'y prendre mal. Vais refaire des test.

  6. #6
    Expert confirmé
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    4 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 126
    Par défaut
    SAlut
    Humm j'ai regarder du cote de WindowsProc qui paraissait etre une bonne idée, mais le problrme est que si tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Procedure MaProcedure(Message : TMessage);
    [...]
    ListView1.WindowProc := MaProcedure;
    Tu bloques tous les messages et le control ne se redessine plus ... enfin presque plus ... les headers ne sont pas affectés, ils sont mis a jour autrepart ... mais je sais pas ou.

    [Edit]
    J'ai peut etre trouvé une autre piste
    http://www.swissdelphicenter.ch/torr...de.php?id=2133
    En particulier la function Header_GetItem
    [/Edit]

    [Edit2]
    Arrrgggg, non désolé j'abandonne, je trouve vraiment pas, a chaque fois sur toutes les piste c'est le meme probleme, y'a pas la possibilité(ou je ne la trouve pas) de passer un parametre pour influer sur la couleur de fond, et pas possible non plus (ou j'ai pas trouvé )d'utiliser directement le canvas...
    Bon courrage, mais j'ai vu dans une discution sur ce forum un autre compo qui apprement le gere, le TMsListView de memoire (gratuit ?).
    A++
    Qwaz
    [/Edit]

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Ok, merci. Je regarderai. Je vais cependant essayer encore un peu.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Le composant que tu m'as donné, je ne l'ai pas trouvé...
    Sinon je possède un composant hérité de TCustomListview qui dessine la couleur de fond du header (j'ai réussi dans ce cas là). TListView hérite aussi de TCustomListview.

    Dans le cas de ce composant j'attrape WM_DrawItem dans le wndProc et je redessine le rectangle, le texte, la couleur de fonds dans ma procédure.
    Ces deux lignes sont utilisés pour écrire le texte, mais ne sont pas nécessaire pour redessiner la couleur de fonds.
    header := ListView_GetHeader(Handle);
    Header_GetItem(header, str.itemID, hditem);

    J'ai regardé avec microsoft spy++ les messages envoyés dans TListview et mon composant. Ils envoient les mêmes messages au début, mais ensuite mon composant envoie le WM_DrawItem et le TListview ne l'envoie pas.

    Arrgh, je suis frustré de pas trouvé une solution à un problème qu idoit pas être si compliqué.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Ok ,si quelqu'un lit encore ce thread.

    J'ai trouvé quelque chose qui semble être ce que je veux. Mais je n'arrive pas à tout saisir comment je peux intégrer cela en delphi. Le code est en c#, voici le lien http://www.codeproject.com/KB/list/customheader.aspx

  10. #10
    Expert confirmé
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    4 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 126
    Par défaut
    SAlut
    J'espere que tu as garder une copie du code par ce que le lien est dead...
    [Edit] Effectivement aujourd'hui il marche [/Edit]
    Sinon je possède un composant hérité de TCustomListview qui dessine la couleur de fond du header (j'ai réussi dans ce cas là). TListView hérite aussi de TCustomListview.
    Si le source est accessible il faudrait regarder comment il s'y prend, si tu as un lien j'installerai le compos le sujet m'interesse.
    A++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Le composant où j'ai pu dessiner la couleur de mon header est un composant payant. Donc je pense pas que j'ai le droit de diffuser son code dans un forum.

    Pour le lien(le c# exemple), je viens de retester, et il semble fonctionner (not dead). Je peux mettre le zip sur un share. Mais je ne sais pas quelle site je devrais utiliser pour uploader le zip.

    Je vais essayer de transcire quand j'ai le temps aujourd'hui ce code c#, mais j'avoue que j'ai un peu du mal X_X;

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Bon, je laisse ceci de côté pour un moment, je réglerai ce problème une autre fois. Merci cependant qwazerty pour tes réponses.

  13. #13
    Membre Expert Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Ca semble être ce que je cherche. Cependant, j'essaie d'adapter le code en delphi .net. Et pour le moment je n'ai pas réussi à le faire fonctionner. Je donne ici mes modifs: (L'exemple est fait pour tester avec des headers de couleurs bleues.)

    L'en-tête est la même que dans le lien donné si gentillement pas edam (l'implémentation est proche, sauf que j'ai essayé de l'appliquer en .net).Ca compile mais ça fonctionne pas X_X;.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
     
    function MyListViewWndProc(p1: HWND; p2: UINT; p3: WPARAM; p4: LPARAM): LRESULT;
    var
     ParentH : HWND;
     M       : TMessage;
     Buffer  : IntPtr;
    Begin
     
     ParentH := GetParent(p1);
     if (ParentH = 0) or (ParentH = p1) then begin
      Result := 1;
      Exit;
     End;
     
     M.Msg    := p2;
     M.WParam := p3;
     M.LParam := p4;
     
      Buffer := Marshal.AllocHGlobal(Marshal.SizeOf(TypeOf(TObject(p3))));
      try
        Marshal.StructureToPtr(TObject(p3), Buffer, False);
        Result := SendMessage(ParentH, PM_HEADERMSG, longint(p3), 0);
      finally
        Marshal.DestroyStructure(Buffer, TypeOf(LParam));
        Marshal.FreeHGlobal(Buffer);
      end;
    end;
    constructor TsListView.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Header        := 0;
      HeaderWndProc := 0;
     
      ViewStyle     := vsReport;
      FixedColor    := clBtnFace;
    end;
     
    procedure TsListView.ChangeHeaderWndProc(var Msg: TMessage);
    begin
     CMRecreateWnd(Msg);
     If (Parent <> nil) Then Begin
      Header := FindWindowEx(Handle, 0, 'SysHeader32', nil);
      If Header = 0 Then Exit;
      HeaderWndProc := GetWindowLong(Header, GWL_WNDPROC);
      SetWindowLong(Header, GWL_WNDPROC, @MyListViewWndProc);
     End;
    end; 
     
    procedure TsListView.CMRecreateWnd(var Message: TMessage);
    begin 
     If Header <> 0 Then Begin 
      If HeaderWndProc <> 0 Then
       SetWindowLong(Header, GWL_WNDPROC, HeaderWndProc); 
      Header := 0; 
      HeaderWndProc := 0;
     End; 
    end; 
     
    procedure TsListView.HeaderMessage(var Msg: TMessage);
     
    begin
     
     Msg.Result := CallWindowProc(IntPtr(HeaderWndProc), Header, Msg.Msg, Msg.WParam, Msg.LParam);
     If Msg.Msg = WM_PAINT Then
      DrawButtons;
     
    end;
     
    procedure TsListView.DrawButtons;
    Var 
     DC       : HDC;
     Bounds   : TRect; 
     Border1, 
     Border2  : Integer;
     I, X     : Integer; 
     
     Canvas   : TCanvas; 
    Begin
     If Header = 0 Then Exit; 
     FFixedColor := clblue;
     Windows.GetClientRect(Header, Bounds); 
     
     Border1 := GetSystemMetrics(SM_CXBORDER);
     Border2 := GetSystemMetrics(SM_CXFIXEDFRAME) - Border1;
     
     DC := GetDC(Header); X := 0;
     
     Canvas := TCanvas.Create;
     Canvas.Handle := DC;
     
     Canvas.Brush.Color := FFixedColor;
     
     For I := 0 To Columns.Count - 1 Do Begin
      Canvas.FillRect(Rect(X + Border1, Border1,
                           X + Columns[I].Width - Border2,
                           Bounds.Bottom - Border2));
     
      Canvas.TextOut(X + Border2, Border2, Columns[I].Caption);
     
      X := X + Columns[I].Width;
     End;
     Canvas.FillRect(Rect(X + Border1, Border1, Bounds.Right, Bounds.Bottom - Border2));
     
     Canvas.Free;
    End;
     
    procedure TsListView.SetFixedColor(const Value: TColor);
    begin
     FFixedColor := clblue;
     DrawButtons;
    end;
     
    procedure TsListView.CreateHandle;
    begin
     inherited;
     
     If Parent <> nil Then
      PostMessage(Handle, PM_CHANGEPROC, 0, 0);
    end;
     
    function TsListView.get_CheckedCount: Integer;
    var
      cpt: integer;
    begin
      Result := 0;
      cpt := 0;
      while (cpt < Items.Count) do begin
        Inc(Result, Ord(Items[cpt].Checked));
        Inc(cpt);
      end;
    end;

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    En recherchant plus sur experts-exchanges, j'ai trouvé un morceau de code simple que j' ai essayé d'intégrer à nouveau en .net. http://www.experts-exchange.com/Prog...eader+listview.

    Cependant, mon intégration échoue dans l'appel du messae WM_DRAWITEM.
    Mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    procedure TsListView.WndProc(var Message: TMessage);
    var
      Code: integer;
      TNMHdr_temp :  TNMHdr;
      HD: THDNotify;
      PItem: THDItem;
      i : integer;
      hdi: THDItem;
     
    begin
     
      case Message.Msg of
        WM_DRAWITEM:
          if (true) then
          begin
            DrawHeaderItem(TDrawItemStruct(Marshal.PtrToStructure(
              IntPtr(Message.LParam), TypeOf(TDrawItemStruct))));
            Message.Result := 1;
            Exit;
          end;
        WM_NOTIFY:
        begin
           FHeaderHandle := ListView_GetHeader(Handle);
     
          // InvalidateRect(FHeaderHandle, nil, true);
           TNMHdr_temp := TNMHdr(Marshal.PtrToStructure(IntPtr(Message.LParam), TypeOf(TNMHdr)));
           if (FHeaderHandle <> 0) and (TNMHdr_temp.hWndFrom = FHeaderHandle) then
           begin
             Code := TNMHdr_temp.Code;
     
             if  (Code = HDN_ITEMCHANGING) or (Code = HDN_ITEMCHANGED) or (Code = HDN_ENDTRACK) then
             begin
               HD := THDNotify(Marshal.PtrToStructure(IntPtr(Message.LParam), TypeOf(THDNotify)));
               PItem := THDItem(Marshal.PtrToStructure(HD.PItem, TypeOf(THDItem)));
             PItem.Mask := HDI_FORMAT;
             PItem.fmt := PItem.fmt or HDF_OWNERDRAW;
             exit;
             end;
           end;
        end
      end;   
      inherited;
    end;
    Si j'ai bien compris, normallement le fait de mettre les "items" en "ownerdraw" alors le message WM_DRAWITEM devrait être appelé automatiquement. Cependant mon code doit oublier ou faire qqch de faux.

  16. #16
    Membre Expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 55
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Par défaut
    N'oubliez pas de désactiver le thème windows XP pour le composant TListview, parce que sinon c'est peine perdue étant donné que, lorsqu'un composant est "thémé" par windows, ce dernier à la main mise dessus en ce qui concerne son dessin.

    Si vous n'avez pas compris, levez le doigt.

    Pour désactiver le thème xp sur un composant, c'est dans la FAQ

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2007
    Messages : 14
    Par défaut
    Les thèmes sont désactivés depuis longtemps... Mais merci cependant.

Discussions similaires

  1. [C#][ProgressBar] Comment modifier les couleurs ?
    Par wiLL_ dans le forum Windows Forms
    Réponses: 6
    Dernier message: 11/02/2006, 14h55
  2. Comment modifier la couleur d'un mot dans un tableau ?
    Par noxious dans le forum Composants VCL
    Réponses: 2
    Dernier message: 16/11/2005, 13h05
  3. Comment modifier les couleurs de Windows ?
    Par Harry dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 29/09/2005, 09h55
  4. Comment modifier les couleurs système ?
    Par yousserr dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 24/07/2005, 10h57
  5. Comment modifier la couleur du texte sélectionné ?
    Par VincentR dans le forum Composants VCL
    Réponses: 4
    Dernier message: 14/06/2005, 22h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo