listview的头部重画是一个历史遗留未解决的问题了,今天上午试验了下,能够重画了,但是效果不理想,在拉动分割条的时候,闪烁的厉害.我的解决方法只要通过子类消息截获然后重画.
问题主要出在:WM_PAINT 和 WM_NCPAINT:的处理上.请那位大虾帮忙解决.另外,还有就是在listview的行的重画上,如果谁有画当前选中行的方法,望告诉俺,如果解决必定高分送上.listview的stye 是report
下面是我的代码
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls;type
TForm1 = class(TForm)
ImageList1: TImageList;
skinimg: TImageList;
ListView1: TListView;
procedure FormShow(Sender: TObject);
private
OldLVWndProc: TWndMethod;
aMouseDown: Bool; procedure SetupColumnToOwnerDraw();
{ Private declarations }
public
procedure NewLVWndProc(var Message: TMessage);
{ Public declarations }
end;var
Form1: TForm1;
var
OldWndProc: Pointer;
imgindex: integer;
FormHandle: HWND;
ISPaint: bool;
implementation
uses
CommCtrl;
{$R *.dfm}procedure TForm1.SetupColumnToOwnerDraw();
var
HeaderHandle: HWND;
hdi: _HD_ITEM;
i: integer;
begin
HeaderHandle := GetDlgItem(ListView1.Handle, 0);
for i := 0 to ListView1.Columns.Count - 1 do
begin
hdi.mask := HDI_TEXT + HDI_FORMAT + HDI_WIDTH;
// hdi.fmt := HDF_LEFT + HDF_OWNERDRAW + HDF_STRING;
hdi.cxy := ListView1.Columns.Items[i].Width;
hdi.cchTextMax := Length(ListView1.Columns.Items[i].Caption);
hdi.pszText := PChar(ListView1.Columns.Items[i].Caption);
hdi.hbm := ImageList1.GetImageBitmap; //();
hdi.iImage := ListView1.Columns.Items[i].ImageIndex;
hdi.fmt := DT_END_ELLIPSIS;
Header_SetItem(HeaderHandle, i, hdi);
end;end;procedure TForm1.NewLVWndProc(var Message: TMessage);
var
dis: ^DRAWITEMSTRUCT;
Rect: TRect;
FCanvas: TCanvas;
LVOffset: integer;
ColCaption: string;
pubbitmap: Tbitmap;
begin
LVOffset := 0;
/////////////////////////////////////
case message.Msg of WM_DRAWITEM:
begin
dis := Pointer(Message.lParam);
FCanvas := TCanvas.Create;
FCanvas.Handle := dis.hDC;
Rect := TRect(dis.rcItem);
if (ListView1.SmallImages <> nil) and (ListView1.Columns.Items[dis.itemID].ImageIndex <> -1) then
begin
LVOffset := 16 + 12;
ListView1.SmallImages.Draw(FCanvas, Rect.Left + 6, Rect.Top + 1,
ListView1.Columns.Items[dis.itemID].ImageIndex, true);
end;
FCanvas.Font.Assign(ListView1.Font);
FCanvas.Brush.Style := bsClear;
// fcanvas.FillRect(Rect);
ColCaption := ListView1.Columns.Items[dis.itemID].DisplayName;
Rect.Left := Rect.Left + 1 + LVOffset;
Rect.Top := Rect.Top;
pubbitmap := Tbitmap.Create;
skinimg.GetBitmap(imgindex, pubbitmap);
FCanvas.StretchDraw(Rect, pubbitmap);
DrawTextEx(
FCanvas.Handle,
PChar(ColCaption),
Length(ColCaption),
Rect,
DT_CENTER or DT_BOTTOM,
nil);
FCanvas.Free;
pubbitmap.Free;
Message.Result := 1;
end;
WM_NCPAINT:
begin
if (ListView1.ViewStyle = vsReport) then
begin
//ÏȽøÐÐÕý³£»
OldLVWndProc(Message);
//ÿһ´Î»ÍêÖ®ºó¶¼±ØÐëÖØÐÂÉèÖÃÊôÐÔ
SetupColumnToOwnerDraw();
//ÔÙ»
OldLVWndProc(Message);
end;
end;
WM_PAINT:
begin
// if ISPaint then
SetupColumnToOwnerDraw(); OldLVWndProc(Message);
end;
end;
OldLVWndProc(Message);
end;function LVHeaderWndProc(hWnd: HWND; Msg, wParam, lParam: Longint): Longint; stdcall;
begin
case Msg of
WM_CAPTURECHANGED:
begin
imgindex := 0;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_NCHITTEST: //Êó±êÒƶ¯³ö±ß½ç
begin
imgindex := 0;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_NCDESTROY:
begin
Result := CallWindowProc(OldWndProc, HWND, Msg, wParam, lParam); // FHeaderHandle := 0;
end; WM_LBUTTONDOWN:
begin
imgindex := 1;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_MOUSEMOVE:
begin
ISPaint := false;
end;
HDM_GETITEMRECT: //´óС¸Ä±äµÄʱºò·¢Éú´ËÏûÏ¢
begin
// ISPaint := false;
// postmessage(hwnd, WM_PAINT, 0, 0, );
end; HDM_ORDERTOINDEX:
begin
// ISPaint := false;
// postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_SETCURSOR: //Êó±ê½øÈë,»á¶à´ÎÒý·¢´ËÏûÏ¢
begin
// imgindex := 2;
// postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_ERASEBKGND:
begin
ISPaint := true;
end; WM_lBUTTONUP: //Êó±ê×ó¼üËÉ¿ª
begin
// ISPaint := true;
imgindex := 0;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
end;
Result := CallWindowProc(OldWndProc, HWND, Msg, wParam, lParam);
end;procedure TForm1.FormShow(Sender: TObject);
var HeaderHandle: HWND;
begin
OldLVWndProc := ListView1.WindowProc;
ListView1.WindowProc := NewLVWndProc; HeaderHandle := GetDlgItem(ListView1.Handle, 0);
OldWndProc := Pointer(SetWindowlong(HeaderHandle, GWL_WNDPROC, Integer(@LVHeaderWndProc)));
end;end.
问题主要出在:WM_PAINT 和 WM_NCPAINT:的处理上.请那位大虾帮忙解决.另外,还有就是在listview的行的重画上,如果谁有画当前选中行的方法,望告诉俺,如果解决必定高分送上.listview的stye 是report
下面是我的代码
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls;type
TForm1 = class(TForm)
ImageList1: TImageList;
skinimg: TImageList;
ListView1: TListView;
procedure FormShow(Sender: TObject);
private
OldLVWndProc: TWndMethod;
aMouseDown: Bool; procedure SetupColumnToOwnerDraw();
{ Private declarations }
public
procedure NewLVWndProc(var Message: TMessage);
{ Public declarations }
end;var
Form1: TForm1;
var
OldWndProc: Pointer;
imgindex: integer;
FormHandle: HWND;
ISPaint: bool;
implementation
uses
CommCtrl;
{$R *.dfm}procedure TForm1.SetupColumnToOwnerDraw();
var
HeaderHandle: HWND;
hdi: _HD_ITEM;
i: integer;
begin
HeaderHandle := GetDlgItem(ListView1.Handle, 0);
for i := 0 to ListView1.Columns.Count - 1 do
begin
hdi.mask := HDI_TEXT + HDI_FORMAT + HDI_WIDTH;
// hdi.fmt := HDF_LEFT + HDF_OWNERDRAW + HDF_STRING;
hdi.cxy := ListView1.Columns.Items[i].Width;
hdi.cchTextMax := Length(ListView1.Columns.Items[i].Caption);
hdi.pszText := PChar(ListView1.Columns.Items[i].Caption);
hdi.hbm := ImageList1.GetImageBitmap; //();
hdi.iImage := ListView1.Columns.Items[i].ImageIndex;
hdi.fmt := DT_END_ELLIPSIS;
Header_SetItem(HeaderHandle, i, hdi);
end;end;procedure TForm1.NewLVWndProc(var Message: TMessage);
var
dis: ^DRAWITEMSTRUCT;
Rect: TRect;
FCanvas: TCanvas;
LVOffset: integer;
ColCaption: string;
pubbitmap: Tbitmap;
begin
LVOffset := 0;
/////////////////////////////////////
case message.Msg of WM_DRAWITEM:
begin
dis := Pointer(Message.lParam);
FCanvas := TCanvas.Create;
FCanvas.Handle := dis.hDC;
Rect := TRect(dis.rcItem);
if (ListView1.SmallImages <> nil) and (ListView1.Columns.Items[dis.itemID].ImageIndex <> -1) then
begin
LVOffset := 16 + 12;
ListView1.SmallImages.Draw(FCanvas, Rect.Left + 6, Rect.Top + 1,
ListView1.Columns.Items[dis.itemID].ImageIndex, true);
end;
FCanvas.Font.Assign(ListView1.Font);
FCanvas.Brush.Style := bsClear;
// fcanvas.FillRect(Rect);
ColCaption := ListView1.Columns.Items[dis.itemID].DisplayName;
Rect.Left := Rect.Left + 1 + LVOffset;
Rect.Top := Rect.Top;
pubbitmap := Tbitmap.Create;
skinimg.GetBitmap(imgindex, pubbitmap);
FCanvas.StretchDraw(Rect, pubbitmap);
DrawTextEx(
FCanvas.Handle,
PChar(ColCaption),
Length(ColCaption),
Rect,
DT_CENTER or DT_BOTTOM,
nil);
FCanvas.Free;
pubbitmap.Free;
Message.Result := 1;
end;
WM_NCPAINT:
begin
if (ListView1.ViewStyle = vsReport) then
begin
//ÏȽøÐÐÕý³£»
OldLVWndProc(Message);
//ÿһ´Î»ÍêÖ®ºó¶¼±ØÐëÖØÐÂÉèÖÃÊôÐÔ
SetupColumnToOwnerDraw();
//ÔÙ»
OldLVWndProc(Message);
end;
end;
WM_PAINT:
begin
// if ISPaint then
SetupColumnToOwnerDraw(); OldLVWndProc(Message);
end;
end;
OldLVWndProc(Message);
end;function LVHeaderWndProc(hWnd: HWND; Msg, wParam, lParam: Longint): Longint; stdcall;
begin
case Msg of
WM_CAPTURECHANGED:
begin
imgindex := 0;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_NCHITTEST: //Êó±êÒƶ¯³ö±ß½ç
begin
imgindex := 0;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_NCDESTROY:
begin
Result := CallWindowProc(OldWndProc, HWND, Msg, wParam, lParam); // FHeaderHandle := 0;
end; WM_LBUTTONDOWN:
begin
imgindex := 1;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_MOUSEMOVE:
begin
ISPaint := false;
end;
HDM_GETITEMRECT: //´óС¸Ä±äµÄʱºò·¢Éú´ËÏûÏ¢
begin
// ISPaint := false;
// postmessage(hwnd, WM_PAINT, 0, 0, );
end; HDM_ORDERTOINDEX:
begin
// ISPaint := false;
// postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_SETCURSOR: //Êó±ê½øÈë,»á¶à´ÎÒý·¢´ËÏûÏ¢
begin
// imgindex := 2;
// postmessage(hwnd, WM_PAINT, 0, 0, );
end;
WM_ERASEBKGND:
begin
ISPaint := true;
end; WM_lBUTTONUP: //Êó±ê×ó¼üËÉ¿ª
begin
// ISPaint := true;
imgindex := 0;
postmessage(hwnd, WM_PAINT, 0, 0, );
end;
end;
Result := CallWindowProc(OldWndProc, HWND, Msg, wParam, lParam);
end;procedure TForm1.FormShow(Sender: TObject);
var HeaderHandle: HWND;
begin
OldLVWndProc := ListView1.WindowProc;
ListView1.WindowProc := NewLVWndProc; HeaderHandle := GetDlgItem(ListView1.Handle, 0);
OldWndProc := Pointer(SetWindowlong(HeaderHandle, GWL_WNDPROC, Integer(@LVHeaderWndProc)));
end;end.
procedure TFrmTmp.ListViewNewWndProc(var Msg: TMessage);
var
hdn: ^THDNotify;
begin
if Msg.Msg=WM_NOTIFY then
begin
hdn := Pointer(Msg.lParam);
if (hdn.hdr.code=HDN_BeginTrackW)or(hdn.hdr.code=HDN_BeginTrackA) then
begin//ListView 抬头开始拖动消息
HeadDraging := True;
end
else if (hdn.hdr.code=HDN_EndTrackW)or(hdn.hdr.code=HDN_EndTrackA) then
begin//ListView 抬头结束拖动消息
LvAdv.Repaint;
HeadDraging := false;
end
else
FListViewOldWndProc(Msg);
end
else if Msg.Msg=WM_SETFOCUS then
begin//无法得到焦点请注消下面一行代码
FListViewOldWndProc(Msg);
end
else
FListViewOldWndProc(Msg);
end;
...
case message.Msg of
WM_PAINT:
begin
// if ISPaint then
SetupColumnToOwnerDraw(); OldLVWndProc(Message);
end;
end;
OldLVWndProc(Message);
end;....
你这不是执行了2次 OldLVWndProc(Message); 重绘2次?
哈哈,谢谢大家关注.