Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
14-1129213003
ArtemESC
2005-10-13 18:16
2005.11.06
MBR


14-1129373148
Иксик
2005-10-15 14:45
2005.11.06
Вот, блин, совпадения...


1-1128978861
Ricks
2005-10-11 01:14
2005.11.06
Рисование поверхностей (желательно OpenGL)


6-1121972461
BBCHa
2005-07-21 23:01
2005.11.06
Создание письма в почтовой программе по умолчанию


14-1129180394
Ega23
2005-10-13 09:13
2005.11.06
С днем рождения! 13 октября





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский