PDA

Visualizza la versione completa : [Borland C++ Builder] Interfaccia non rettangolare....


Ephestus
30-09-2004, 13:04
'giorno... :ciauz:

sapete mica come si possa creare un progetto che invece della solita interfaccia rettangolare di base, possa avere forme particolari? :dottò: Ad esempio che segue i contorni di un'immagine predisegnata o modellarlo sul momento? :oVVoVe:

Come esempio reale mi viene in mente il classico Windows Media Player di Winzozz XP nella modalità "Interfaccia". :zizi:



Grazie mille



:ciauz::ciauz:

alka
30-09-2004, 13:20
L'effetto a cui ti riferisci viene spesso utilizzato anche nelle SplashForm, allo scopo di modellare la finestra introduttiva dell'applicazione rendendola trasparente, in alcuni casi "bucata", in corrispondenza di un'immagine caricata al suo interno.

Ho scritto una procedura simile in Delphi; a grandi linee, si tratta di usare le funzioni API CreateRectRgn e CombineRgn.

La funzione CreateRectRgn permette di creare una regione rettangolare; la "regione" definisce un'area di disegno entro la quale ogni operazione di disegno, appunto, viene concessa, mentre all'esterno diviene ininfluente.

La regione può essere associata ad un form affinchè esso venga tracciato seguendo tale regione, quindi la complessità del lavoro si ha nel definire una regione che abbia la forma del bitmap selezionato, ma escludendo le parti che possiedono un colore predeterminato come trasparente.

Si può iniziare creando una regione rettangolare che abbia le dimensioni del bitmap con la funzione CreateRectRgn; in seguito, si scandisce ogni singolo pixel del bitmap e, quando si individua il colore trasparente, si crea una regione rettangolare separata che abbia le dimensioni e la posizione del pixel; attraverso la funzione CombineRgn si combinano le due regioni sottraendo la regione del pixel da quella del bitmap.

Ripetendo l'operazione per tutti i pixel del bitmap, si otterrà una regione rettangolare privata di tutte le microregioni interne appartenenti a ciascun pixel che viene decretato come trasparente.

Attraverso la funzione API SetWindowRgn si può associare la regione risultante alla form, affinchè le operazioni grafiche necessarie al suo tracciamento non escano dall'area definita dalla regione stessa. Inserendo poi un controllo TImage con coordinate (0, 0) nella form con il bitmap stesso, si avrà l'effetto di una form modellata attorno all'immagine che lascia intravedere lo sfondo.

In Delphi 6 e C++Builder 6 sono presenti anche le proprietà Transparent e TransparentColor per le form, ma utilizzando API funzionanti solo su sistemi Windows 2000 e XP, mentre la soluzione presentata prima lavora su qualsiasi sistema.

Ciao! :ciauz:

Ephestus
30-09-2004, 14:04
Interessante il primo modo....quindi non fai altro che creare tante regioni trasparenti ove l'immagine è bianca (ad esempio..), poi elimini dalla regione creata con CreateRectRgn(Top,Left,Height,Width); (che sovrappone esattamente la bitmap inserita in TImage) tutte le regioni trasparenti ed infine il form viene settato con quest'ultima regione risultante...

Come logica mi piace, ma ci sono dei problemi in fase di programmazione....
1)come si fa a testare pixel a pixel in un TImage? :master:
2)Questa funzione va richiamata all'evento OnCreate, OnPaint o On Activate?? Io sarei propenso all'OnCreate....ma non ne sono certo...

Per il resto....grazie!

Ci provo immediatamente

alka
30-09-2004, 14:13
Il concetto di "trasparenza" non è incluso nel concetto di "regione".

La regione è semplicemente un'area geometrica nella quale sono valide le operazioni di disegno, mentre all'esterno esse non vengono eseguite.

Si possono creare regioni rettangolari, ellittiche e così via; quella rettangolare è la base di partenza, nel nostro caso.

Per ciascun pixel da considerare trasparente nel bitmap si deve creare una piccola regione rettangolare delle dimensioni del pixel; tale regione dovrà essere combinata con la regione rettangolare più grande affinchè da quest'ultima venga rimossa la prima. In poche parole, la regione risultante è la regione rettangolare originale privata della regione corrispondente al pixel trasparente. Ripetendo questa operazione per tutti e soli i pixel da considerate trasparenti, la regione finale avrà la forma desiderata della figura.

Per ottenere le caratteristiche dell'immagine e il colore dei singoli pixel, devi accedere al bitmap contenuto nel controllo TImage attraverso la proprietà Picture.Bitmap; la proprietà Bitmap di tipo TBitmap dispone di una proprietà ScanLine che ti permette di reperire le informazioni sul colore; esiste anche la proprietà Pixels del Canvas, ma è più lenta. Le informazioni su ScanLine le trovi nella Guida in linea.

Per quanto riguarda l'esecuzione del metodo, io ridefinirei il metodo Loaded della form e inserirei in quel punto la chiamata al metodo che implementa la definizione della regione, poichè tutte le proprietà della form e dei controlli in essa contenuti sono già state caricate.

Ciao! :ciauz:

Ephestus
30-09-2004, 14:34
Perfetto....diventi sempre più chiaro (ti spieghi sempre meglio) ma complichi sempre di più le cose........... :zizi: :
Non ho la più pallida idea di come modificare un metodo (non sapevo nemmeno che si potesse fare fino a qualche minuto fa...) potresti essere così gentile da spendere 2 paroline sull'argomento? :D

Grazie mille...


:ciauz:

alka
30-09-2004, 14:41
La trattazione può essere molto complessa. In Delphi, si ottiene aggiungendo la parola chiave override alla dichiarazione del metodo.

Ridefinire metodi virtuali è una prerogativa della programmazione orientata agli oggetti e serve ad implementare il concetto di polimorfismo.

Come ben sai, non conosco così bene C++Builder poichè lavoro in Delphi, quindi non uso C++ bensì il linguaggio Object Pascal (anzi, Delphi), pertanto non mi è possibile fornirti aiuto sulla stesura del codice, se non in quei frangenti in cui si tratta di analizzare la VCL, che è identica sia in C++Builder che in Delphi.

L'unico ulteriore suggerimento che posso darti è quello di fare una ricerca approfondita su Google riguardo questo argomento, oppure attendere aiuto da qualcun altro che utilizzi C++Builder. :(

Ephestus
30-09-2004, 14:52
Sto cercando su google e non solo....con scarsi risultati...continuerò finché non sarò distrutto :D

Comunque se non erro il C++Builder ha la possibilità di importare file Delphi(ne sono certo perché il mio proff. era solito scrivere in Delphi le sue applicazioni per poi farcele "modificare"/"utilizzare" sul C++...

Se stendi qualche riga di codice in Pascal provo a farla girare sul C Builder....mal che vada cercherò di tradurla a mano :incupito: Che pazzo che sono...... :D



Davvero molte grazie comunque....ti farò sapere se ne vengo a capo...

:ciauz: :ciauz:

alka
30-09-2004, 14:57
Originariamente inviato da Ephestus
Comunque se non erro il C++Builder ha la possibilità di importare file Delphi(ne sono certo perché il mio proff. era solito scrivere in Delphi le sue applicazioni per poi farcele "modificare"/"utilizzare" sul C++...
Per quanto ne so, sono i file compilati (dcu e bpl) ad essere compatibili, ma non il codice sorgente vero e proprio, che deve essere compilato all'interno di ciascun ambiente.


Originariamente inviato da Ephestus
Se stendi qualche riga di codice in Pascal provo a farla girare sul C Builder....mal che vada cercherò di tradurla a mano :incupito: Che pazzo che sono...... :D
Ti posto il codice del metodo che si occupa di creare la regione, ma non posso prendermi il tempo di formattarlo in HTML nè di commentarlo in modo approfondito:


function TSplashForm.CreateRegion(Bmp: TBitmap): THandle;
type
PRGBArray = ^TRGBArray;
TRGBArray = array[0..32767] of TRGBTriple;
var
x, y, s: Integer;
Excl: THandle;
Row: PRGBArray;
TrColor: TRGBTriple;
begin
Bmp.PixelFormat := pf24bit;
Result := CreateRectRgn(0, 0, Bmp.Width, Bmp.Height);
with TrColor do
begin
rgbtRed := 0;
rgbtGreen := 255;
rgbtBlue := 0;
end;
for y := 0 to Bmp.Height - 1 do
begin
Row := Bmp.ScanLine[y];
s := -1;
for x := 0 to Bmp.Width - 1 do
begin
if (Row[x].rgbtRed = TrColor.rgbtRed)
and (Row[x].rgbtGreen = TrColor.rgbtGreen)
and (Row[x].rgbtBlue = TrColor.rgbtBlue) then
begin
if s = -1 then
s := x;
end
else begin
if s > -1 then
begin
Excl := CreateRectRgn(s, y, x + 1, y + 1);
try
CombineRgn(Result, Result, Excl, RGN_DIFF);
s := -1;
finally
DeleteObject(Excl);
end;
end;
end;
end;
if s > -1 then
begin
Excl := CreateRectRgn(s, y, Bmp.Width, y + 1);
try
CombineRgn(Result, Result, Excl, RGN_DIFF);
finally
DeleteObject(Excl);
end;
end;
end;
end;

La funzione accetta come parametro di ingresso il bitmap da utilizzare come modello e restituisce l'handle della regione corrispondente da impostare sul form.

Ciao! :ciauz:

Ephestus
30-09-2004, 15:04
grazie davvero....adesso con calma me lo studio...ti farò sapere!


:ciauz:

Ephestus
30-09-2004, 15:56
FATTO!!!!!!! :unz::yuppi::unz:......in parte!

Queste sono le mie scoperte (mischiando le informazioni trovate in 8 siti diversi....)
1) Non è necessario modificare il metodo Loaded... basta che all'evento OnCreate venga richiamata la funzione, nella quale è presente SetWindowRgn(Handle,Regione,true); Il true alla fine indica che il programma deve immediatamente ridisegnare la Form.
2) Al contrario del Delphi il CreateRectRgn non può essere assegnato ad una variabile THandle (non esiste o non me la riconosce), ma bensi ad una variabile HRGN.

Appena avrò finito tutta la funzione la scriverò qua sotto così i posteri non dovranno dannarsi... :D :D



Moltissime grazie a te Alka....prima o poi erigerò un monumento in tuo onore.... :D

:ciauz:

Loading