Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows Delphi:ListView(vsReport)具有自定义字体颜色的单列标题?_Windows_Delphi_Listview_Delphi Xe2_Columnheader - Fatal编程技术网

Windows Delphi:ListView(vsReport)具有自定义字体颜色的单列标题?

Windows Delphi:ListView(vsReport)具有自定义字体颜色的单列标题?,windows,delphi,listview,delphi-xe2,columnheader,Windows,Delphi,Listview,Delphi Xe2,Columnheader,在具有vsReport ViewStyle的ListView中,如何自定义任何单个列标题的字体颜色?例如(第二列标题为红色字体): 您可以从listview获取本机标题控件,然后将列的特定项标记为所有者绘制。当标题项请求绘制时,只需更改文本颜色(如果不删除字符串标志)。绘图消息将被发送到标题的父级-listview,因此您需要在那里处理消息。有关所有者绘制的标题控件,请参见 示例代码: type TForm1 = class(TForm) ListView1: TListView;

在具有vsReport ViewStyle的ListView中,如何自定义任何单个列标题的字体颜色?例如(第二列标题为红色字体):

您可以从listview获取本机标题控件,然后将列的特定项标记为所有者绘制。当标题项请求绘制时,只需更改文本颜色(如果不删除字符串标志)。绘图消息将被发送到标题的父级-listview,因此您需要在那里处理消息。有关所有者绘制的标题控件,请参见

示例代码:

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
     ...
  private
    FLVHeader: HWND;
    FSaveLVWndProc: TWndMethod;
    procedure LVWndProc(var Msg: TMessage);
    procedure SetHeaderItemStyle(Index: Integer);
  end;

..
uses commctrl;
..

procedure TForm1.FormCreate(Sender: TObject);
begin
  FLVHeader := ListView_GetHeader(ListView1.Handle);
  SetHeaderItemStyle(1);

  FSaveLVWndProc := ListView1.WindowProc;
  ListView1.WindowProc := LVWndProc;
end;

procedure TForm1.SetHeaderItemStyle(Index: Integer);
var
  HeaderItem: THDItem;
begin
  HeaderItem.Mask := HDI_FORMAT or HDI_TEXT or HDI_LPARAM;
  Header_GetItem(FLVHeader, 1, HeaderItem);
  HeaderItem.Mask := HDI_FORMAT;
  HeaderItem.fmt := HeaderItem.fmt or HDF_OWNERDRAW;
  Header_SetItem(FLVHeader, 1, HeaderItem);
end;

procedure TForm1.LVWndProc(var Msg: TMessage);
begin
  FSaveLVWndProc(Msg);    // thanks to @Kobik (cause SO if called later then WM_NOTIFY case on some (all other then mine?) machines)

  case Msg.Msg of
    WM_DRAWITEM:
      if (TWmDrawItem(Msg).DrawItemStruct.CtlType = ODT_HEADER) and
          (TWmDrawItem(Msg).DrawItemStruct.hwndItem = FLVHeader) and
          (TWmDrawItem(Msg).DrawItemStruct.itemID = 1) then
        SetTextColor(TWmDrawItem(Msg).DrawItemStruct.hDC, ColorToRGB(clRed));
    WM_NOTIFY:
      if (TWMNotify(Msg).NMHdr.hwndFrom = FLVHeader) and
          (TWMNotify(Msg).NMHdr.code = HDN_ITEMCHANGED) then
          // also try 'HDN_ENDTRACK' if it doesn't work as expected
        SetHeaderItemStyle(1);
    WM_DESTROY: ListView1.WindowProc := FSaveLVWndProc;
  end;
end;
我将在
CDDS\u itemprespaint
呈现阶段处理标题通知代码,并使用
CDRF\u NEWFONT
返回代码响应此通知消息。以下代码显示了如何扩展列表视图控件,使其具有用于指定标题项字体颜色的事件:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, CommCtrl, StdCtrls;

type
  TGetHeaderItemFontColorEvent = procedure(Sender: TCustomListView;
    ItemIndex: Integer; var FontColor: TColor) of object;
  TListView = class(ComCtrls.TListView)
  private
    FHeaderHandle: HWND;
    FOnGetHeaderItemFontColor: TGetHeaderItemFontColorEvent;
    procedure WMNotify(var AMessage: TWMNotify); message WM_NOTIFY;
  protected
    procedure CreateWnd; override;
  published
    property OnGetHeaderItemFontColor: TGetHeaderItemFontColorEvent read
      FOnGetHeaderItemFontColor write FOnGetHeaderItemFontColor;
  end;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
  private
    procedure GetHeaderItemFontColor(Sender: TCustomListView;
      ItemIndex: Integer; var FontColor: TColor);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TListView }

procedure TListView.CreateWnd;
begin
  inherited;
  FHeaderHandle := ListView_GetHeader(Handle);
end;

procedure TListView.WMNotify(var AMessage: TWMNotify);
var
  FontColor: TColor;
  NMCustomDraw: TNMCustomDraw;
begin
  if (AMessage.NMHdr.hwndFrom = FHeaderHandle) and
    (AMessage.NMHdr.code = NM_CUSTOMDRAW) then
  begin
    NMCustomDraw := PNMCustomDraw(TMessage(AMessage).LParam)^;
    case NMCustomDraw.dwDrawStage of
      CDDS_PREPAINT:
        AMessage.Result := CDRF_NOTIFYITEMDRAW;
      CDDS_ITEMPREPAINT:
      begin
        FontColor := Font.Color;
        if Assigned(FOnGetHeaderItemFontColor) then
          FOnGetHeaderItemFontColor(Self, NMCustomDraw.dwItemSpec, FontColor);
        SetTextColor(NMCustomDraw.hdc, ColorToRGB(FontColor));
        AMessage.Result := CDRF_NEWFONT;
      end;
    else
      AMessage.Result := CDRF_DODEFAULT;
    end;
  end
  else
    inherited;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListView1.OnGetHeaderItemFontColor := GetHeaderItemFontColor;
end;

procedure TForm1.GetHeaderItemFontColor(Sender: TCustomListView;
  ItemIndex: Integer; var FontColor: TColor);
begin
  case ItemIndex of
    0: FontColor := clRed;
    1: FontColor := clGreen;
    2: FontColor := clBlue;
  end;
end;

end.
整个项目你都可以。下面是上述示例的结果:


@SertacAkyuz:当我尝试调整任何列的大小时,我都会得到AV。@Andreas,谢谢你关于
NMCustomDraw.dwItemSpec
的观点@特拉玛——这让我很难受,事实证明,事实上,这是公平的。回答得好(+1)顺便说一句…@SertacAkyuz,这也是我的第一个想法(因为堆栈溢出)。这没有帮助。@kobik-这是操作系统的一个特性,也被VCL源验证过:在
TCustomHeaderControl.CNNotify
中有一个案例分支:
HDN\u ITEMCHANGEDA,HDN\u ITEMCHANGEDW:
。VCL也不能冒险使用
HDN\u ITEMCHANGED
@TLama,可能是。我刚刚执行了您的EXE并报告了我所看到的:)@kobik,如果您将该列表视图剪切并粘贴到另一个项目,您也会看到同样的结果;-)您可以通过不喜欢的
双缓冲
属性来解决此问题,也可以使用虚拟模式解决此问题。我打赌QC中有很多关于它的报告。我明天会在工作中尝试(那里有一个XP系统)。我认为它在那里会工作得很好。测试:在Windows 2000和Vista上工作,但在Windows XP上不工作。即使切换到Xp标准主题。找到解决方案:
Condition1:=True;无效竖立(ListView1.FHeaderHandle,无,真)