![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ни как не могу убрать мерцание картинки! [D7, Win95/98, WinXP]
Нулевой © (2006-12-24 19:56:00)Если не глядеть на мерцание (что не реально) вроде "все" работает! Создается Bitmap, на нем Image. Я конечно вижу много вызовов Paint, но куда бех них. Может есть способ обновить сам фон, под картинкой.
Помогите, скажите как побороть! Код (часть):
procedure TPngLVButton.Paint;
var
BtnBmp: TBitmap;
CaptionRect: TRect;
PngImgLeft, PngImgTop, TextTop, TextLeft, TextWidth, TextHeight: integer;
FaceColor, GradColor, LightColor, DarkColor, BorderColor, TextColor: TColor;
//--- +
PaintRect: TRect;
//--- end
begin
BtnBmp := TBitmap.Create;
BtnBmp.Width := Width;
BtnBmp.Height := Height;
case FBtnState of
bsNormal:
begin
FaceColor := FColorFace;
GradColor := FColorGrad;
LightColor := FColorLight;
DarkColor := FColorDark;
BorderColor := FColorBorder;
TextColor := FColorText;
end;
bsOver:
begin
FaceColor := FOverColorFace;
GradColor := FOverColorGrad;
LightColor := FOverColorLight;
DarkColor := FOverColorDark;
BorderColor := FOverColorBorder;
TextColor := FOverColorText;
end;
bsDown:
begin
FaceColor := FDownColorFace;
GradColor := FDownColorGrad;
LightColor := FDownColorLight;
DarkColor := FDownColorDark;
BorderColor := FDownColorBorder;
TextColor := FDownColorText;
end;
//--- +
else
begin
FaceColor := FColorFace;
GradColor := FColorGrad;
LightColor := FColorLight;
DarkColor := FColorDark;
BorderColor := FColorBorder;
TextColor := FColorText;
end;
//--- end
end;
if not Enabled then
begin
FaceColor := FDisabledColorFace;
GradColor := FDisabledColorGrad;
LightColor := FDisabledColorLight;
DarkColor := FDisabledColorDark;
BorderColor := FDisabledColorBorder;
TextColor := FDisabledColorText;
end;
with BtnBmp.Canvas do
begin
Brush.Color := FaceColor;
Brush.Style := bsSolid;
Rectangle(0, 0, Width, Height);
end;
if FGradient then
begin
GradientFillRect(BtnBmp.Canvas, Rect(0, 0, Width, Height), FaceColor, GradColor);
end;
BtnBmp.Canvas.Font := Font;
BtnBmp.Canvas.Font.Color := TextColor;
TextWidth := BtnBmp.Canvas.TextWidth(Caption);
TextHeight := BtnBmp.Canvas.TextHeight(Caption);
TextTop := (Height - TextHeight) div 2;
TextLeft := (Width - TextWidth) div 2;
//--- +
if not PngImage.Empty then
begin
//Calculate the position of the PNG glyph
begin
PngImgLeft := 0;
case FLayout of
blGlyphLeft:
begin
PngImgTop := (Height - FPngImage.Height) div 2;
PngImgLeft := TextLeft - FPngImage.Width div 2;
inc(TextLeft, FPngImage.Width div 2);
if not (Caption = '') then
begin
PngImgLeft := PngImgLeft - FSpacing div 2 - FSpacing mod 2;
inc(TextLeft, FSpacing div 2);
end;
end;
blGlyphRight:
begin
PngImgTop := (Height - FPngImage.Height) div 2;
PngImgLeft := TextLeft + TextWidth - FPngImage.Width div 2;
inc(TextLeft, -FPNGImage.Width div 2);
if not (Caption = '') then
begin
PngImgLeft := PngImgLeft + FSpacing div 2 + FSpacing mod 2;
inc(TextLeft, -FSpacing div 2);
end;
end;
blGlyphTop:
begin
PngImgLeft := (Width - FPngImage.Width) div 2;
PngImgTop := TextTop - FPngImage.Height div 2 - FPngImage.Height mod 2;
inc(TextTop, FPngImage.Height div 2);
if not (Caption = '') then
begin
PngImgTop := PngImgTop - FSpacing div 2 - FSpacing mod 2;
inc(TextTop, +FSpacing div 2);
end;
end;
blGlyphBottom:
begin
PngImgLeft := (Width - FPngImage.Width) div 2;
PngImgTop := TextTop + TextHeight - FPngImage.Height div 2;
inc(TextTop, -FPngImage.Height div 2);
if not (Caption = '') then
begin
PngImgTop := PngImgTop + FSpacing div 2 + FSpacing mod 2;
inc(TextTop, -FSpacing div 2);
end;
end;
else
PngImgTop := (Height - FPngImage.Height) div 2; //--- +
end;
if FBtnState = bsDown then
begin
inc(PngImgTop);
inc(PngImgLeft);
end;
end;
PaintRect := Rect(PngImgLeft, PngImgTop, PngImgLeft + FPngImage.Width, PngImgTop +
FPngImage.Height);
end;
//--- end
if FBtnState = bsDown then
begin
inc(TextTop);
inc(TextLeft);
end;
with CaptionRect do
begin
Top := TextTop;
Left := TextLeft;
Right := Left + TextWidth;
Bottom := Top + TextHeight;
end;
if Caption <> '' then
begin
BtnBmp.Canvas.Brush.Style := bsClear;
DrawText(BtnBmp.Canvas.Handle,
PChar(Caption),
length(Caption),
CaptionRect,
DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOCLIP);
end;
with BtnBmp.Canvas do
begin
Pen.Style := psSolid;
Brush.Color := FaceColor;
Pen.Color := BorderColor;
Brush.Style := bsClear;
Rectangle(0, 0, Width, Height);
if Ctl3D then
begin
Pen.Color := LightColor;
MoveTo(1, Height - 2);
LineTo(1, 1);
LineTo(Width - 1, 1);
Pen.Color := DarkColor;
MoveTo(Width - 2, 1);
LineTo(Width - 2, Height - 2);
LineTo(1, Height - 2);
end;
end;
if FFocused then
begin
//--- + местами
BtnBmp.Canvas.Pen.Width := 2;
BtnBmp.Canvas.Pen.Color := FColorBorder;
BtnBmp.Canvas.Brush.Style := bsClear;
BtnBmp.Canvas.Rectangle(1, 1, Width, Height);
BtnBmp.Canvas.Pen.Width := 1;
BtnBmp.Canvas.Pen.Color := clWhite;
BtnBmp.Canvas.Brush.Style := bsClear;
BtnBmp.Canvas.Rectangle(2, 2, Width - 2, Height - 2);
BtnBmp.Canvas.Pen.Width := 1;
BtnBmp.Canvas.Pen.Color := FColorFocusRect;
BtnBmp.Canvas.Brush.Style := bsClear;
BtnBmp.Canvas.Rectangle(3, 3, Width - 3, Height - 3);
//--- end
end;
Canvas.Draw(0, 0, BtnBmp);
BtnBmp.Free;
//--- +
if not PngImage.Empty then
begin
if Enabled then
DrawPNG(FPngImage, Canvas, PaintRect, [])
else
DrawPNG(FPngImage, Canvas, PaintRect, FPngOptions);
end;
//--- end
end;
Нулевой (2006-12-27 16:09:00) [1]Если правильно понял показать DrawPNG(FPngImage, Canvas, PaintRect, []), то:
procedure DrawPNG(Png: TPNGObject; Canvas: TCanvas; const Rect: TRect; const Options:
TPngOptions);
var
PngCopy: TPNGObject;
begin
if Options <> [] then
begin
PngCopy := TPNGObject.Create;
try
PngCopy.Assign(Png);
if pngBlendOnDisabled in Options then
MakeImageBlended(PngCopy);
if pngGrayscaleOnDisabled in Options then
MakeImageGrayscale(PngCopy);
PngCopy.Draw(Canvas, Rect);
finally
PngCopy.Free;
end;
end
else
Png.Draw(Canvas, Rect);
end;
Наиль (2006-12-26 17:12:00) [2]
> или ничего не даст!
даст некоторое ускорение, но не избавит от мерцания.
> И почему Наиль © (26.12.06 08:53) [12] не рисует на Canvase
> BtnBmp?
Покажи как ты это делаешь. И проверь PaintRect.
Нулевой (2006-12-26 13:11:00) [3]Как сделать в BtnBmp типа TBitmap дырку размером PaintRect?
Нулевой (2006-12-26 13:06:00) [4]Сделал очень большую кнопку.
Точно 3. идет переключение канвы(канвов) с одной на другую.
PngImage зарисовывает BtnBmp.Canvas, потом BtnBmp.Canvas - PngImage.
Нулевой (2006-12-26 12:33:00) [5]1. Созданию на Canvase CustomControl картинку TBitmap, со всеми своими свойствами BtnBmp.Canvas... и др. (внешний вид)
2. Созданию на Canvase CustomControl картинку TPngImage.
3. В Paint: 1-2-1-2-1 видимо здесь и заметно моргание Image. Одно закрывает другое.
И почему Наиль © (26.12.06 08:53) [12]не рисует на Canvase BtnBmp?
Нулевой (2006-12-26 11:49:00) [6]А есть смысл создание BtnBmp вынести в Create
procedure TPngLVButton.Paint;
var
BtnBmp: TBitmap;
CaptionRect: TRect;
PngImgLeft, PngImgTop, TextTop, TextLeft, TextWidth, TextHeight: integer;
FaceColor, GradColor, LightColor, DarkColor, BorderColor, TextColor: TColor;
//--- +
PaintRect: TRect;
//--- end+
begin
BtnBmp := TBitmap.Create;
BtnBmp.Width := Width;
BtnBmp.Height := Height;
или ничего не даст!
Нулевой (2006-12-26 11:47:00) [7]Забываю написать - мерцает толька картинка (для моих глаз так). Мерцания за картинкой не наблюдаю, или это происходит очень быстро.
Нулевой (2006-12-26 11:39:00) [8]DimaBr (26.12.06 08:52) [11]
Не совсем понял? где поставить брейкпоинт.
Нулевой (2006-12-26 11:15:00) [9]Наиль © (26.12.06 08:53) [12]
ЕслиDrawPNG(FPngImage, BtnBmp.Canvas, PaintRect, [])
картинки нет вообще, ни в среде... ни при click!
Наиль (2006-12-26 08:53:00) [10]
> Нулевой © (25.12.06 17:23) [10]
У тебя всё ещё
DrawPNG(FPngImage, Canvas, PaintRect, [])
или уже
DrawPNG(FPngImage, BtnBmp.Canvas, PaintRect, [])?
DimaBr (2006-12-26 08:52:00) [11]
> Нулевой © (25.12.06 17:08) [9]
А использование сообщения описали ?
Проще всего проверить поставив брейкпоинт на первую строчку метода Paint и "нажать на кнопку". В этот момент ваша "нарисованная кнопочка" должна ещё быть нарисованной. Если этого не происходит (вы рисуете на чистом полотне) - кто-то его уже очищает.
Нулевой (2006-12-25 17:23:00) [12]Попробовал на Image - 24x24 - можно сказать не вижу верцания.
На Image 128x128 - осталось почти также.
NB. В принцепе оно и было то не сильное.
Нулевой (2006-12-25 17:08:00) [13]DimaBr (25.12.06 16:22) [6]
Добавил:
procedure TPngLVButton.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
Message.Result := 1;
end;
Результата нет.
DimaBr (2006-12-25 16:42:00) [14]
procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
{ Only erase background if we're not doublebuffering or painting to memory. }
if not FDoubleBuffered or
(TMessage(Message).wParam = TMessage(Message).lParam) then
FillRect(Message.DC, ClientRect, FBrush.Handle);
Message.Result := 1;
end;
По умолчанию фон перерисовывается путём такой вот прорисовки - моргание которой вы и наблюдаете. После вы уже и рисуете на чистом полотне в методе Paint
Нулевой (2006-12-25 16:38:00) [15]DimaBr (25.12.06 16:22) [6]
Наоборот нужно перерисовать только фон! А картинку оставить.
DimaBr (2006-12-25 16:22:00) [16]Моргает потому что перерисовывается фон. Запретите перерисовывание фона (WMEraseBkgnd -> Message.Result := 1;)
Нулевой (2006-12-25 15:36:00) [17]Наиль © (25.12.06 10:33) [3]
1.
type
TBtnState = (bsNormal, bsOver, bsDown);
TButtonLayout = (blGlyphLeft, blGlyphRight, blGlyphTop, blGlyphBottom);
TColorScheme = (csNeoDesert, csNeoSky, csNeoGrass, csNeoSilver, csNeoRose,
csNeoSun,
csDesert, csGrass, csSky, csSun, csRose, csSilver, cs71LVNet, csCustom);
TPngLVButton = class(TCustomControl)
private
FColorFace: TColor;
...
2. Да
DoubleBuffered:=true использовал не помогает, см.в коде, потом закоментировал.
DimaBr (25.12.06 10:45) [4]
1. не помогает.
3. это переписать? - лень!
Моя думает дописать типа такого... сделать дырку в BtnBmp в которую поместить картинку, тогда моргаь не будет (наверно, пока уверен). Исхожу из того, что написав FrameRect(PaintRect), где Rect это PngImage) перекрыв весь вид кнопки - мерцания нет, тока цвет последнего Brush, т.е. вид кнопки поломался.
Весь смысл кода, что создается Bitmap, поверх PngImage, потом при Paint опять Bitmap - pngImage - вот здесь при перерисовке и мерцание. А хотелось бы обновлять только фон, т.е. BtnBmp.
Уже зарапортавался - а как из BtnBmp (TBitmap) вырезать PngImage, если есть Rect этого PngImage. Может использовать регионы? Чёт уже готов плюнут на мерцание!!!! ПОМОГИТЕ-ТЕ-ТЕ!
DimaBr (2006-12-25 10:45:00) [18]По коду:
1. Paint, лучше заменить на Invalidate или InvalidateRect
2. Временный BitMap можно создавать единожды а не в прорисовке.
3. Вообще можно нарисовать кнопку в трёх состояниях и просто копировать - будет работать гораздо быстрее.
Наиль (2006-12-25 10:33:00) [19]Я попытался разобраться в вопросе.
Сделал следующие выводы.
По коду:
1. Реализовывается наследник от TWinControl, скорее всего от TButton.
2. компонент выполняет функции кнопки.
3. Может имееть полупрозрачный глиф (рисунок).
По вопросу:
Причина возникновения мерцания для меня не ясна.
Возможно поможет DoubleBuffered:=true в конструктуре.
Но в любом случае PNG лучше рисовать не на компоненте, а на поверхности временого BitMap'a. А уже полностью готовое изображение (кнопки) переносить с BitMap'a на компонент.
DimaBr (2006-12-25 09:58:00) [20]Очень много кода - нечитабельно. Объясните вкраце суть вашей проблемы.