Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];

Вниз

Ни как не могу убрать мерцание картинки!   Найти похожие ветки 

 
Нулевой ©   (2006-12-24 19:56) [0]

Если не глядеть на мерцание (что не реально) вроде "все" работает! Создается 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-24 19:57) [1]

...

constructor TPngLVButton.Create(AOwner: TComponent);
begin
 inherited;
 Width := 75;
 Height := 25;
 FCtl3D := True;
 FGradient := False;
 TabStop := True;
 FSpacing := 4;
 FCancel := False;
 FDefault := False;
 FHotTrack := False;
 ColorScheme := cs71LVNet;
 FClicked := False;
 FOverColorGrad := $00C8D0D4;
 FDownColorGrad := $00C8D0D4;
 FDisabledColorGrad := $00C8D0D4;
 //--- +
 FPngImage := TPNGObject.Create;
 FPngOptions := [pngBlendOnDisabled];
 FImageFromAction := False;
 FMargin := -1;
 //DoubleBuffered := true;
 //ControlStyle := ControlStyle + [csOpaque];
 //--- end
end;

destructor TPngLVButton.Destroy;
begin
 FPngImage.Free; //--- +
 inherited Destroy;
end;

procedure TPngLVButton.ActionChange(Sender: TObject; CheckDefaults: Boolean);
begin
 inherited ActionChange(Sender, CheckDefaults);
 if Sender is TCustomAction then
   with TCustomAction(Sender) do
   begin
     //Copy image from action"s imagelist
     if (PngImage.Empty or FImageFromAction) and (ActionList <> nil) and
       (ActionList.Images <> nil) and (ImageIndex >= 0) and (ImageIndex <
       ActionList.Images.Count) then
     begin
       CopyImageFromImageList(FPngImage, ActionList.Images, ImageIndex);
       FImageFromAction := True;
     end;
   end;
end;

procedure TPngLVButton.Click;
begin
 if Parent <> nil then
   GetParentForm(self).ModalResult := ModalResult;
 FBtnState := bsNormal;
 //Paint;
 inherited;
end;

procedure TPngLVButton.MouseEnter(var msg: TMessage);
begin
 if csDesigning in ComponentState then
   exit;
 if not FHotTrack then
   exit;
 if FClicked then
   FBtnState := bsDown
 else
   FBtnState := bsOver;
 Paint;
end;

procedure TPngLVButton.MouseLeave(var msg: TMessage);
begin
 inherited;
 if not FHotTrack then
   exit;
 FBtnState := bsNormal;
 Paint;
end;

procedure TPngLVButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y:
 Integer);
begin
 inherited;
 if Button <> mbLeft then
   Exit;
 FClicked := True;
 FBtnState := bsDown;
 if TabStop then
   SetFocus;
 Paint;
end;

procedure TPngLVButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:
 Integer);
begin
 inherited;
 FClicked := False;
 if (x > 0) and (y > 0) and (x < width) and (y < height) then
   if FHotTrack then
     FBtnState := bsOver
   else
     FBtnState := bsNormal;
 Paint;
end;

procedure TPngLVButton.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
 inherited;
end;

procedure TPngLVButton.WMSetFocus(var msg: TWMSetFocus);
begin
 FFocused := true;
 Paint;
end;

procedure TPngLVButton.WMKillFocus(var msg: TWMKillFocus);
begin
 FFocused := false;
 FBtnState := bsNormal;
 Paint;
end;

procedure TPngLVButton.WMKeyDown(var msg: TWMKeyDown);
begin
 if msg.CharCode = VK_SPACE then
   FBtnState := bsDown;
 if msg.CharCode = VK_RETURN then
   Click;
 Paint;
end;

procedure TPngLVButton.WMKeyUp(var msg: TWMKeyUp);
begin
 if (msg.CharCode = VK_SPACE) then
 begin
   FBtnState := bsNormal;
   Paint;
   Click;
 end;
end;

...


 
DimaBr   (2006-12-25 09:58) [2]

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


 
Наиль ©   (2006-12-25 10:33) [3]

Я попытался разобраться в вопросе.
Сделал следующие выводы.
По коду:
1. Реализовывается наследник от TWinControl, скорее всего от TButton.
2. компонент выполняет функции кнопки.
3. Может имееть полупрозрачный глиф (рисунок).

По вопросу:
Причина возникновения мерцания для меня не ясна.
Возможно поможет DoubleBuffered:=true в конструктуре.
Но в любом случае PNG лучше рисовать не на компоненте, а на поверхности временого BitMap"a. А уже полностью готовое изображение (кнопки) переносить с BitMap"a  на компонент.


 
DimaBr   (2006-12-25 10:45) [4]

По коду:
1. Paint,  лучше заменить на Invalidate или InvalidateRect
2. Временный BitMap можно создавать единожды а не в прорисовке.
3. Вообще можно нарисовать кнопку в трёх состояниях и просто копировать - будет работать гораздо быстрее.


 
Нулевой ©   (2006-12-25 15:36) [5]

Наиль ©   (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 16:22) [6]

Моргает потому что перерисовывается фон. Запретите перерисовывание фона (WMEraseBkgnd -> Message.Result := 1;)


 
Нулевой ©   (2006-12-25 16:38) [7]

DimaBr   (25.12.06 16:22) [6]
Наоборот нужно перерисовать только фон! А картинку оставить.


 
DimaBr   (2006-12-25 16:42) [8]


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 17:08) [9]

DimaBr   (25.12.06 16:22) [6]
Добавил:
procedure TPngLVButton.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
 Message.Result := 1;
end;
Результата нет.


 
Нулевой ©   (2006-12-25 17:23) [10]

Попробовал на Image - 24x24 - можно сказать не вижу верцания.
На Image 128x128 - осталось почти также.
NB. В принцепе оно и было то не сильное.


 
DimaBr   (2006-12-26 08:52) [11]


> Нулевой ©   (25.12.06 17:08) [9]

А использование сообщения описали ?
Проще всего проверить поставив брейкпоинт на первую строчку метода Paint и "нажать на кнопку". В этот момент ваша "нарисованная кнопочка" должна ещё быть нарисованной. Если этого не происходит (вы рисуете на чистом полотне) - кто-то его уже очищает.


 
Наиль ©   (2006-12-26 08:53) [12]


> Нулевой ©   (25.12.06 17:23) [10]

У тебя всё ещё
DrawPNG(FPngImage, Canvas, PaintRect, [])
или уже
DrawPNG(FPngImage, BtnBmp.Canvas, PaintRect, [])?


 
Нулевой ©   (2006-12-26 11:15) [13]

Наиль ©   (26.12.06 08:53) [12]
Если DrawPNG(FPngImage, BtnBmp.Canvas, PaintRect, [])
картинки нет вообще, ни в среде... ни при click!


 
Нулевой ©   (2006-12-26 11:39) [14]

DimaBr   (26.12.06 08:52) [11]
Не совсем понял? где поставить брейкпоинт.


 
Нулевой ©   (2006-12-26 11:47) [15]

Забываю написать - мерцает толька картинка (для моих глаз так). Мерцания за картинкой не наблюдаю, или это происходит очень быстро.


 
Нулевой ©   (2006-12-26 11:49) [16]

А есть смысл создание 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 12:33) [17]

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 13:06) [18]

Сделал очень большую кнопку.
Точно 3. идет переключение канвы(канвов) с одной на другую.
PngImage зарисовывает BtnBmp.Canvas, потом BtnBmp.Canvas - PngImage.


 
Нулевой ©   (2006-12-26 13:11) [19]

Как сделать в BtnBmp типа TBitmap дырку размером PaintRect?


 
Наиль ©   (2006-12-26 17:12) [20]


> или ничего не даст!

даст некоторое ускорение, но не избавит от мерцания.

> И почему Наиль ©   (26.12.06 08:53) [12] не рисует на Canvase
> BtnBmp?

Покажи как ты это делаешь. И проверь PaintRect.


 
Нулевой ©   (2006-12-27 16:09) [21]

Если правильно понял показать 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;



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

Форум: "Основная";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.052 c
2-1169892708
GEN++
2007-01-27 13:11
2007.02.18
Передача массива между приложениями


9-1144169967
Pa5ha
2006-04-04 20:59
2007.02.18
Эффекты на OpenGL


4-1160039736
Михаил И.
2006-10-05 13:15
2007.02.18
Найти процесс


2-1170190894
Marker
2007-01-31 00:01
2007.02.18
Цветные строки в TMemo


3-1163802142
diofant
2006-11-18 01:22
2007.02.18
Olap и IB





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский