Форум: "KOL";
Текущий архив: 2005.11.06;
Скачать: [xml.tar.bz2];
ВнизOwnerDraw в TreeView Найти похожие ветки
← →
Ajax © (2005-03-03 18:35) [0]Кто-нибудь занимался собственноручной отрисовкой TreeView? Если да, то поделитесь пожалуйста наработками. Спасибо.
← →
z007 (2005-03-05 00:28) [1]Буквально вчера занимался.
Правда, без Lines и Buttons (т.к. они мне были не нужны),
даже вынес все это в отдельный unit (и во внешнюю библиотеку).
Делает:
- фоновый рисунок (правда,без doublebuffered Сильно мигает, но я где-то читал, что это недостаток самого treeview),
- пользовательскую отрисовку item"ов
- значки для Item"ов
Если надо, - пожалуйста. Но вряд ли раньше 09.03
← →
Ajax © (2005-03-05 15:37) [2]Конечно надо. Буду чрезвычайно признателен.
Как реализуется CustomDraw? Через перехват wm_notify или полностью wm_paint?
← →
z007 (2005-03-06 00:17) [3]Раньше делал на paint
теперь вроде бы работает и с notify (по крайней мере в рамках необходимого для меня).
Честно говоря, за основу взял какой-то старый компонент для vcl -там подробно расписывается как работать с wm_notify:customdraw.
Код пока не могу (07 или 09) - на работе остался.
← →
Ajax © (2005-03-09 19:32) [4]Я весь в ожидании... :-)
← →
z007 (2005-03-10 00:00) [5]Примерно так (реализован только один вариант отрисовки),
в качестве примера используются стандартные рисунки.
Для демо-проекта достаточно подключить юнит, заполнить
TreeView и присоединить к нему процедуру:TV.AttachProc(TVCustomDrawFunc);
Если будут усовершенствования, прошу сообщить, ладно?unit TVCustomDraw;
interface
uses Windows, Messages, Kol;
function TVCustomDrawFunc( Sender: PControl; var Msg: TMsg;
var Rslt: Integer ): Boolean;
var
bgBitmap : pBitmap = nil;
TVImageList : PImageList = nil;
shell32:Cardinal;
implementation
function CheckItemState(item:Cardinal):TDrawState;
begin
//todo?
end;
procedure OnBeforePaint(Sender:pControl; DC:HDC);
begin
{loading demo bmp and lv}
if TVImageList = nil then
begin
TVImageList := NewImageList( nil );
TVImageList.LoadSystemIcons( true );
Sender.Perform(TVM_SETIMAGELIST,TVSIL_NORMAL,TVImageList.Handle);
end;
if bgBitmap=nil then
begin
shell32:=LoadLibrary("shell32.dll");
bgBitmap:=NewBitmap(1,1);
bgBitmap.LoadFromResourceID(shell32,130);
Sender.Font.FontName:="Arial Cyr";
Sender.Font.FontStyle:=[FSBold];
Sender.Color:=clYellow;
Sender.DoubleBuffered:=True;
end;
{end of}
SetBkMode(Sender.Canvas.Handle, TRANSPARENT);
end;
procedure OnAfterPaint(Sender:pControl; DC:HDC);
var item: cardinal;
R, rect:TRect;
ibk:integer;
begin
item:= Sender.Perform(TVM_GETNEXTITEM,TVGN_LASTVISIBLE,0);
if item > 32 then begin
R := Sender.TVItemRect[item,False];
if R.Bottom < Sender.Height then
begin
Sender.Canvas.Brush.Color := Sender.Color;
R.Top := R.Bottom;
R.Bottom := Sender.Height;
BitBlt(DC, 0, r.Top, bgBitmap.Width, r.bottom-r.top, bgBitmap.Canvas.Handle, 0, r.Top, SRCCOPY);
end;
end;
end;
{OnBeforeItemPaint
OnAfterItemPaint -
возвращаемое значенрие можно использовать в основной функции
для выполнения DefaultDraw
}
function OnBeforeItemPaint(Sender:pControl; DC:HDC; Item:cardinal; const Rect:tRect; Level:integer; ItemState:TDrawState):boolean;
var I, L : Integer;
ibk:integer;
r:Trect;
begin
Result:=True;
I := Rect.Bottom - Rect.Top;
L := Rect.Left + Level * Sender.TVIndent;
BitBlt(DC, 0, Rect.Top, bgBitmap.Width, I, bgBitmap.Canvas.Handle, 0, Rect.Top, SRCCOPY);
r:=Sender.TVItemRect[item,True];
if Sender.TVItemSelected[Item] then
begin
Sender.Canvas.Brush.Color := clBtnShadow;
FillRect(Sender.Canvas.Handle,Rect,Sender.Canvas.Brush.Handle);
Sender.Canvas.DrawFocusRect(Rect);
ExtTextOut(Sender.Canvas.Handle,L + 32, Rect.Top, ETO_OPAQUE, @Rect, pchar(Sender.TVItemText[Item]),Length(Sender.TVItemText[Item]),nil);
end
else begin
Sender.Canvas.Brush.BrushStyle := bsClear;
ibk:=SetBkMode(Sender.Canvas.Handle, TRANSPARENT);
Sender.Canvas.TextOut(L+32, Rect.Top, Sender.TVItemText[Item]);
end;
Sender.Canvas.Font.Color := Sender.Font.Color;
//Sender.Canvas.Font.FontStyle := [];
SetBkMode(Sender.Canvas.Handle, ibk);
DrawIconEx(Sender.Canvas.Handle,l,r.Top,TVImageList.ExtractIcon(Sender.TVItemImage[item]),
TVImageList.ImgWidth,TVImageList.ImgHeight,0,0, DI_NORMAL);
end;
function OnAfterItemPaint(Sender:pControl; DC:HDC; Item:cardinal; const Rect:tRect; Level:integer; ItemState:TDrawState):boolean;
var I, L : Integer;
begin
Result:=True;
{todo?}
end;
type
tagNMTVCUSTOMDRAW = packed record
nmcd: TNMCustomDraw;
clrText: COLORREF;
clrTextBk: COLORREF;
iLevel: Integer;
end;
PNMTVCustomDraw = ^TNMTVCustomDraw;
TNMTVCustomDraw = tagNMTVCUSTOMDRAW;
const
CDRF_NOTIFYITEMERASE = $00000080;
function TVCustomDrawFunc( Sender: PControl; var Msg: TMsg;
var Rslt: Integer ): Boolean;
var NMCustDraw: PNMTVCustomDraw;
NMHdr: PNMHdr;
Item:Cardinal;
ItemIdx, SubItemIdx: Integer;
S: TListViewItemState;
ItemState: TDrawState;
OwnerDraw: boolean;
begin
Result := FALSE;
if Msg.message = WM_NOTIFY then
begin
NMHdr := Pointer( Msg.lParam );
if (NMHdr.code = TVN_ITEMEXPANDED) then
Sender.Invalidate; //???
if (NMHdr.code = NM_CUSTOMDRAW) then
begin
NMCustDraw := Pointer( Msg.lParam );
case NMCustDraw.nmcd.dwDrawStage of
CDDS_PREPAINT:
begin
OnBeforePaint(Sender,NMCustDraw.nmcd.hdc);
Rslt := CDRF_NOTIFYITEMDRAW or
CDRF_NOTIFYITEMERASE or
CDRF_NOTIFYPOSTERASE or
CDRF_NOTIFYPOSTPAINT;
Result:=True;
end;
CDDS_ITEMPREPAINT:
begin
rslt:=CDRF_NOTIFYPOSTPAINT;
Item:= NMCustDraw.nmcd.dwItemSpec;
if Item <32 then
begin
Rslt := CDRF_DODEFAULT;
Exit;
end;
itemState:= CheckItemState(Item);
OnBeforeItemPaint(Sender, NMCustDraw.nmcd.hdc, Item, NMCustDraw.nmcd.rc, NMCustDraw.iLevel, itemState);
Rslt := {CDRF_NEWFONT or - todo?} CDRF_SKIPDEFAULT;
Result:=True;
end;
CDDS_ITEMPREERASE:
begin
Rslt := CDRF_DODEFAULT; // not yet supported
Result:=True;
end;
CDDS_ITEMPOSTERASE:
begin
Rslt := CDRF_DODEFAULT; // not yet supported
Result:=True;
end;
CDDS_ITEMPOSTPAINT: // smth. wrong?
begin
Item := NMCustDraw.nmcd.lItemlParam;
OnAfterItemPaint(Sender, NMCustDraw.nmcd.hdc, Item, NMCustDraw.nmcd.rc, NMCustDraw.iLevel, ItemState);
rslt:= CDRF_DODEFAULT;
Result:=False;
end;
CDDS_POSTPAINT:
begin
OnAfterPaint(Sender, NMCustDraw.nmcd.hdc);
Rslt := CDRF_DODEFAULT;
Result:=False;
end;
CDDS_PREERASE:
begin
Rslt := CDRF_DODEFAULT; // not yet supported
Result:=True;
end;
CDDS_POSTERASE:
begin
Rslt := CDRF_DODEFAULT; // not yet supported
Result:=True;
end;
else
begin
Rslt := CDRF_DODEFAULT; // not yet supported
Result:=True;
end;
Result:=True;
end;
end;
end;
end;
{demo il & bmp}
initialization
finalization
if TVImageList <> nil then
TVImageList.Free;
if bgBitmap <> nil then
bgBitmap.Free;
end.
← →
Ajax © (2005-03-10 13:13) [6]Спасибо большое! Пойду разбираться.
Усовершенствования будут вряд-ли, скорее я все это сильно упрощу - для моих нужд этого достаточно с избытком. Но если найду какие-нибудь ошибки или добавлю что-то, сообщу обязательно.
Страницы: 1 вся ветка
Форум: "KOL";
Текущий архив: 2005.11.06;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.034 c