Udostępnij za pośrednictwem


Kontenery grafiki

Stan grafiki — przycinanie regionu, przekształceń i ustawień jakości — jest przechowywany w obiekcie Graphics. Windows GDI+ umożliwia tymczasowe zastąpienie lub rozszerzenie części stanu w obiekcie Graphics przy użyciu kontenera. Kontener jest uruchamiany przez wywołanie metody Graphics::BeginContainer obiektu grafiki, a następnie zakończenie kontenera przez wywołanie metody Graphics::EndContainer. Między Graphics::BeginContainer i Graphics::EndContainer, wszelkie zmiany stanu wprowadzone w obiekcie grafiki należą do kontenera i nie zastępują istniejącego stanu obiektu Grafiki.

Poniższy przykład tworzy kontener w obiekcie Graphics. Światowa transformacja obiektu Graphics to tłumaczenie 200 jednostek po prawej stronie, a światowa transformacja kontenera to tłumaczenie 100 jednostek w dół.

myGraphics.TranslateTransform(200.0f, 0.0f);

myGraphicsContainer = myGraphics.BeginContainer();
   myGraphics.TranslateTransform(0.0f, 100.0f);
   myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50);
myGraphics.EndContainer(myGraphicsContainer);

myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50);

Zwróć uwagę, że w poprzednim przykładzie instrukcja myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50) między wywołaniami Graphics::BeginContainer i Graphics::EndContainer tworzy inny prostokąt niż ta sama instrukcja wykonana po wywołaniu Graphics::EndContainer. Tylko tłumaczenie poziome ma zastosowanie do wywołania DrawRectangle wykonanego poza kontenerem. Oba przekształcenia — translacja pozioma 200 jednostek i pionowe tłumaczenie 100 jednostek — mają zastosowanie do Graphics::D rawRectangle wywołania wykonanego wewnątrz kontenera. Na poniższej ilustracji przedstawiono dwa prostokąty.

zrzut ekranu okna z dwoma prostokątami rysowanymi z niebieskim piórem, jeden umieszczony nad drugim

Kontenery mogą być zagnieżdżone w kontenerach. Poniższy przykład tworzy kontener w obiekcie Graphics i innym kontenerze w pierwszym kontenerze. Światowa transformacja obiektu Graphics to tłumaczenie 100 jednostek w kierunku x i 80 jednostek w kierunku y. Światowa transformacja pierwszego kontenera jest rotacją 30 stopni. Transformacja świata drugiego kontenera to skalowanie według współczynnika 2 w kierunku x. Wywołanie metody Graphics::D rawEllipse jest wykonywane wewnątrz drugiego kontenera.

myGraphics.TranslateTransform(100.0f, 80.0f, MatrixOrderAppend);

container1 = myGraphics.BeginContainer();
   myGraphics.RotateTransform(30.0f, MatrixOrderAppend);

   container2 = myGraphics.BeginContainer();
      myGraphics.ScaleTransform(2.0f, 1.0f);
      myGraphics.DrawEllipse(&myPen, -30, -20, 60, 40);
   myGraphics.EndContainer(container2);

myGraphics.EndContainer(container1);

Poniższa ilustracja przedstawia wielokropek.

zrzut ekranu okna, który zawiera obrócony niebieski wielokropek z jego środka oznaczony jako (100,80)

Należy pamiętać, że wszystkie trzy przekształcenia dotyczą Graphics::D rawEllipse wywołania wykonanego w drugim (najbardziej wewnętrznym) kontenerze. Zwróć również uwagę na kolejność przekształceń: najpierw skaluj, a następnie obróć, a następnie przetłumacz. Najpierw zastosowano najbardziej wewnętrzną transformację, a ostatnio zastosowano transformację najbardziej zewnętrzną.

Każdą właściwość obiektugrafikimożna ustawić wewnątrz kontenera (między wywołaniami Graphics::BeginContainer i Graphics::EndContainer). Na przykład region wycinków można ustawić wewnątrz kontenera. Każdy rysunek wykonany wewnątrz kontenera będzie ograniczony do obszaru wycinkowania tego kontenera, a także będzie ograniczony do regionów wycinków dowolnego kontenera zewnętrznego i regionu wycinków grafiki samego obiektu.

Właściwości omówione do tej pory — transformacja świata i region wycinków — są łączone przez zagnieżdżone kontenery. Inne właściwości są tymczasowo zastępowane przez zagnieżdżony kontener. Jeśli na przykład ustawisz tryb wygładzania na SmoothingModeAntiAlias w kontenerze, wszystkie metody rysowania wywoływane wewnątrz tego kontenera będą używać trybu wygładzania antyalii, ale metody rysowania o nazwie after Graphics::EndContainer będą używać trybu wygładzania, który był w miejscu przed wywołaniem Graphics::BeginContainer.

Na potrzeby innego przykładu łączenia światowych przekształceń obiektu Grafiki i kontenera załóżmy, że chcesz narysować oko i umieścić je w różnych lokalizacjach na sekwencji twarzy. Poniższy przykład zwraca oko wyśrodkowane na początku układu współrzędnych.

void DrawEye(Graphics* pGraphics)
{
   GraphicsContainer eyeContainer;
   
   eyeContainer = pGraphics->BeginContainer();

      Pen myBlackPen(Color(255, 0, 0, 0));
      SolidBrush myGreenBrush(Color(255, 0, 128, 0));
      SolidBrush myBlackBrush(Color(255, 0, 0, 0));

      GraphicsPath myTopPath;
      myTopPath.AddEllipse(-30, -50, 60, 60);

      GraphicsPath myBottomPath;
      myBottomPath.AddEllipse(-30, -10, 60, 60);

      Region myTopRegion(&myTopPath);
      Region myBottomRegion(&myBottomPath);

      // Draw the outline of the eye.
      // The outline of the eye consists of two ellipses.
      // The top ellipse is clipped by the bottom ellipse, and
      // the bottom ellipse is clipped by the top ellipse.
      pGraphics->SetClip(&myTopRegion);
      pGraphics->DrawPath(&myBlackPen, &myBottomPath);
      pGraphics->SetClip(&myBottomRegion);
      pGraphics->DrawPath(&myBlackPen, &myTopPath);

      // Fill the iris.
      // The iris is clipped by the bottom ellipse.
      pGraphics->FillEllipse(&myGreenBrush, -10, -15, 20, 22);

      // Fill the pupil.
      pGraphics->FillEllipse(&myBlackBrush, -3, -7, 6, 9);

   pGraphics->EndContainer(eyeContainer);
}

Na poniższej ilustracji przedstawiono oko i osie współrzędnych.

ilustracja przedstawiająca oko składające się z trzech wielokropka: po jednym dla konturu, irysu i źrenicy

Funkcja DrawEye zdefiniowana w poprzednim przykładzie odbiera adres obiektu Graphics i natychmiast tworzy kontener w tym obiekcie Graphics. Ten kontener izoluje każdy kod, który wywołuje funkcję DrawEye z ustawień właściwości wykonanych podczas wykonywania funkcji DrawEye. Na przykład kod w funkcji DrawEye ustawia wycinek regionu obiektu Graphics, ale gdy drawEye zwraca kontrolę do procedury wywołującej, region wycinków będzie tak samo jak przed wywołaniem metody DrawEye.

Poniższy przykład rysuje trzy wielokropki (twarze), z których każda ma oko w środku.

// Draw an ellipse with center at (100, 100).
myGraphics.TranslateTransform(100.0f, 100.0f);
myGraphics.DrawEllipse(&myBlackPen, -40, -60, 80, 120);

// Draw the eye at the center of the ellipse.
DrawEye(&myGraphics);

// Draw an ellipse with center at 200, 100.
myGraphics.TranslateTransform(100.0f, 0.0f, MatrixOrderAppend);
myGraphics.DrawEllipse(&myBlackPen, -40, -60, 80, 120);

// Rotate the eye 40 degrees, and draw it 30 units above
// the center of the ellipse.
myGraphicsContainer = myGraphics.BeginContainer();
   myGraphics.RotateTransform(-40.0f);
   myGraphics.TranslateTransform(0.0f, -30.0f, MatrixOrderAppend);
   DrawEye(&myGraphics);
myGraphics.EndContainer(myGraphicsContainer);

// Draw a ellipse with center at (300.0f, 100.0f).
myGraphics.TranslateTransform(100.0f, 0.0f, MatrixOrderAppend);
myGraphics.DrawEllipse(&myBlackPen, -40, -60, 80, 120);

// Stretch and rotate the eye, and draw it at the 
// center of the ellipse.
myGraphicsContainer = myGraphics.BeginContainer();
   myGraphics.ScaleTransform(2.0f, 1.5f);
   myGraphics.RotateTransform(45.0f, MatrixOrderAppend);
   DrawEye(&myGraphics);
myGraphics.EndContainer(myGraphicsContainer);

Na poniższej ilustracji przedstawiono trzy wielokropki.

zrzut ekranu okna z trzema wielokropkami, z których każdy zawiera oko o innym rozmiarze i rotacji

W poprzednim przykładzie wszystkie wielokropki są rysowane przy użyciu wywołania DrawEllipse(&myBlackPen, -40, -60, 80, 120), który rysuje wielokropek wyśrodkowany na początku układu współrzędnych. Wielokropek jest odsunął się od lewego górnego rogu obszaru klienta, ustawiając transformację świata obiektu Graphics. Instrukcja powoduje, że pierwszy wielokropek ma być wyśrodkowany na (100, 100). Instrukcja powoduje, że środek drugiego wielokropka ma być 100 jednostek po prawej stronie środka pierwszego wielokropka. Podobnie, środek trzeciego wielokropka wynosi 100 jednostek po prawej stronie środka drugiego wielokropka.

Kontenery w poprzednim przykładzie służą do przekształcania oka względem środka danego wielokropka. Pierwsze oko jest rysowane w środku wielokropka bez przekształcenia, więc wywołanie DrawEye nie znajduje się wewnątrz kontenera. Drugie oko jest obracane o 40 stopni i rysowane 30 jednostek powyżej środka wielokropka, więc funkcja DrawEye i metody ustawiające transformację są wywoływane wewnątrz kontenera. Trzecie oko jest rozciągane i obracane i rysowane w środku wielokropka. Podobnie jak w przypadku drugiego oka, funkcja DrawEye i metody ustawiające przekształcenie są wywoływane wewnątrz kontenera.