Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.11.06;
Скачать: CL | DM;

Вниз

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 вся ветка

Текущий архив: 2005.11.06;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.14 c
14-1129373148
Иксик
2005-10-15 14:45
2005.11.06
Вот, блин, совпадения...


1-1129243045
AlexLines
2005-10-14 02:37
2005.11.06
каким образом можно узнать, что в конце находятся ...


14-1129355243
Машка
2005-10-15 09:47
2005.11.06
Как стать мастерицей Delphi?


14-1129575930
NewWonder
2005-10-17 23:05
2005.11.06
Мастера web-дизайна!


14-1129004148
БарЛог
2005-10-11 08:15
2005.11.06
Религия и эгоизм?