[Delphi] Nieodświeżalny Canvas dla kontrolki innej niż TImag

0

Witam.

Stworzyłem sobie klasę dziedziczącą z TScrollBox, wzbogaconą o Canvas, ale mam problem. Jak na tym Canvasie coś narysuję
albo napisze to po na przykład zminimalizowaniu formatki i ponownym jej przywróceniu wszystko znika. Czy jest możliwość aby
zawartość Canvasa zostawała? Prosiłbym o jakiś przykładowy kod. Patrzyłem na stare źródła TImage, ale nie znalazłem według'
mnie żadnego kodu, który by pozostawiał to co narysowano. Pewnie jest to możliwe, bo TImage dziedziczy z TGraphicControl, a
mi potrzebna jest taka kontrolka jak choćby ScrollBox, który może być Parentem dla innych wizualnych komponentów. Tyle tylko,
że dodatkowo ma posiadać Canvas, na którym pozostaje to co zostało napisane lub narysowane, tak jak dzieje się to na TImage.

0

rysujesz po bitmapie a w zdarzeniu paint komponentu przerysowywujesz z bitmapy na płutno

0

Dzięki, to samo polecono mi na innym forum. Ale nadal mam problem, bo nie bardzo wiem jak to zrobić.

  protected
    procedure Paint; override;

I zwraca mi oczywiście błąd.

[Error] canvasedscrollbox.pas(13): Method 'Paint' not found in base class

Wiadomo, bo TScrollBox, z którego dziedziczę nie posiada takiej metody. Można prosić o jakiś kod
przykładowy, bo rozumiem że mam rysować po zadeklarowanej na formatce Bitmapie, a później
do zdarzenia OnPaint przekazać jako parametr tę bitmapę i ją narysować, na przykład tak jak tutaj:

var
  A : Tcanvasedscrollbox;
  Bmp : TBitmap;
begin
  A := Tcanvasedscrollbox.Create(Self);
  A.Parent := Form1;
  Bmp := TBitmap.Create;
  Bmp.Width := A.Width;
  Bmp.Height := A.Height;
  Bmp.Canvas.Brush.Color := clBtnFace;
  Bmp.Canvas.FillRect(ClientRect);
  Bmp.Canvas.TextOut(10, 10, 'TEST');
  A.Canvas.Draw(0, 0, Bmp);
  Bmp.Free;
end;

Tylko właśnie ja nie wiem jak dodać zdarzenie OnPaint do ScrollBoxa, tak aby to wszystko jak
należy działało. Prosiłbym o krótki przykład. Z gory dziękuję i przepraszam za zawracanie głowy.

0

to zamiast Paint daj w private

procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

i tam wstaw ten kod

ROBISZ SWÓJ KOMPONENT WIĘC JAKA FORMATKA, JAKI PARAMETR PRZEKAZAĆ!!!?????

Olesio nie jesteś przecież tępym klikaczem :)

co ma być na tej bitmapie??

0

Dzięki już sobie poradziłem. A i fajnie, że mnie nie uważasz za klikacza ;) Staram się. Jakby ktoś chciał
kiedyś zdziałać coś podobnego to poniżej cały kod. Można dziedziczyć z jakichś innych komponentów.
A co do pytania co ma być na bitmapie, to ja zalożyłem że tylko tekst rysowany pod różnymi kątami :)

unit canvasedscrollbox;

interface

uses
  Windows, Messages, Classes, Controls, Forms, Graphics;

type
  TCanvasedScrollBox = class(TScrollBox)
  private
    FBmp: TBitmap;
    FCanvas: TCanvas;
    procedure SetBitmap(Value: TBitmap);
  protected
    procedure WMPaint(var Message: TMessage); message WM_PAINT;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property Bitmap: TBitmap read FBmp write SetBitmap;
    property Canvas: TCanvas read FCanvas;
  end;

implementation

constructor TCanvasedScrollBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
    csSetCaption, csDoubleClicks];
  Width := 185;
  Height := 41;
  BorderStyle := bsSingle;
  FBmp := TBitmap.Create;
  FCanvas := TControlCanvas.Create;
  TControlCanvas(FCanvas).Control := Self;
end;

procedure TCanvasedScrollBox.SetBitmap(Value: TBitmap);
begin
  FBmp.Assign(Value);
  SendMessage(Handle, WM_PAINT, 0, 0);
end;

procedure TCanvasedScrollBox.WMPaint(var Message: TMessage);
var
  Bmp : TBitmap;
begin
  if Assigned(FBmp) then
    begin
    Bmp := TBitmap.Create;
    Bmp.Assign(FBmp);
    Canvas.Draw(0, 0, Bmp);
    Bmp.Free;
    end;
  inherited;
end;

end.
0
procedure TCanvasedScrollBox.WMPaint(var Message: TMessage);
begin
  if Assigned(FBmp) then
    FCanvas.Draw(0, 0, FBmp);
  inherited;
end;
procedure TCanvasedScrollBox.SetBitmap(Value: TBitmap);
begin
  FBmp.Assign(Value);
  Invalidate; //albo RePaint jeśl Invalidate nie zadziała
end;
  1. Canvas w public nie published!
  2. w destruktorze musisz zwolnić FBmp i FCanvas
0

Dziękuję za porady. Poprawię co trzeba. Ale jednak musi chyba zostać tak:

procedure TCanvasedScrollBox.SetBitmap(Value: TBitmap);
begin
  FBmp.Assign(Value);
  SendMessage(Handle, WM_PAINT, 0, 0);
end;

Gdyż ani Invalidate ani RePaint na koncu - nie powodują pokazania się bitmapy, a przy wysyłaniu za
pomocą SendMessage WM_PAINT jest wszystko ok. Do pozostałych rad się zastosowałem, chyba że
masz Misiekd jeszcze jakieś pomysły albo wiesz moze jak zrobić SetBitmap bez SendMessage, to pisz.
Ja kombinowałem pod Delphi 7 i niestety konieczne jest wysłanie WM_PAINT aby działało poprawnie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1