Articol Lucrul cu regiunile


API Windows oferă un set de funcții care vă permit să descrie arbitrar (daca doriti - o destul de complex) figură geometrică, care pot fi apoi utilizate cu ferestre, sau, în terminologia Delphi, controale. Utilizarea poate fi, de exemplu, bazându-se pe panza, in stabilirea unei regiuni specifice a ferestrei de actualizare, etc. În plus față de aceste caracteristici aici sunt relativ nevinovate, tehnologie regiunile pozvolyayaet face, de asemenea, o bătaie de joc contururile nobile ale oricărui descendent al lui TWinControl (cu alte cuvinte, orice supraveghere a unui mâner, alias TForm, TButton, etc). regiuni deosebit de bine sunt utilizate în forme, cu desen și actualizarea acestora. Ei bine, pentru început, să vedem ce acest lucru foarte regiune.

Win32 SDK definește regiunea după cum urmează:

În Microsoft Windows, regiunea se numește un dreptunghi, poligon sau a unei elipse (sau o combinație de două sau mai multe dintre aceste cifre), care pot fi umplute, vopsite, răsturnată, încadrată și pot fi utilizate pentru a determina locația cursorului

(Ceea ce înseamnă că există o funcție standard care determină dacă un punct este o parte din (X, Y) în regiunea noastră).

Trei tipuri principale de regiuni menționate în SDK: dreptunghiulare, eliptice, și poligonale. Despre tip chotvortom, dreptunghiulare, cu margini rotunjite, shamefully silențioase, precum și smochine cu el. Se pare că acest lucru se datorează faptului că acesta poate fi obținut din primele două. Faptul că regiunile pot fi combinate unul cu altul, folosind operatori logici OR, XOR, etc. Dar pentru acest lucru vom reveni mai târziu.

HRGN = tip LongWord;


După cum puteți vedea, nimic extraordinar. De fapt, este un pointer la o structură în memorie. această structură este descrisă după cum urmează:


_RGNDATA = înregistrare
RDH. TRgnDataHeader;
Tampon. mulțime # 91; 0 0 # 93; din CHAR;
Rezervat. mulțime # 91; 0. 2 # 93; din CHAR;
se încheie;


Remarcabil, în Win32 SDK _RGNDATA a declarat un pic diferit. Elementul cel mai interesant al acestei înregistrări, cu siguranță, TRgnDataHeader. În Windows.pas apare modul, și este:

_RGNDATAHEADER = înregistrare ambalate
dwSize. DWORD;
iType. DWORD;
nCount. DWORD;
nRgnSize. DWORD;
rcBound. TRect;
se încheie;


Aici merită luat în considerare mai detaliat.

Acesta combină regiunile și p3 p2, eliminând zonele care se suprapun


Valorile returnate pot fi NULLREGION (regiune gol), SIMPLEREGION (un dreptunghi), COMPLEXREGION (orice altceva) și EROARE (nu nifiga creat). Să vedem cum arată în practică (nu prea mult chin, eu sunt doar de finisare exemplul anterior).

Procedura TForm1. FormCreate # 40; Expeditor. TObject # 41; ;
var
ap. mulțime # 91; 1. 7 # 93; din TPoint;
av. mulțime # 91; 1. 2 # 93; din întreg;
r. R2. r3. r4. hRGN;
începe
ap # 91; 1 # 93;. = Punct # 40; 0 0 # 41; ;
ap # 91; 2 # 93;. = Punct # 40; Lățime. 0 # 41; ;
ap # 91; 3 # 93;. = Punct # 40; Lățime. Înălțimea div 2 # 41; ;
ap # 91; 4 # 93;. = Punct # 40; 0. Înălțimea div 2 # 41; ;
ap # 91; 5 # 93;. = Punct # 40; Lățime div 2. Înălțime div 2 # 41; ;
ap # 91; 6 # 93;. = Punct # 40; 0. Inaltime # 41; ;
ap # 91; 7 # 93;. = Punct # 40; Lățime. înălțime # 41; ;
av # 91; 1 # 93;. = 4;
av # 91; 2 # 93;. = 3;
r. = CreatePolyPolygonRgn # 40; ap. av. 2. ÎNFĂȘURARE # 41; ;
încerca
R2. = CreateRoundRectRgn
# 40; Lățime div 4 - 20. Inaltime div 6-20.
Lățime div 4 + 20. Înălțimea div 6 + 20. 16. 16 # 41; ;
r3. = CreateRoundRectRgn
# 40; Lățime div 4 * 3 - 20. Înălțimea div 6-20.
Lățime div 4 * 3 + 20. Înălțimea div + 20. 6 16. 16 # 41; ;
r4. = CreateEllipticRgn # 40; lățime
div 10. Înălțimea div 9 * 3.
Lățime div 10 * 9. Înălțime div 9 * 4 # 41; ;
încerca
CombineRgn # 40; r. r. R2. RGN_XOR # 41; ;
CombineRgn # 40; r. r. r3. RGN_XOR # 41; ;
CombineRgn # 40; r. r. r4. RGN_XOR # 41; ;
în cele din urmă
DeleteObject # 40; r2 # 41; ;
DeleteObject # 40; r3 # 41; ;
DeleteObject # 40; r4 # 41; ;
se încheie;
SetWindowRgn # 40; Mâner. r. TRUE # 41; ;
în cele din urmă
DeleteObject # 40; r # 41; ;
se încheie;
se încheie;


Nerasmotrennoy din primul grup de funcții a fost doar ExtCreateRgn. Eu nu am de gând să-l conice, cu excepția a spune că un cuplu cu o funcție GetRegionData, poate fi util, de exemplu, pentru a salva și regiunile de încărcare pentru a / dintr-un fișier.

Regiunile sunt necesare nu numai pentru a tăia găuri în formele. Uneori, ele pot fi destul de util instrument este în stadiul său de calitate „nativ“, adică, pentru a desena pe ecran, mai degrabă forme geometrice complexe. De exemplu, pentru a afișa hărți, care reprezintă o colecție de linii poligonale construite din matrici de puncte. Crearea unei linii noi nu va fi o problemă, este timpul să dau seama cum să-l arate la utilizator.

Din desen primele două funcții pe care le avem deja vag familiare: ei nu prea, ceea ce face parametrul FillMode (ALTERNATIV / DIZOLVARE) pentru funcțiile CreatePolygonRgn și CreatePolyPolygonRgn. GetPolyFillMode devine un context pentru modul de umplere specificat și SetPolyFillMode se instalează. Doar în acest moment nu este vorba despre o regiune, dar numai pe desenul lui. Valoarea stabilită va fi semnificativ pentru toate funcțiile, regiunea încorporate, de exemplu, PaintRgn și FillRgn, în timp ce regiunea în sine va rămâne modul în care a fost creat, dar vor fi vopsite în mod diferit, în cazul în care este format din mai multe regiuni care se suprapun. Pentru regiuni simple, cum ar fi un dreptunghi sau setarea această valoare nu se schimba nimic elipse.

Deci Să ne urgent pentru a crea un fir și să tragă. Puteți face cu siguranță acest lucru în aceeași funcție, de exemplu, în OnCreate, dar atunci imaginea ar fi foarte de scurtă durată - până la forma primei redesenare. Prin urmare, vom proceda în mod diferit: declară proprietatea privată fRgn, în OnCreate inițializa în OnPaint se va afișa, în OnDestroy - distruge. Codul metodă este prezentată mai jos:

Procedura TForm1. FormCreate # 40; Expeditor. TObject # 41; ;
începe
fRgn. = CreateEllipticRgn # 40; 10. 10. 200. 200 # 41; ;
se încheie;

Procedura TForm1. FormDestroy # 40; Expeditor. TObject # 41; ;
începe
DeleteObject # 40; fRgn # 41; ;
se încheie;

Procedura TForm1. FormPaint # 40; Expeditor. TObject # 41; ;
începe
Canvas. Perie. Culoare. = ClBlack;
PaintRgn # 40; Canvas. Mâner. fRgn # 41; ;
se încheie;


Trebuie amintit că funcția de desen regiuni sunt întotdeauna de lucru cu culoare,
specificate în Canvas.Brush.Color. Chiar și desenarea unui chenar (cadru) utilizat nu este culoarea Canvas.Pen, că, în general, pare a fi mai logică și Canvas.Brush culoare.

Nimic nu sa transformat într-un cerc. Tipul de îngropare. Hai face mai vesel și în același timp la aspectul FrameRgn modul de lucru:

Procedura TForm1. FormPaint # 40; Expeditor. TObject # 41; ;
var
bmp. TBitmap;
începe
bmp. = TBitmap. Creați;
încerca
bmp. LoadFromFile # 40; 'C: WINDOWS \ albastru 16.bmp dantelă' # 41; ;
Canvas. Perie. Bitmap. = Bmp;
PaintRgn # 40; Canvas. Mâner. fRgn # 41; ;
Canvas. Perie. Culoare. = ClBlack;
FrameRgn # 40; Canvas. Mâner. fRgn. Canvas. Perie. Mâner. 2. 2 # 41; ;
în cele din urmă
Canvas. Perie. Bitmap. = Nil;
bmp. gratuit;
se încheie;
se încheie;


Am fost o astfel de imagine este aici:

Articol Lucrul cu regiunile

În ceea ce mă privește, FillRgn PaintRgn și funcțiile diferă unul de altul numai prin aceea că primul vă permite să specificați mânerul periei nu este asociat cu canvas'om curent. caracteristică discutabila din punct de vedere Delphi, ca manipula culoarea curentă a pânzei mai ușor să se spele în mod diferit decât a crea o clasă separată instanță TBrush. Aici, de fapt, totul despre desen. Este demn de remarcat faptul că, pentru a atrage regiunea nu avem nevoie să știe ce este ca. Pur și simplu trece un mâner la aceeași procedură, și se va afișa pe ecran un cerc, oval, triunghi, steaua lui David - nimic.
Funcțiile efectuate în cadrul altor nimic deosebit de interesant, în sine, nu reprezintă, și, în general, este intuitiv. rassotrim atât de puțini dintre ei.

Facem acest lucru cu un exemplu. Să nedumerit de capacitatea de a trage mouse-ul peste forma unui cerc, creat în exemplul anterior. Ceea ce avem nevoie. În primul rând, amintiți-vă în cazul în care ați început tragerea (fStartX, fStartY). În al doilea rând, steagul (fDragging), indicând faptul că utilizatorul peretskivaet într-adevăr regiunea noastră, nu doar urmarind un ecran de muscă. În al treilea rând, este necesar să se afle dacă el a subliniat în regiune, mai degrabă decât prin (PtInRegion). În al patrulea rând, este necesar să se mute regiunea ca el se mișcă mouse-ul (OffsetRgn). Aici, probabil, și toate. În acest moment, modulul va da textul integral. Singurul lucru care merită menționat - această proprietate DoubleBuffered. Acesta este expus la TRUE, ca în caz contrar există pâlpâitoare. Deci

utilizări
Windows. Mesaje. SysUtils. Variante. Clase. Grafica.
Controale. Formulare. Dialoguri;

tip
TForm1 = class # 40; TForm # 41;
Procedura de FormCreate # 40; Expeditor. TObject # 41; ;
Procedura de FormDestroy # 40; Expeditor. TObject # 41; ;
Procedura de FormPaint # 40; Expeditor. TObject # 41; ;
Procedura de FormMouseDown # 40; Expeditor. TObject; Button. TMouseButton; Shift.
TShiftState; X. Y. Integer # 41; ;
Procedura de FormMouseMove # 40; Expeditor. TObject; Shift.
TShiftState; X. Y. Integer # 41; ;
privat

fDragging. boolean;
fRgn. hRGN;
fStartX.
fStartY. întreg;
public

se încheie;

var
Form1. TForm1;

Procedura TForm1. FormCreate # 40; Expeditor. TObject # 41; ;
începe
fRgn. = CreateEllipticRgn # 40; 10. 10. 200. 200 # 41; ;
fDragging. = FALSE;
DoubleBuffered. = TRUE;
se încheie;

Procedura TForm1. FormDestroy # 40; Expeditor. TObject # 41; ;
începe
DeleteObject # 40; fRgn # 41; ;
se încheie;

Procedura TForm1. FormPaint # 40; Expeditor. TObject # 41; ;
var
bmp. TBitmap;
începe
bmp. = TBitmap. Creați;
încerca
bmp. LoadFromFile # 40; 'C: WINDOWS \ albastru 16.bmp dantelă' # 41; ;
Canvas. Perie. Bitmap. = Bmp;
PaintRgn # 40; Canvas. Mâner. fRgn # 41; ;
Canvas. Perie. Culoare. = ClBlack;
FrameRgn # 40; Canvas. Mâner. fRgn. Canvas. Perie. Mâner. 2. 2 # 41; ;
în cele din urmă
Canvas. Perie. Bitmap. = Nil;
bmp. gratuit;
se încheie;
se încheie;

Procedura TForm1. FormMouseDown # 40; Expeditor. TObject; Button.
TMouseButton; Shift. TShiftState; X. Y. Integer # 41; ;
începe
dacă # 40; Butonul = mbLeft # 41; și # 40; PtInRegion # 40; fRgn. X. Y # 41; # 41; apoi începe
fDragging. = TRUE;
fStartX. = X;
fStartY. = Y;
se încheie;
se încheie;

Procedura TForm1. FormMouseMove # 40; Expeditor. TObject; Shift.
TShiftState; X. Y. Integer # 41; ;
începe
dacă # 40; ssLeft în schimbare # 41; și apoi începe fDragging
OffsetRgn # 40; fRgn. X - fStartX. Y - fStartY # 41; ;
fStartX. = X;
fStartY. = Y;
Refresh;
se încheie;
se încheie;

Procedura TForm1. FormMouseUp # 40; Expeditor. TObject; Button. TMouseButton;
Shift. TShiftState; X. Y. Integer # 41; ;
începe
fDragging. = FALSE;
se încheie;


După cum puteți vedea, absolut nimic complex în regiunile nu. Dar oportunitățile pe care le dau destul de interesant. Figura de orice formă poate fi colorat după cum doriți (inclusiv bitmap-uri), pentru a afișa, pentru a determina dacă un punct este o parte din (X, Y), în figură, mutați-l, și mult mai mult. Pentru a completa imaginea pe care tocmai trebuie să învețe să păstreze regiunile de pe disc și citiți spate.

Salvarea și încărcarea regiunii

După cum sa menționat la început, toate datele sunt stocate într-o structură de regiune RGNDATA. Referință a fost, de asemenea, o caracteristică ce permite structura pentru a obține: GetRegionData. Această funcție are o caracteristică frumos: dacă a treia opțiune este de a trece zero, atunci se va returna cantitatea de memorie necesară pentru a salva regiune.

Procedura de SaveRegion # 40; FileName. șir # 41; ;
var
s. TStream;
dimensiune. cardinal;
date. pointer;
începe
s. = TFileStream. crea # 40; FileName. fmCreate # 41; ;
încerca
dimensiune. = GetRegionData # 40; fRgn. sizeof # 40; RGNDATA # 41;. zero # 41; ;
date. = GlobalAllocPtr # 40; GPTR. dimensiune # 41; ;
încerca
GetRegionData # 40; fRgn. dimensiune. date # 41; ;
s. scrie # 40; date ^. dimensiune # 41; ;
în cele din urmă
GlobalFreePtr # 40; date # 41; ;
se încheie;
în cele din urmă
s. gratuit;
se încheie;
se încheie;


În mod similar, puteți citi și înregistrate pe regiunea de disc:

funcţia LoadRegion # 40; FileName. șir # 41;. hRGN;
var
date. PRgnData;
s. TStream;
începe
s. = TFileStream. crea # 40; FileName. fmOpenRead # 41; ;
încerca
date. = GlobalAllocPtr # 40; GPTR. s. dimensiune # 41; ;
încerca
s. citit # 40; date ^. s. dimensiune # 41; ;
Rezultat. = ExtCreateRegion # 40; zero. s. Dimensiune. date ^ # 41; ;
în cele din urmă
GlobalFreePtr # 40; date # 41; ;
se încheie;
în cele din urmă
s. gratuit;
se încheie;
se încheie;


Aici, pe acest lucru, probabil, putem termina aceasta recenzie nu pretinde a fi exhaustivă.
Din fericire, cineva acest opus va încuraja crearea de fire ceva bun, sau doar pentru a salva câteva ore crawling pe întrebări Win32 SDK.Vse vă puteți adresa din săpun. Pentru acest ICQ: 89576939. dar cel mai bun din toate, bineînțeles, aici, în acest forum.
Mult noroc.


toate cele bune,
X77.

articole similare