![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
некорректный ClipRect при resize TCustomControl'а
Leff © (2007-02-05 14:32:00)Создаю компонент-потомок TCustomControl. Размещаю его на форме, делаю Align = alClient и у меня возникает проблема при изменении размеров компонента (как при уменьшении, так и при увеличении) - он перерисовывается ПОЛНОСТЬЮ, причем, сначала область занятая компонентом заполняется цветом формы, после чего отрисовывается весь компонет, что вызывает очень неприятные мерцания. Вот пример процедуры отрисовки:
procedure TMyControl.PaintWindow(DC: HDC);
var
y: integer;
begin
if ot then exit else ot := true;
with canvas.ClipRect do for y := top to bottom do begin
if odd(y div 2) then canvas.Pen.Color := $A0A0A0 else canvas.Pen.Color := $C0C0C0;
canvas.MoveTo(left,y);
canvas.LineTo(right,y);
end;
end;
при установке DoubleBuffered у компонента в True, он вообще перестает корректно прорисовываться и я вижу только цвет формы.
при вставке этого-же куска кода в OnPaint формы все происходит как надо - отрисовываются только действительно измененные участки изображения (например те области, которые появились после увеличения размеров формы)
подскажите как решить проблему
Leff (2007-02-09 09:57:00) [1]> [10] GrayFace © (09.02.07 01:35)
Блин, как я раньше не заметил, достаточно было сравнить исходники TScrollingWinControl.CreateParams и TWinControl.CreateParams :)
GrayFace (2007-02-09 01:35:00) [2]Все дело в наличии CS_VREDRAW и CS_HREDRAW в Params.WindowClass.Style.
Leff (2007-02-08 11:31:00) [3]Всем спасибо, проблема решена - в качестве предка использую TScrollingWinControl (планируется использование скроллинга), сам создаю канву и обрабатываю WM_PAINT. Теперь отрисовка производится только в измененных областях :)
Leff (2007-02-08 09:23:00) [4][6] RASkov (07.02.07 14:17)
проблема не в мерцании как таковом, а в том что перерисовывается вся область, так как там будут не полосочки а намного более сложная функция отрисовки содержимого окна, отрисовка только измененных участков повысила бы производительность
[7] capkoh © (07.02.07 22:49)
на счет WM_ERASEBKGND спасибо, действительно помогло против мерцаний :)
тем не менее содержимое окна, к сожалению, перерисовывается полностью :(
capkoh (2007-02-07 22:49:00) [5]Читайте в MSDN о сообщении WM_ERASEBKGND... Его нужно перекрыть пустой функцией (но вернуть результат = 0), если, конечно, не сделать параметр hbrBackground = 0. Небольшая выдержка:
hbrBackground
When this member is NULL, an application must paint its own background whenever it is requested to paint in its client area. To determine whether the background must be painted, an application can either process the WM_ERASEBKGND message or test the fErase member of the PAINTSTRUCT structure filled by the BeginPaint function.
RASkov (2007-02-07 14:17:00) [6]> [2] Leff © (07.02.07 09:24)
Я вот только, что так попробывал, все нормально:
type
TMyControl = class(TCustomControl)
procedure Paint; override;
end;
TForm1 = class(TForm)
Panel1: TPanel; {Align=alLeft}
Panel2: TPanel; {Align=alTop}
Button1: TButton; //на форме, не на панелях
ListBox1: TListBox; //на форме, не на панелях
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Ctr: TMyControl;
implementation
{$R *.dfm}
{ TMyControl }
procedure TMyControl.Paint;
var Y: Integer;
begin
with Canvas do for y := ClipRect.Top to ClipRect.Bottom do begin
if odd(y div 2) then Pen.Color := $A0A0A0 else Pen.Color := $C0C0C0;
MoveTo(ClipRect.Left, y);
LineTo(ClipRect.Right, y);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
with TMyControl.Create(Self) do begin
Parent:=Self;
Align:=alClient;
SendToBack;
DoubleBuffered:=True; //Вот без этой строки "моргает"
end;
end;
Моргает когда размер моего контрола(его канва) меняется, так, что здесь все нормально и двойная буферизация помогает.
Иначе сам агоритм, рисования полосок, нужно переделывать... имхо. Хотя в голову не приходит ничего, как это сделать.
Можно на временном битмапе рисовать и подсовывать, но это тоже самое, что и DoubleBuffered:=True;
Leff (2007-02-07 11:21:00) [7]Пытаюсь сделать потомок TWinControl, перекрываю WM_PAINT. В BeginPaint опять получаю обласьть отрисовки во весь control... Чувствую засада здесь в SetBounds TWinControl'а, должен же быть способ обойти это, StringGrid не мерцает вроде.... :-\
Leff (2007-02-07 10:26:00) [8]Речь идет конечно о Run-Time, размеры компонента при Align = alClient можно минять изменяя размер клиентской области, в данном случае формы
KSergey (2007-02-07 09:51:00) [9]Leff © (05.02.07 14:32)
> Создаю компонент-потомок TCustomControl. Размещаю его на
> форме, делаю Align = alClient и у меня возникает проблема
> при изменении размеров компонента
1) А разве при Align = alClient размеры компонента можно менять?!
2) Речь про DesignTime или RunTime?
Leff (2007-02-07 09:24:00) [10]изначально я Paint и перекрывал - результат тот-же :)
RASkov (2007-02-05 17:14:00) [11]Может перекрыть метод Paint лучше...
procedure TMyControl.Paint;
var Y: Integer;
begin
with Canvas do for y := ClipRect.Top to ClipRect.Bottom do begin
if odd(y div 2) then canvas.Pen.Color := $A0A0A0 else canvas.Pen.Color := $C0C0C0;
Canvas.MoveTo(ClipRect.Left, y);
Canvas.LineTo(ClipRect.Right, y);
end;
end;