Tip |
Pens are used to draw the borders of an object. The default pen is black. The code show below paints a black line from the left top corner (0, 0) to the point (100, 150) using Microsoft GDI. Las plumas son utilizadas para pintar el contorno de los objetos. La pluma por defecto es negra. El código mostrado debajo pinta una línea negra desde la esquina superior izquierda (0, 0) al punto (100, 150) usando Microsoft GDI.. |
Program.cpp |
void Hello::Window_Open(Win::Event& e) { } void Program::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); gdi.Line(0, 0, 100, 150); } |
Problem 1 |
Create a Window Application called Target to draw the figure shown. The width and height of the window are stored in the variables: this->width and this->height respectively. Cree una aplicación de ventana llamado Target para dibujar la figura mostrada. El ancho y alto de la ventana están almacenados en las variables: this->width y this->height respectivamente. |
Problem 2 |
Repeat the Target application using Win32. Repita el programa de Target usando Win32. |
Target32.cpp |
//_________________________________________________ Target32.cpp #include "stdafx.h" #include "Target32.h" int width = 0; int height = 0; ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) { MSG msg; MyRegisterClass(hInstance); if (!InitInstance(hInstance, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TARGET32)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TARGET32); wcex.lpszClassName = L"Target32"; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd = CreateWindow(L"Target32", L"Target32", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // ::MoveToEx(hdc, 0, 0, NULL); ::LineTo(hdc, width, height); // ::MoveToEx(hdc, 0, height, NULL); ::LineTo(hdc, width, 0); // ::MoveToEx(hdc, width / 2, 0, NULL); ::LineTo(hdc, width / 2, height); // ::MoveToEx(hdc, 0, height / 2, NULL); ::LineTo(hdc, width, height / 2); // EndPaint(hWnd, &ps); break; case WM_SIZE: width = LOWORD(lParam); height = HIWORD(lParam); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } |
Problem 3 |
Repeat the Target application using Direct2D. Repita el programa de Target usando Direct2D. |
TargetD.h |
#pragma once //______________________________________ TargetD.h #include "Resource.h" class TargetD: public Win::Window { public: TargetD() { } ~TargetD() { } Direct::Graphics graphics; Direct::SolidBrush brushBlack; . . . }; |
TargetD.cpp |
. . . void TargetD::Window_Open(Win::Event& e) { brushBlack.Create(graphics, 0.0f, 0.0f, 0.0f, 1.0f); // red, green, blue, alpha } void TargetD::Window_Paint(Win::Event& e) { if (graphics.BeginDraw(hWnd, width, height, 1.0f, 1.0f, 1.0f, 1.0f) == false) return; // red, green, blue, alpha graphics.SetTransform(D2D1::Matrix3x2F::Identity()); D2D1_SIZE_F size = graphics.GetSize(); graphics.DrawLine(0.0f, 0.0f, size.width, size.height, brushBlack, 1.0f); . . . graphics.EndDraw(true); } |
Tip |
If you use Class View in a Wintempla project, you will be able to understand the CG::Gdi class that encapsulates Win32 GDI library, see figure below. Si usted usa la Vista de Clases en un proyecto de Wintempla, usted podrá entender la clase CG::Gdi que encapsula la librería GDI de Win32, vea la figura de abajo. |
Problem 4 |
Create a program called Box to draw a 3D box as shown. You can use Microsoft GDI or Microsoft Direct2D. Cree un programa llamado Box para una dibujar una caja 3D como se muestra. Usted puede usar Microsoft GDI o Microsoft Direct2D. |
GDI pen styles |
GDI has severals pen styles: PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, and PS_INSIDEFRAME. In order to use a pen different to the default pen, first a pen has to be created, and then the pen must be selected. In code shown below, a solid blue pen with a width of three pixels is created. Then, the pen is selected and a line is draw. GDI tiene diversos estilos de plumas: PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, y PS_INSIDEFRAME. DASH quiere decir raya y DOT punto, así, PS_DASHDOTDOT es una línea de raya, punto, punto, raya, punto, punto, et. Para usar una pluma diferente a la de defecto, primero se crea la pluma y luego se selecciona. En el ejemplo mostrado debajo se crea una pluma solida de tres pixeles de ancho, y de color azul. Después de seleccionar la pluma azul y se dibuja una línea. |
Program.cpp |
void Program::Window_Open(Win::Event& e) { } void Program::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); CG::Pen pen(PS_SOLID, 3, RGB(0, 0, 255)); gdi.Select(pen); gdi.Line(0, 0, width, height); } |
Tip |
Be careful when pens are used to draw using printer because the printer have resolutions of at least 300 pixels per inches, the width of one pixel is extremely thin. Tengo cuidado cuando cree plumas para dibujar usando una impresora. Las impresoras tienen una resolución de más de 300 pixeles por pulgadas, un pluma de un pixel es extremadamente delgada para ser visualizada fácilmente. |
Rectangle |
A rectangle in GDI is a structure defined as RECT. This structure has four variables describing the sides of rectangle: left, top, right and bottom. The code shows below draws a rectangle using Microsoft GDI. Un rectángulo en GDI es una estructura como RECT. Esta estructura tiene cuatro variables que describen los lados del rectángulo: izquierda, arriba, derecha y abajo. El código de abajo muestra como dibujar un rectángulo en Microsoft GDI. |
Program.cpp |
void Program::Window_Open(Win::Event& e) { } void Program::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); RECT rect; rect.left = 100; rect.right = 200; rect.top = 120; rect.bottom = 220; gdi.Rectangle(rect); } |
Tip |
The code below shows some of the functions to manipulate rectangles. El código de abajo muestra algunas de las funciones para manipular rectángulos. |
Program.h |
//Moves the rectangle a number of logical units) ::OffsetRect(&rect, x, y); //Increase or decrease the size of the rectangle ::InflateRect(&rect, x, y); ::SetRectEmpty(&rect); ::IsRectEmpty(&rect); ::IntersectRect(&rectDest, &rect1, &rect2); ::UnionRect(&rectDest, &rect1, &rect2); // Determines whether a point is in a rectangle POINT pt; RECT rect; pt.x = 10; pt.y = 20; ::PtInRect(&rect, pt); // Copies the coordinates of one rectangle to another ::CopyRect // Determines whether the two specified rectangles are equal ::EqualRect //Determines the coordinates of a rectangle formed by subtracting one rectangle from another. ::SubtractRect |
IntersectRect |
It calculates the intersection of two rectangles. If the rectangles intersect, the return value is nonzero. If the rectangles do not intersect, the return value is zero. See example. Esta calcula la intersección entre dos rectángulos. Si los rectángulos se intersectan, la función regresa un valor diferente de cero. Si los rectángulos no se intersectan, la función regresa cero. Vea el ejemplo. |
Program.h |
bool Program::DoTheyIntersect(const RECT& rect1, const RECT& rect2) { RECT destination; if (::IntersectRect(&destination, &rect1, &rect2) == 0) return false; //if (::IntersectRect(NULL, &rect1, &rect2) == 0) return false; return true; } |
Problem 5 |
Create a Window Application called Room to display the figure shown below using Microsoft GDI. The lines must be spaced 100 pixels from the window borders. Cree un programa llamado Room para dibujar la figura mostrada debajo usando Microsoft GDI. Las líneas debe estar separadas 100 pixeles de los bordes de la ventana. |
Problem 6 |
Create a Window Application called RoomD to display the figure shown below using Microsoft Direct2D. The lines must be spaced 100 pixels from the window borders. The figure below shows the stroke styles in Microsoft Direct2D. Cree un programa llamado Room para dibujar la figura mostrada debajo usando Microsoft GDI. Las líneas debe estar separadas 100 pixeles de los bordes de la ventana. La figura de abajo muestra los estilos de líneas en Microsoft Direct2D. |
RoomD.h |
#pragma once //______________________________________ RoomD.h #include "Resource.h" class RoomD: public Win::Window { public: RoomD() { } ~RoomD() { } Direct::Graphics graphics; Direct::SolidBrush brushRed; Direct::StrokeStyle strokeStyle; . . . }; |
RoomD.cpp |
. . . void RoomD::Window_Open(Win::Event& e) { //________________________________________________________ 1. Red brush brushRed.Create(graphics, 1.0f, 0.0f, 0.0f, 1.0f); // red, green, blue, alpha //________________________________________________________ 2. Stoke style D2D1_STROKE_STYLE_PROPERTIES strokeProp; strokeProp.startCap = D2D1_CAP_STYLE_FLAT; strokeProp.endCap = D2D1_CAP_STYLE_FLAT; strokeProp.dashCap =D2D1_CAP_STYLE_ROUND; strokeProp.lineJoin = D2D1_LINE_JOIN_MITER; strokeProp.miterLimit = 10.0f; strokeProp.dashStyle = D2D1_DASH_STYLE_DASH; strokeProp.dashOffset = 0.0f; strokeStyle.Create(graphics, strokeProp, nullptr, 0); } void RoomD::Window_Paint(Win::Event& e) { if (graphics.BeginDraw(hWnd, width, height, 1.0f, 1.0f, 1.0f, 1.0f) == false) return; // red, green, blue, alpha graphics.SetTransform(D2D1::Matrix3x2F::Identity()); D2D1_SIZE_F size = graphics.GetSize(); //________________________________________ 1. Rectangle D2D1_RECT_F rect; rect.left = 100.0f; rect.right = size.width - 100.0f; . . . graphics.DrawRectangle(rect, brushRed, 1.0f, strokeStyle); //________________________________________ 2. Lines graphics.DrawLine(0.0f, 0.0f, 100.0f, 100.0f, brushRed, 1.0f, strokeStyle); . . . graphics.EndDraw(true); } |
Problem 7 |
Create a program called Inflate using a Window application to draw a rectangle using Microsoft GDI. The user may increase or decrease the size of the rectangle using the keys Up and Down from the keyboard. Use the events: WM_PAINT (Window_Paint) and WM_KEYDOWN (Window_Keydown). Create a RECT member variable y use la función ::InflateRect. You may use the function MyWindow.Repaint(RECT* rc, bool erase) to force Microsoft Window to call Window_Paint. The first parameter of this function may be NULL to repaint the whole window. The second parameter can be true to erase the previous window content. Cree un programa llamado Inflate usando una aplicación de ventana para dibujar un rectángulo usando GDI. El usuario puede incrementar o decrementar el tamaño del rectángulo usando las teclas de dirección Arriba y Abajo del teclado. Use los eventos: WM_PAINT (Window_Paint) y WM_KEYDOWN (Window_Keydown). Cree una variable miembro RECT y use la función ::InflateRect. Usted puede usar la función MyWindow.Repaint(RECT* rc, bool erase) para forzar a Microsoft Windows a llamar Window_Paint. El primer parámetro de esta función puede ser NULL para repintar la ventana completa. El segundo parámetro puede ser true para borrar el contenido previo de la ventana. |
Inflate.cpp |
. . . void Inflate::Window_KeyDown(Win::Event& e) { switch (e.wParam) { case VK_UP: ... case VK_DOWN: ... } } void Inflate::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); RECT intersection; ::IntersectRect(&intersection, &rect, &gdi.GetRcPaint()); if (::IsRectEmpty(&intersection) == TRUE) return; // Nothing to paint gdi.Rectangle(rect); } |
Problem 8 |
Create a Window Application called EyeSpider to display the figure shown below using Microsoft GDI. Use a total of 100 lines (50 + 50). Cree un aplicación de ventana llamada EyeSpider para dibujar la figura mostrada debajo Usando Microsoft GDI. Use un número total de 100 líneas (50 + 50). |
Tip |
The message WM_PAINT or Window_Paint event are called by the operating system when the window requires painting. In some cases, it is necessary to paint something different in the window, and to ask the operating system to call the Window_Paint function the commands this->Repaint or ::InvalidateRect must be called. Repaint takes two parameters: rcPaint and erase. To repaint the whole window rcPaint can be NULL, to erase the window use erase = true. If rcPaint is not NULL, the area described by rcPaint will be repainted. El mensaje WM_PAINT o el evento Window_Paint son llamados por el sistema operativo cuando la ventana requiere ser pintada. En algunos casos, es necesario pintar algo diferente en la ventana, y para pedirle al sistema operativo que llame la función Window_Paint se pueden usar los comandos: this->Repaint o ::InvalidateRect. Repaint toma dos parametros: rcPaint y erase. Para repintar toda la ventana rcPaint debe ser NULL, para borrar la ventana use erase = true. Si rcPaint no es NULL, el área descrita por rcPaint será repintada. |
Problem 9 |
Create a Wintempla Window application called EyeSpiderD to draw the eye spider using Microsoft 2D (observe that this project is not a DirectX application). After creating the application, open Wintempla and double click the on the GUI editor to select the events: KeyDown, Paint and Size. Cree una aplicación de ventana de Wintempla llamada EyeSpiderD para dibujar el ojo de la araña usando Microsoft 2D (observe que este proyecto no es una aplicación de DirectX). Después de crear la aplicación, abra Wintempla y haga clic doble en el editor de la GUI para seleccionar los eventos: KeyDown, Paint y Size. |
Step A |
Edit the EyeSpiderD.h file and the EyeSpiderD.cpp file as shown. Edite el archivo EyeSpiderD.h y el archivo EyeSpiderD.cpp como se muestra. |
EyeSpiderD.h |
#pragma once //______________________________________EyeSpiderD.h #include "Resource.h" class EyeSpiderD: public Win::Window { public: EyeSpiderD() { } ~EyeSpiderD() { } Direct::Graphics graphics; Direct::SolidBrush brushBlue; Direct::SolidBrush brushBlack; . . . }; |
EyeSpiderD.cpp |
. . . int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE , LPTSTR cmdLine, int cmdShow){ EyeSpiderD app; //_______________________________________________________________ Option 1. Window app.CreateMainWindow(L"EyeSpiderD", cmdShow, IDI_EyeSpiderD, NULL, (HBRUSH)::GetStockObject(NULL_BRUSH), hInstance); //_______________________________________________________________ Option 2. Full Screen (Press Escape to close) //app.CreateMainWindow(0, WS_POPUP | WS_VISIBLE, 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN), // L"FastView", SW_NORMAL, IDI_FastView, NULL, (HBRUSH)::GetStockObject(NULL_BRUSH), hInstance); return app.MessageLoop(IDC_FastView); } void EyeSpiderD::Window_Open(Win::Event& e) { brushBlack.Create(graphics, 0.0f, 0.0f, 0.0f, 1.0f); brushBlue.Create(graphics, 0.0f, 0.0f, 1.0f, 1.0f); } void EyeSpiderD::Window_Paint(Win::Event& e) { //_______________________________________________________________________________ 1. BeginDraw if (graphics.BeginDraw(hWnd, width, height, 1.0f, 1.0f, 1.0f, 1.0f) == false) return; graphics.SetTransform(D2D1::Matrix3x2F::Identity()); //_______________________________________________________________________________ 2. Lines const int lineCount = 50; D2D1_SIZE_F size = graphics.GetSize(); const float deltaX = size.width/(float)lineCount; const float deltaY = size.height/(float)lineCount; for (int i = 0; i < lineCount; i++) { graphics.DrawLine(. . .); graphics.DrawLine(. . .); } //_______________________________________________________________________________ 3. Blue rectangle D2D1_RECT_F rect = D2D1::RectF(size.width/2- 50.0f, size.height/2- 50.0f, size.width/2 + 50.0f, size.height/2 + 50.0f); graphics.FillRectangle(rect, brushBlue); //_______________________________________________________________________________ 4. EndDraw graphics.EndDraw(true); } void EyeSpiderD::Window_KeyDown(Win::Event& e) { switch (e.wParam) { case VK_ESCAPE: ::DestroyWindow(hWnd); break; } } |