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

Вниз

TTreeView - скроллер   Найти похожие ветки 

 
IgorR   (2004-06-09 16:43) [0]

Два вопроса по Tree
1. Как сделать скроллер в TreeView типа Flat.

2. Если свойство BevelKind установить bkFlat то при частичном перекрытии скроллеров другим окном скроллеры плохо перерисовываются. Внутри своего приложения можно после вызова дочернего окна вызвать
TreeView1.Perform(CM_RECREATEWND, 0, 0);
но проблеммы возникают и при перекрытии чужими окнами.

Интересно это глюк или фича.


 
Sha ©   (2004-06-10 19:44) [1]

Эта баго-фича имеется также и в D6 :)

Кроме описанных тобой случаев она проявляется также при максимизации формы, перемещении формы из-за границ экрана, перекрытии формы хинтами и т.п.

Можно попробовать подменить в Controls.pas метод TWinControl.WMNCPaint.

Оригинальный юнит лучше не трогать, достаточно скопировать его в каталог проекта и выполнить билд проекта.

Сделал исправление только сегодня и по-настоящему еще не тестировал.

procedure TWinControl.WMNCPaint(var Message: TMessage);
const
 InnerStyles: array[TBevelCut] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER, 0);
 OuterStyles: array[TBevelCut] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER, 0);
 EdgeStyles: array[TBevelKind] of Integer = (0, 0, BF_SOFT, BF_FLAT);
 Ctl3DStyles: array[Boolean] of Integer = (BF_MONO, 0);
var
 DC: HDC;
 RC, RW: TRect;
 EdgeSize: Integer;
 WinStyle: Longint;
begin
 inherited;
 { Get window DC that is clipped to the non-client area }
 if (BevelKind <> bkNone) or (BorderWidth > 0) then
 begin
   DC := GetWindowDC(Handle);
   try
     Windows.GetClientRect(Handle, RC);
     GetWindowRect(Handle, RW);
     MapWindowPoints(0, Handle, RW, 2);
     OffsetRect(RC, -RW.Left, -RW.Top);
     { Draw borders in non-client area }
     InflateRect(RC, BorderWidth, BorderWidth);
     if BevelKind <> bkNone then
     begin
       EdgeSize := 0;
       if BevelInner <> bvNone then Inc(EdgeSize, BevelWidth);
       if BevelOuter <> bvNone then Inc(EdgeSize, BevelWidth);
       with RC do
       begin
         WinStyle := GetWindowLong(Handle, GWL_STYLE);
         if beLeft in BevelEdges then Dec(Left, EdgeSize);
         if beTop in BevelEdges then Dec(Top, EdgeSize);
         if beRight in BevelEdges then Inc(Right, EdgeSize);
         if beBottom in BevelEdges then Inc(Bottom, EdgeSize);
         if (WinStyle and WS_VSCROLL) <> 0 then Inc(Right, GetSystemMetrics(SM_CXVSCROLL));
         if (WinStyle and WS_HSCROLL) <> 0 then Inc(Bottom, GetSystemMetrics(SM_CYHSCROLL));
       end;
       if BevelWidth > 1 then
       begin
         RW := RC;               RW.Right := RW.Left + EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
         RW.Right := RC.Right;   RW.Left := RW.Right - EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
         RW.Left := RC.Left;     RW.Bottom := RW.Top + EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
         RW.Bottom := RC.Bottom; RW.Top := RW.Bottom - EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
       end;
       DrawEdge(DC, RC, InnerStyles[BevelInner] or OuterStyles[BevelOuter],
         Byte(BevelEdges) or EdgeStyles[BevelKind] or Ctl3DStyles[Ctl3D] or BF_ADJUST);
     end;
   finally
     ReleaseDC(Handle, DC);
   end;
 end;
end;


 
Sha ©   (2004-06-10 20:33) [2]

Надо добавить обработку BorderWidth, метод работает правильно только при BorderWidth=0.


 
Sha ©   (2004-06-10 21:14) [3]

Так вроде работает. Хотя, может, чего и забыл.

procedure TWinControl.WMNCPaint(var Message: TMessage);
const
 InnerStyles: array[TBevelCut] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER, 0);
 OuterStyles: array[TBevelCut] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER, 0);
 EdgeStyles: array[TBevelKind] of Integer = (0, 0, BF_SOFT, BF_FLAT);
 Ctl3DStyles: array[Boolean] of Integer = (BF_MONO, 0);
var
 DC: HDC;
 RC, RW: TRect;
 EdgeSize, dx, dy: Integer;
 WinStyle: Longint;
begin
 inherited;
 { Get window DC that is clipped to the non-client area }
 if (BevelKind <> bkNone) or (BorderWidth > 0) then
 begin
   DC := GetWindowDC(Handle);
   try
     Windows.GetClientRect(Handle, RC);
     GetWindowRect(Handle, RW);
     MapWindowPoints(0, Handle, RW, 2);
     OffsetRect(RC, -RW.Left, -RW.Top);
     { Draw borders in non-client area }
     InflateRect(RC, BorderWidth, BorderWidth);
     EdgeSize := 0; dx := 0; dy := 0;
     if BevelKind <> bkNone then
     begin
       if BevelInner <> bvNone then Inc(EdgeSize, BevelWidth);
       if BevelOuter <> bvNone then Inc(EdgeSize, BevelWidth);
       if beLeft in BevelEdges then Dec(RC.Left, EdgeSize);
       if beTop in BevelEdges then Dec(RC.Top, EdgeSize);
       if beRight in BevelEdges then Inc(RC.Right, EdgeSize);
       if beBottom in BevelEdges then Inc(RC.Bottom, EdgeSize);
     end;
     WinStyle := GetWindowLong(Handle, GWL_STYLE);
     if (WinStyle and WS_VSCROLL) <> 0 then dx:=GetSystemMetrics(SM_CXVSCROLL);
     if (WinStyle and WS_HSCROLL) <> 0 then dy:=GetSystemMetrics(SM_CYHSCROLL);
     Inc(EdgeSize,BorderWidth);
     Inc(RC.Right, dx);
     Inc(RC.Bottom, dy);
     if (BevelKind <> bkNone) and (BevelWidth > 1) or (BorderWidth > 0) then
     begin
       RW := RC;               RW.Right := RW.Left + EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
       RW.Right := RC.Right;   RW.Left := RW.Right - EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
       RW.Left := RC.Left;     RW.Bottom := RW.Top + EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
       RW.Bottom := RC.Bottom; RW.Top := RW.Bottom - EdgeSize; Windows.FillRect(DC, RW, Brush.Handle);
     end;
     if (dx <> 0) and (dy <> 0) then
     begin                                                                      
       RW.Bottom := RC.Bottom - EdgeSize; RW.Top := RW.Bottom - dy;
       RW.Right := RC.Right - EdgeSize; RW.Left := RW.Right - dx;  
       Windows.FillRect(DC, RW, Brush.Handle);
     end;
     if BevelKind <> bkNone then
     begin
       DrawEdge(DC, RC, InnerStyles[BevelInner] or OuterStyles[BevelOuter],
         Byte(BevelEdges) or EdgeStyles[BevelKind] or Ctl3DStyles[Ctl3D] or BF_ADJUST);
     end;
   finally
     ReleaseDC(Handle, DC);
   end;
 end;
end;


 
Sha ©   (2004-06-11 12:49) [4]

Еще одна правка:
добавить объявление var SaveColor: TColor;
после       DC := GetWindowDC(Handle);
добавить SaveColor := Brush.Color; Brush.Color := clBtnFace;
после       ReleaseDC(Handle, DC);
добавить Brush.Color := SaveColor;

   В заключение замечу, что мы по примеру Borland"а рисуем скаты Bevel"а для TWinControl"а всегда толщиной в одну линию, причем Border рисуем не между скатами Bevel"а, в между Bevel"ом и клиентской областью. Почему так - загадка. В глаза это не бросается, т.к. обычно BevelWidth=1, BorderWidth=0 и почти всегда BevelWidth<=1, BorderWidth<=1.
   Конечно, это можно подправить и рисовать TWinControl аналогично TCustomPanel.



Страницы: 1 вся ветка

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

Наверх




Память: 0.49 MB
Время: 0.021 c
14-1086757862
Baks
2004-06-09 09:11
2004.06.27
Вопрос на зацепку (скорее на скорость ответа)


1-1087305759
Maxim
2004-06-15 17:22
2004.06.27
DLL


14-1086723074
Petr V. Abramov
2004-06-08 23:31
2004.06.27
Текст лицензии на FIBPlus для юр.лиц и для физ лиц.


3-1086154578
snake1977
2004-06-02 09:36
2004.06.27
Структура БД


3-1086056822
ИМХО
2004-06-01 06:27
2004.06.27
О DBF-файлах