Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Ни как не могу убрать мерцание картинки! [D7, Win95/98, WinXP]


Страницы:   1 2

Нулевой ©   (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]

Очень много кода - нечитабельно. Объясните вкраце суть вашей проблемы.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо