Newsgroup: it.comp.lang.delphi
Titolo: TCustomControl + Timage + TScrollBox

Sto cercando di costruire un componente TMyComp costituito da un'Image e 
da un ScrollBox, tale che l'immagine visualizzata da Image deve avere le 
barre di scorrimento del ScrollBox se non può
venire visualizzata interamente.
Segue sinteticamente il codice che crea il componente:
procedure TMainForm.FormCreate(Sender: TObject);
begin
   Doublebuffered := True;
   TMyComp := TMyComp.Create(Self);
   TMyComp.Parent := Self;
   TMyComp.Align := alClient;
   TMyComp.Visible := True;
   TMyComp.OpenImage(...); // carica un'immagine in loDicom.Image
end;
Segue sinteticamente il codice del componente:
TMyComp = class(TCustomControl)
     Image: TImage;
     ScrollBox: TScrollBox;
		...
end;
constructor TMyComp.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   DoubleBuffered := True;
   ScrollBox := TScrollBox.Create(AOwner);
//  ScrollBox.Parent := Self;
   ScrollBox.Align := alClient;
   ScrollBox.Visible := True;
   Image := TImage.Create(ScrollBox);
   Image.Anchors := [akLeft,akTop];
   Image.Left := 0;
   Image.Top := 0;
   Image.Align := alClient;
   Image.AutoSize := True;
   ...
end;
procedure TMyComp.Paint;
begin
   Canvas.Draw(0, 0, Image.Picture.Graphic);
   inherited Paint;
end;
In  questo modo viene visualizzato il componente con l'immagine 
specificata in TMyComp.OpenImage, ma non c'è ombra del ScrollBox.
Se decommento la riga 'ScrollBox.Parent := Self;' non si vede più nulla, 
sembrerebbe che l'area del ScrollBox copra l'area dell'Image.
Bye, bye

 venire visualizzata interamente. [...]
Ci sono alcuni errori nella tua implementazione.
Ne elenco alcuni tra quelli più evidenti (sono un po' di corsa...). :-)
Usare un *TImage* per contenere un'immagine, se la disegni manualmente 
(come sembra che tu stia facendo), è uno spreco di risorse: è 
sufficiente usare un *TPicture* o una classe specifica relativa ad un 
formato ben determinato di immagine (bitmap, ecc.) per contenere 
l'immagine stessa, da tracciare poi nell'area del controllo.
In secondo luogo, il controllo *TScrollBox* fa apparire le barre quando 
i controlli che si trovano nella sua "area client" eccedono la parte 
visibile di quell'area; nel tuo caso, se usi un *TImage*, che è un 
controllo, ma solamente per contenere l'immagine che poi tracci usando i 
metodi del Canvas, allora il controllo *TScrollBox* non avrà alcun 
controllo che esce dai confini menzionati poco fa, e quindi non farà 
apparire alcuna barra.
Devi decidere se vuoi utilizzare il controllo *TImage* vero e proprio 
per visualizzare l'immagine, delegando ad esso questo compito e magari 
impostando a True la proprietà /AutoSize/ e posizionandolo in alto a 
sinistra nel controllo *TScrollBox*, da assegnare come /Parent/, oppure 
tracciare manualmente l'immagine, ma in quest'ultimo caso dovrai anche 
occuparti di informare tu stesso il controllo *TScrollBox* dei casi in 
cui le barre devono apparire (in sostanza, il vantaggio di usare quel 
controllo svanisce).
Spero di essere riuscito a fornirti il quadro del problema; poi, la 
scelta della strada da seguire la lascio a te. :-)
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

 
Innanzitutto grazie per la tua risposta, credo che mi sia stata utile.
Infatti ho modificato il codice come segue e adesso funziona, se 
necessario ci sono anche le barre di scorrimento, ma purtroppo quando 
ridimensiono la form c'è un leggero flickering dell'area client 
dell'Image. Se tolgo la riga 'ScrollBox.Parent := Self;' scompare il 
flickering ma spariscono anche le barre di scorrimento.
E' possibile ovviare a questo difetto di visualizzazione?
procedure TMainForm.FormCreate(Sender: TObject);
begin
   Doublebuffered := True;
   MyComp := TMyComp.Create(Self);  // definito nella classe TMainForm
   MyComp.Parent := Self;
   MyComp.Align := alClient;
   MyComp.Visible := True;
   MyComp.OpenImage(...); // carica un'immagine in TMyComp.Image
end;
Segue sintetticamente il codice del componente:
TMyComp = class(TCustomControl)
     Image: TImage;
     ScrollBox: TScrollBox;
		...
end;
constructor TMyComp.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   DoubleBuffered := True;
   ScrollBox := TScrollBox.Create(AOwner);
   ScrollBox.Parent := Self;
   ScrollBox.Align := alClient;
   Image := TImage.Create(ScrollBox);
   Image.Parent := ScrollBox;
   Image.Left := 0;
   Image.Top := 0;
   Image.AutoSize := True;
   ...
end;
procedure TMyComp.Paint;
begin
   Canvas.Draw(0, 0, Image.Picture.Graphic);
   inherited Paint;
end;
Grazie ancora e ciao.

 
Innanzitutto grazie per la tua risposta, credo che mi sia stata utile.
Infatti ho modificato il codice come segue e adesso funziona, se 
necessario ci sono anche le barre di scorrimento, ma purtroppo quando 
ridimensiono la form c'è un leggero flickering dell'area client 
dell'Image. Se tolgo la riga 'ScrollBox.Parent := Self;' scompare il 
flickering ma spariscono anche le barre di scorrimento.
E' possibile ovviare a questo difetto di visualizzazione?
procedure TMainForm.FormCreate(Sender: TObject);
begin
   Doublebuffered := True;
   MyComp := TMyComp.Create(Self);  // definito nella classe TMainForm
   MyComp.Parent := Self;
   MyComp.Align := alClient;
   MyComp.Visible := True;
   MyComp.OpenImage(...); // carica un'immagine in TMyComp.Image
end;
Segue sintetticamente il codice del componente:
TMyComp = class(TCustomControl)
     Image: TImage;
     ScrollBox: TScrollBox;
		...
end;
constructor TMyComp.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   DoubleBuffered := True;
   ScrollBox := TScrollBox.Create(AOwner);
   ScrollBox.Parent := Self;
   ScrollBox.Align := alClient;
   Image := TImage.Create(ScrollBox);
   Image.Parent := ScrollBox;
   Image.Left := 0;
   Image.Top := 0;
   Image.AutoSize := True;
   ...
end;
procedure TMyComp.Paint;
begin
   Canvas.Draw(0, 0, Image.Picture.Graphic);
   inherited Paint;
end;
Grazie ancora e ciao.

 Infatti ho modificato il codice come segue e adesso funziona [...]
Hai ancora il metodo /Paint/ ridefinito con le istruzioni che fanno uso 
dei metodi dell'oggetto /Canvas/, che non servono (visto che utilizzi un 
controllo *TImage* incorporato, che è perfettamente in grado di svolgere 
tutto il lavoro).
Il codice del tuo controllo dovrebbe essere quasi azzerato e ridotto 
all'esposizione dei due controlli incorporati, il *TScrollBox* e il 
*TImage*, di cui si serve coniugandone le funzionalità in un unico 
controllo visuale.
Ciao,
   Marco.


 
Ho eliminato la ridefinizione del metodo /Paint/ del TCustomControl 
delegando il ridisegno dell'area client all'oggetto /Image/, ma 
purtroppo il difetto di flickering permane. Ho provato anche ad 
impostare la proprietà DoubleBuffered sia della Form sia del controllo 
TScrollBox ma senza nessun effetto positivo.
Sto sbagliando qualcosa altro?
Grazie ancora.

 
Ho eliminato la ridefinizione del metodo /Paint/ del TCustomControl 


 TScrollBox ma senza nessun effetto positivo.
Forse va abilitato per il *TImage*. Non vorrei comunque che tu avessi 
ancora codice che effettua dei tracciamenti...


 
Mi sembra che la proprietà DoubleBuffered appartenga a *TWinControl*, 
invece *TImage* deriva da *TGraphicControl*.
Tutte le operazioni di disegno avvengono esclusivamente sull'oggetto Image.
Ho provato a togliere il controllo *TScrollBox* ed effettivamente 
scompare anche il flickering e quindi sarei tentato nel credere che il 
problema sia dovuto al *TScrollBox*.
Qualche altro suggerimento?
Grazie e ciao.


Risolto!
E' stato sufficiente inserire la riga:
ControlStyle := ControlStyle + [csAcceptControls];
nel costruttore del *TCustomControl*.
Ciao