Двойной буферизации в delphi недостаточно - PullRequest
2 голосов
/ 09 апреля 2020

Я пытаюсь построить индикатор авионии c с Delphi XE2.

enter image description here

Я использую tRotateimage для горизонта http://www.delphiarea.com/products/delphi-components/rotateimage/

enter image description here

Это изображение за обычным изображением с прозрачным участком посередине.

enter image description here

Возможность поворота изображения для поворота и перемещения tRotateimage.top для высоты тона работает хорошо, но я получаю много мерцающих событий с двойной буферизацией, включенной в мою форму. Он мигает, когда я поворачиваю изображение или перемещаю его вверх с помощью .top

Могу ли я что-то еще сделать, чтобы устранить это мерцание?

 if tryStrToFloat(GetHashtag('#ROLL',',',Memo1.Lines.Text),MyDouble) then
 Begin
  rtAttitudeNeedle.Angle := 0- MyDouble;
  rtAttitude.Angle :=0- MyDouble;
 end;

 if tryStrToFloat(GetHashtag('#PITCH',',',Memo1.Lines.Text),MyDouble) then
 Begin
  rtAttitude.Top := Round(iAttitudeTop + MyDouble);
 end;

1 Ответ

4 голосов
/ 09 апреля 2020

Двойная буферизация формы - не всегда волшебный трюк c для решения всех ваших проблем с мерцанием. вам нужно понять, почему у вас это мерцание в первую очередь.

если вы часто используете объект холста непосредственно в процедуре рисования, то вы ничего не делаете.

В большинстве случаев Чтобы решить эту проблему и уменьшить мерцание, вам необходимо нарисовать растровое изображение памяти, затем, наконец, CopyRect для объекта canvas.

Что-то вроде этого для вашего компонента (замените процедуру Paint на эту code)

procedure TRotateImage.Paint;
var
  SavedDC: Integer;
  PaintBmp: TBitmap;
begin
  PaintBmp := TBitmap.Create;
  try
    PaintBmp.SetSize(Width, Height);

    if not RotatedBitmap.Empty then
    begin
      if RotatedBitmap.Transparent then
      begin
        PaintBmp.Canvas.StretchDraw(ImageRect, RotatedBitmap);
      end
      else
      begin
        SavedDC := SaveDC(PaintBmp.Canvas.Handle);
        try
          SelectClipRgn(PaintBmp.Canvas.Handle, ImageRgn);
          IntersectClipRect(PaintBmp.Canvas.Handle, 0, 0, Width, Height);
          PaintBmp.Canvas.StretchDraw(ImageRect, RotatedBitmap);
        finally
          RestoreDC(PaintBmp.Canvas.Handle, SavedDC);
        end;
      end;
    end;
    if csDesigning in ComponentState then
    begin
      PaintBmp.Canvas.Pen.Style := psDash;
      PaintBmp.Canvas.Brush.Style := bsClear;
      PaintBmp.Canvas.Rectangle(0, 0, Width, Height);
    end;

    Canvas.CopyRect(ClientRect, PaintBmp.Canvas, PaintBmp.Canvas.ClipRect);
  finally
    PaintBmp.Free;
  end;
end;

, если это не решит проблему полностью, вы можете взглянуть на этот набор компонентов без мерцания и попытаться адаптировать вращающийся код на одном из его компонентов или наследовать его (Я не автор, и он претендует на функциональность без мерцания).

FreeEsVclComponents GitHub репозиторий

Редактировать: после отладки Я обнаружил много проблем с этим элементом управления, поэтому я решил go с моей рекомендацией.

Я создал для вас следующий элемент управления

* 10 23 *A gif image for TAttitudeControl

Все, что я сделал, это унаследовал от TEsImage и внес некоторые изменения в его работу. Из старого элемента управления я использовал приведенную ниже процедуру для преобразования вращения.

function CreateRotatedBitmap(Bitmap: TBitmap; const Angle: Extended; bgColor: TColor): TBitmap;

Как видно из рисунка выше, процедура вращения не идеальна. Я предлагаю вам поискать альтернативу.

Я также разветвил репозиторий FreeEsVclComponents и добавил TAttitudeControl к блоку Es.Images, так что у вас есть все, что нужно для установки элемента управления в вашей системе. Нажмите здесь

Наконец я протестировал это в Токио, и из файла readme репозитория оно должно работать на XE2 без проблем.

Edit2: Я изменил CreateRotatedBitmap на лучший (на основе GDI +), вот результат:

TAlttitudeControl gif image

Я уже перенес изменения в Github так что вы можете git код оттуда. Я также добавляю код здесь на случай, если Github выйдет из строя (очень маловероятно:))

uses
  WinApi.Windows, WinApi.GDIPApi, WinApi.GDIPObj, Vcl.Graphics, System.Types;

function RotateImage(Source: TBitmap; Angle: Extended; AllowClip: Boolean): TBitmap;
var
  OutHeight, OutWidth: Integer;
  Graphics: TGPGraphics;
  GdiPBitmap: TGPBitmap;
begin

  if AllowClip then
  begin
    OutHeight := Source.Height;
    OutWidth := Source.Width;
  end
  else
  begin
    if (Source.Height > Source.Width) then
    begin
      OutHeight := Source.Height + 5;
      OutWidth := Source.Height + 5;
    end
    else
    begin
      OutHeight := Source.Width + 5;
      OutWidth := Source.Width + 5;
    end;
  end;

  Result := TBitmap.Create;
  Result.SetSize(OutWidth, OutHeight);

  GdiPBitmap := nil;
  Graphics := TGPGraphics.Create(Result.Canvas.Handle);
  try
    Graphics.SetSmoothingMode(SmoothingModeDefault);
    Graphics.SetPixelOffsetMode(PixelOffsetModeHalf);
    Graphics.SetInterpolationMode(InterpolationModeLowQuality);

    Graphics.TranslateTransform(OutWidth / 2, OutHeight / 2);
    Graphics.RotateTransform(Angle);
    Graphics.TranslateTransform(-OutWidth / 2, -OutHeight / 2);

    GdiPBitmap := TGPBitmap.Create(Source.Handle, Source.Palette);
    try
      Graphics.DrawImage(GdiPBitmap, 0, 0);
    finally
      GdiPBitmap.Free;
    end;
  finally
    Graphics.Free;
  end;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...