Font |
| A font is another type of GDI object that is used to draw text. In most recent versions of Windows, the text is displayed using anti-aliasing in the borders, which hides the transition in the borders of the letters. In its most basic form, to create a font a family and a size are required. En la example shown below, a font of type Times New Roman of 12 pixels is created to draw the word Thomas. The text is displayed in black (the default text color). When the text is painted, the letters are painted using the color text and the remaining areas are painted using the default background color which is white. La fuente es otro tipo de objeto GDI que permite dibujar texto. En las versiones más recientes de Windows, el texto aparece difuminado en los bordes lo cual produce un efecto que oculta la transición en los bordes de las letras. En su forma más básica, para crear una fuente se requiere una familia de fuente y un tamaño. En el ejemplo mostrado debajo se crea una fuente del tipo Times New Roman de 12 pixeles y se dibuja el texto Hola usando el color de texto de defecto el cual es negro. Cuando se dibuja el texto, las letras se pintan usando el color del texto y las áreas restantes se pintan usando el color de fondo de texto que por defecto es blanco. |
| Problem 1 |
| Create a Window Application using Wintempla called Thomas to show some text using the TextOut API. Cree una Window Application usando Wintempla llamada Thomas para mostrar un texto usando la API TextOut. |
| Thomas.cpp |
| . . . void Thomas::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); CG::Font font; font.Create(L"Times New Roman", 120, false, false, false, false); gdi.Select(font); gdi.TextOut(0, 0, L"Tomas"); } |

| Problem 2 |
| Create a Win32 Window Application called Thomas32 (do not use Wintempla). Cree una Window Application llamada Thomas32 (No use Wintempla). |
| Thomas32 .cpp |
| //________________________________________ Thomas32 .cpp #include "stdafx.h" #include "Thomas32 .h" ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); const wchar_t * windowClass = L"Thomas32 "; 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_THOMAS32)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_THOMAS32); wcex.lpszClassName = windowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd = CreateWindow(windowClass, windowClass, 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); { //________________________________________________ Create Font LOGFONT logfont; logfont.lfHeight = -120; logfont.lfWidth = 0; logfont.lfEscapement = 0; logfont.lfOrientation = 0; logfont.lfWeight = FW_NORMAL; logfont.lfItalic = FALSE; logfont.lfUnderline = FALSE; logfont.lfStrikeOut = FALSE; logfont.lfCharSet = DEFAULT_CHARSET; logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; logfont.lfQuality = DEFAULT_QUALITY; logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE; _snwprintf_s(logfont.lfFaceName, 32, _TRUNCATE, L"Times New Roman"); HFONT font = ::CreateFontIndirect(&logfont); //____________________________________________ Select Font and Text Out HFONT previousFont = (HFONT)::SelectObject(hdc, font); ::TextOut(hdc, 0, 0, L"Tomas", wcslen(L"Tomas")); //____________________________________________ Clean Up ::SelectObject(hdc, previousFont); ::DeleteObject(font); } EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } |
| Tip |
| It is possible to change the text color and the back color as shown in the example. The text is painted in green, and the background is painted in another shade of green. Es posible cambiar el color del texto y el color de fondo como se muestra en el ejemplo. El texto se pinta en verde y el fondo se pinta en gris diluido con un poco de verde. |
| Problem 3 |
| Modify the code of Problem 1 (the Thomas project) as shown. Modifique el código del Problema 1 (el projecto Thomas) como se muestra. |
| Thomas.cpp |
| . . . void Thomas::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); CG::Font font; font.Create(L"Times New Roman", 120, false, false, false, false); gdi.Select(font); gdi.SetTextColor(RGB(0, 140, 0)); gdi.SetBkColor(RGB(140, 180, 140)); gdi.TextOut(0, 0, L"Tomas"); } |

| Tip |
| The following code shows the Win32 version of the previous code. Note how after painting we must restore the Device Context to its original state. El código siguiente muestra la versión Win32 del código previo. Observe como después de pintar se debe restaurar el Contexto al Dispositivo a su estado original. |
| Program32.cpp |
| //________________________________________ Program32.cpp #include "stdafx.h" #include "Program32.h" ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); const wchar_t * windowClass = L"Program32"; 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_PROGRAM32)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PROGRAM32); wcex.lpszClassName = windowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd = CreateWindow(windowClass, windowClass, 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); { //________________________________________________ Create Font LOGFONT logfont; logfont.lfHeight = -120; logfont.lfWidth = 0; logfont.lfEscapement = 0; logfont.lfOrientation = 0; logfont.lfWeight = FW_NORMAL; logfont.lfItalic = FALSE; logfont.lfUnderline = FALSE; logfont.lfStrikeOut = FALSE; logfont.lfCharSet = DEFAULT_CHARSET; logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; logfont.lfQuality = DEFAULT_QUALITY; logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE; _snwprintf_s(logfont.lfFaceName, 32, _TRUNCATE, L"Times New Roman"); HFONT font = ::CreateFontIndirect(&logfont); //____________________________________________ Select Font and Text Out HFONT previousFont = (HFONT)::SelectObject(hdc, font); COLORREF previousTextColor = ::SetTextColor(hdc, RGB(0, 140, 0)); COLORREF previousBackColor = ::SetBkColor(hdc, RGB(140, 180, 140)); ::TextOut(hdc, 0, 0, L"Tomas", wcslen(L"Tomas")); //____________________________________________ Clean Up ::SelectObject(hdc, previousFont); ::SetTextColor(hdc, previousTextColor); ::SetBkColor(hdc, previousBackColor); ::DeleteObject(font); } EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } |
GetTextExtentPoint32 |
| This function takes a text variable and a variable of SIZE data type to get the width and height of a given text, as shown in the following code. Esta función toma una variable de texto y una variable del tipo SIZE para obtener el ancho y el alto de un texto dado, como se muestra en el código de abajo. |
| Program.cpp |
| void Program::Window_Paint(Win::Event& e) { . . . //_____________________________ Method 1 SIZE size; wstring text = L"Hello"; gdi.GetTextExtentPoint32(text.c_str(), size); //_____________________________ Method 2 SIZE size; wchar_t *text = L"Hello"; gdi.GetTextExtentPoint32(text, size); //_____________________________ Method 3 SIZE size; wstring text = L"Hello"; ::GetTextExtentPoint32(hdc, text.c_str(), size); //_____________________________ Method 4 SIZE size; wchar_t *text = L"Hello"; ::GetTextExtentPoint32(hdc, text, size); } |
Centering Text |
| The figure below illustrates how to use size.cx and size.cy to center some text inside an area. La figura de abajo ilustra cómo usar size.cx y size.cy para centrar un texto dentro de una área. |

Text Align and TextOut |
| The function gdi.TextOut is the most basic function to draw text, it takes the coordinates of x and y where the text will be draw. GDI supports the function SetTextAlign to control text alignment; valid values are: TA_CENTER, TA_LEFT, TA_RIGHT, TA_BASELINE, TA_BOTTOM (tmDescent) , TA_TOP (tmAscent) and TA_UPDATETC. La función gdi.TextOut es la función más básica para dibujar texto, ésta toma las coordenadas de x y y donde el texto será dibujado. La GDI tiene la función SetTextAlign para controlar la alineación del texto; los valores válidos son: TA_CENTER, TA_LEFT, TA_RIGHT, TA_BASELINE, TA_BOTTOM (tmDescent), TA_TOP (tmAscent) y TA_UPDATETC. |
| Problem 4 |
| Modify the code of Problem 1 (the Thomas project) as shown. Modifique el código del Problema 1 (el projecto Thomas) como se muestra. |
| Thomas.cpp |
| . . . void Thomas::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); CG::Font font; font.Create(L"Times New Roman", 60, false, false, false, false); gdi.Select(font); //___________________________________ 1. Left Top/Red gdi.SetBkColor(RGB(255, 0, 0)); gdi.SetTextAlign(TA_LEFT | TA_TOP); gdi.TextOut(0, 0, L"1 Thomas"); //___________________________________ 2. Center Top/Yellow gdi.SetBkColor(RGB(255, 255, 0)); gdi.SetTextAlign(TA_CENTER | TA_TOP); gdi.TextOut(width/2, 0, L"2 Thomas"); //___________________________________ 3. Right Top/Orange gdi.SetBkColor(RGB(255, 100, 0)); gdi.SetTextAlign(TA_RIGHT | TA_TOP); gdi.TextOut(width, 0, L"3 Thomas"); //___________________________________ 4. Left Bottom/Blue gdi.SetBkColor(RGB(0, 0, 255)); gdi.SetTextAlign(TA_LEFT | TA_BOTTOM); gdi.TextOut(0, height, L"4 Thomas"); //___________________________________ 5. Center Base Line/Cyan gdi.SetBkColor(RGB(0, 255, 255)); gdi.SetTextAlign(TA_CENTER | TA_BASELINE); gdi.TextOut(width/2, height, L"5 Thomas"); //___________________________________ 6. Right Bottom/Green gdi.SetBkColor(RGB(0, 255, 0)); gdi.SetTextAlign(TA_RIGHT | TA_BOTTOM); gdi.TextOut(width, height, L"6 Thomas"); //___________________________________ 7. Center/Purple gdi.SetBkColor(RGB(255, 0, 255)); gdi.SetTextAlign(TA_LEFT | TA_TOP); SIZE size; gdi.GetTextExtentPoint32(L"7 Thomas", size); gdi.TextOut((width-size.cx+1)/2, (height-size.cy+1)/2, L"7 Tomas"); } |

TEXTMETRIC |
| This structure stores several text metrics than are necessary drawing text using GDI. The following figure illustrates the meaning of some of the variables in TEXTMETRIC. The code shows how to get a TEXTMETRIC variable. Esta estructura almacena varias métricas del texto que son necesarias para dibujar texto usando GDI. La figura siguiente ilustra el significado de algunas de las variables de TEXTMETRIC. El código muestra cómo conseguir una variable TEXTMETRIC. |

| Program.cpp |
| //_______________________________________________________ METHOD 1 void Program::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); TEXTMETRIC tm; gdi.GetTextMetrics(tm); const int descent = tm.tmDescent; } //_______________________________________________________ METHOD 2 void Program::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); TEXTMETRIC tm; ::GetTextMetrics(gdi.GetHDC(), &tm); const int descent = tm.tmDescent; } |
OUTLINETEXTMETRIC |
| When drawing advanced text, the OUTLINETEXTMETRIC structure provides detailed text metrics as shown in the figure below. OUTLINETEXTMETRIC is available only for True Type fonts as shown in the example for an Arial font. Cuando se dibuja texto avanzado, la estructura OUTLINETEXTMETRIC proporciona métricas de texto detalladas como se muestra en la figura de abajo. OUTLINETEXTMETRIC está disponible solamente para fuentes True Type como se muestra en el ejemplo para la fuente Arial. |

| Program.cpp |
| void Program::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); CG::Font font(L"Arial", 12); gdi.Select(font); CG::OutlineTextMetrics metric; gdi.GetOutlineTextMetrics(metric); const int ascent = metric.tm->otmAscent; } |
| Tip |
| In some cases, it is desired that the text merges perfectly with the background. In these cases, the function gdi.SetBkMode can be used to turn on the transparent mode as illustrated in the following problem. En algunos casos, se desea que el texto se combine en forma perfecta con el fondo. En estos casos, la función gdi.SetBkMode puede ser usada para activar el modo transparente como se ilustra en el siguiente problema. |
| Problem 5 |
| Create a Window Application called Chile to paint the flag of Chile covering the whole window. Use a Wingdings font to draw the star as shown in the Character Map. To draw the star in the center of the blue rectangle located at the top left corner, the values of left, top, right, and bottom of the variable RECT must be set. Cree una aplicación de ventana llamado Chile para dibujar la bandera de Chile en toda la ventana. Use una fuente Wingdings para dibujar la estrella como se muestra en el mapa de caracteres. Para dibujar la estrella en el centro rectángulo superior izquierdo de color azul se deben llenar los valores de: left, top, right y bottom de la variable RECT. |


| Chile.cpp |
| . . . void Chile::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); . . . //______________________________________ Blue rectangle . . . //______________________________________ Red rectangle . . . //______________________________________ Paint the Star CG::Font font(L"Wingdings", . . .); . . . gdi.SetBkMode(true); wstring text; text = (wchar_t)0x2605; // SIZE size; gdi.GetTextExtentPoint32(text.c_str(), size); gdi.TextOut(. . ., text); } |
Text Layout and Text Format |
| Direct Write provides two interfaces for drawing text: Text Layout (IDWriteTextLayout) and Text Format (IDWriteTextFormat). Text Layout allows you to draw text that combines bold, italic, underlined and normal text. Text Format, on the other hand, draws text where all the text is of the same font type and style. The other difference is that in Text Layout the text is provided at the time of creating the Text Layout interface, while in Text Format the text is provided at the time of drawing the text. Direct Write proporciona dos interfaces para dibujar texto: Text Layout (IDWriteTextLayout) y Text Format (IDWriteTextFormat). Text Layout permite dibujar texto qué combina texto en negrita, cursiva, subrayado y normal. En cambio, Text Format dibuja texto dónde todo el texto es de un mismo tipo y estilo de fuente. La otra diferencia es qué en Text Layout el texto se proporciona en el momento de crear la interface Text Layout, mientras que en Text Format el texto se proporciona en el momento de dibujar el texto. |
| Tip |
| Text Layout (IDWriteTextLayout) and Text Format (IDWriteTextFormat) allow you to draw multilne text. Both interfaces format some text so that it can be displayed inside a specified box. You should use Text Layout (IDWriteTextLayout) when the text to be displayed does not change frequently. Text Layout (IDWriteTextLayout) y Text Format (IDWriteTextFormat) permiten dibujar texto en múltiples líneas. Ambas interfaces dan formato al texto para que éste pueda ser mostrado dentro de una caja específica. Usted debe de utilizar Text Layout (IDWriteTextLayout) cuándo el texto a ser mostrado no cambia con frecuencia. |
| Problem 6 |
| Create a Window Application called ChileD to paint the flag of Chile using Direct2D and DirectWrite. Cree una aplicación de ventana llamado ChileD para dibujar la bandera de Chile usando Direct2D y DirectWrite. |

| ChileD.h |
| #pragma once //______________________________________ ChileD.h #include "Resource.h" class ChileD: public Win::Window { public: ChileD() { } ~ChileD() { } Direct::Graphics graphics; Direct::SolidBrush brushBlue; Direct::SolidBrush brushRed; Direct::SolidBrush brushWhite; Direct::TextFormat textFormat; FLOAT blueWidth = 0.0f; FLOAT blueHeight = 0.0f; . . . }; |
| ChileD.cpp |
| . . . void ChileD::Window_Open(Win::Event& e) { brushBlue.Create(. . .); // red, green, blue, alpha brushRed.Create(. . .); // red, green, blue, alpha brushWhite.Create(. . .); // red, green, blue, alpha textFormat.Create(graphics, L"Wingdings", false, false, 72.0f, L""); } void ChileD::Window_Paint(Win::Event& e) { . . . //____________________________________ 1. Blue rectangle . . . //____________________________________ 2. Red rectangle . . . //____________________________________ 3. Paint the Star . . . wstring text; text = (wchar_t)0xAB; graphics.DrawTextX(text, textFormat, rect, brushWhite); // graphics.EndDraw(true); } void ChileD::Window_Size(Win::Event& e) { graphics.Resize(hWnd, width, height); D2D1_SIZE_F size = graphics.GetSize(); blueWidth = 0.35f * size.width; blueHeight = size.height / 2.0f; textFormat.Create(graphics, L"Wingdings", false, false, (blueWidth < blueHeight) ? blueWidth : blueHeight, L""); textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); } |
| Problem 7 |
| Create a Window Application called UnitedStates to paint the flag of the United States covering the whole window. Cree una aplicación de ventana llamado UnitedStates para dibujar la bandera de los Estados Unidos en toda la ventana. |


| Problem 8 |
| Create a Window Application called UnitedStatesD to paint the flag of the United States covering the whole window. Use Direct2D and DirectWrite. Cree una aplicación de ventana llamado UnitedStatesD para dibujar la bandera de los Estados Unidos en toda la ventana. Use Direct2D y DirectWrite. |

| Problem 9 |
| Create a Window Application called USFlag to change the contrast of the flag of the United States every time is click with the mouse. First, the flag appears in normal contrast. When the user clicks the windows, the contrast of the flag is reduced. When the user clicks again the window, the contrast returns to normal. Cree una aplicación de ventana llamada USFlag para cambiar el contraste de la bandera de los Estados Unidos cada vez que se hace clic con el ratón. Primero, la bandera aparece con contraste normal. Cuando el usuario hace clic en la ventana, el contraste de la bandera se reduce. Cuando el usuario vuelve a hacer clic en la ventana, el contraste regresa a su forma normal. |


| USFlag.h |
| #pragma once //______________________________________ USFlag.h #include "resource.h" class USFlag: public Win::Window { public: USFlag() { isLowContrast = false; } ~USFlag() { } bool isLowContrast; const wchar_t * GetClassName(){return L"USFLAG";} protected: . . . }; |
| USFlag.cpp |
| void USFlag::Window_Open(Win::Event& e) { } void USFlag::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); . . . } void USFlag::Window_LButtonDown(Win::Event& e) { if (isLowContrast == true) { isLowContrast = false; } else { isLowContrast = true; } this->Repaint(NULL, true); } |
| Tip |
| Some functions are directly called by Microsoft Windows to notify about events in the computer. Some of these functions are: Window_Open, Window_Close, Window_Timer. These functions can be manually created or use Wintempla. If you Wintempla, open Wintempla, then make double click in the window and select the respective event). Algunas funciones son llamadas directamente por Microsoft Windows para notificar sobre eventos en la computadora. Algunas de estas funciones son: Window_Open, Window_Close, Window_Timer. Estas funciones pueden ser creadas manualmente o usando Wintempla. Si se usa Wintempla, abra Wintempla, entonces haga doble clic en la ventana y seleccione el evento respectivo). |
| Problem 10 |
| Create a Window Application called Clock to show a digital clock. When the program begins, the timer 1 is set to every 1000 milliseconds. Thus, the function Window_Timer is called every second, forcing the window to repaint by calling Window_Paint. When the user closes the program, the timer is killed and the program closed. Each time the window is painted, the variable now of type Sys::Time has the current time. The time is then formatted as text and shown to the user. Cree una aplicación de ventana llamada Clock para mostrar un reloj digital. Cuando el programa empieza, el timer 1 es fijado en cada 1000 milisegundos. Así, la función Window_Timer es llamada cada segundo, forzando a la ventana a repintarse llamando Window_Paint. Cuando el usuario cierra el programa, el timer se detiene y el programa se cierra. Cada vez que la ventana se pinta, la variable now del tipo Sys::Time tiene el tiempo actual. El valor de tiempo se formatea como texto y muestra al usuario. |

| Clock.cpp |
| void Clock::Window_Open(Win::Event& e) { this->timer.Set(1, 1000); } void Clock::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); CG::Font font(L"Times New Roman", 32); gdi.Select(font); Sys::Time now; RECT rc; rc.left = 0; rc.right = width; rc.top = 0; rc.bottom = height; // wstring text; Sys::Format(text, L"%02d:%02d:%02d", now.wHour, now.wMinute, now.wSecond); gdi.TextOut(rc, text); } void Clock::Window_Timer(Win::Event& e) { this->Repaint(NULL, true); } void Clock::Window_Close(Win::Event& e) { this->timer.Kill(1); e.returnValue = ::DefWindowProc(hWnd, e.uMsg, e.wParam, e.lParam); } |
| Problem 11 |
| Create a Window Application called GreenClock to display the hour with green numbers and black background. Cree una aplicación de ventana llamado GreenClock para mostrar la hora con números verdes y fondo negro. |

| Tip |
| The high of character is approximately the double of its width. Additionally, the 14.5 % of the high of a font is reserved to accents in uppercase characters; in some applications it is recommended to remove this space so that the text may be displayed vertically centered. La altura de una letra es aproximadamente el doble que su ancho. Adicionalmente, el 14.5% del alto de la fuente se reserva para colocar acentos en las letras mayúsculas; en algunas aplicaciones es conveniente remover este espacio para que el texto aparezca en forma centrada verticalmente. |
| Problem 12 |
| Create a Window Application called ParImpar to draw the list of numbers as shown below. A structure TEXTMETRIC provides information about a font. In the program, this structure is used to compute the space between two lines of text. Cree una aplicación de ventana llamado ParImpar para dibujar la lista de números como se muestra debajo. Una estructura TEXTMETRIC proporciona información acerca de una fuente. En el programa, esta estructura es usada para calcular el espacio entre dos líneas de texto. |


| ParImpar.cpp |
| void ParImpar::Window_Open(Win::Event& e) { } void ParImpar::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); TEXTMETRIC tm; gdi.GetTextMetrics(tm); wchar_t tmp[32]; int y = 0; int i = 0; //_______________________________________________________________ 1. Left gdi.SetTextAlign(TA_TOP | TA_LEFT); for(. . .) { _snwprintf_s. . . gdi.TextOut(. . ., . . ., tmp); y += tm.tmHeight + tm.tmInternalLeading; } //_______________________________________________________________ 2. Right y = 0; gdi.SetTextAlign(TA_TOP | TA_RIGHT); for(. . .) { _snwprintf_s. . . gdi.TextOut(. . ., . . ., tmp); y += tm.tmHeight + tm.tmInternalLeading; } } |
| Problem 13 |
| Create a Window Application called ParImparD to draw the list of numbers as shown below. Use Direct2D and DirectWrite. Cree una aplicación de ventana llamado ParImparD para dibujar la lista de números como se muestra debajo. Use Direct2D y DirectWrite. |

| ParImparD.h |
| #pragma once //______________________________________ ParImparD.h #include "Resource.h" class ParImparD: public Win::Window { public: ParImparD() { } ~ParImparD() { } Direct::Graphics graphics; Direct::SolidBrush brushBlack; Direct::TextFormat textFormat; wstring textLeft; wstring textRight; . . . }; |
| ParImparD.cpp |
| . . . void ParImparD::Window_Open(Win::Event& e) { brushBlack.Create(graphics, 0.0f, 0.0f, 0.0f, 1.0f); // red, green, blue, alpha textFormat.Create(graphics, L"Times New Roman", false, false, 18.0f, L""); graphics.Resize(hWnd, width, height); wchar_t tmp[32]; int i = 0; //_______________________________________________________________ 1. Left for (. . .) { _snwprintf_s(tmp, 32, _TRUNCATE, L"%d\r\n", i); textLeft += tmp; } //_______________________________________________________________ 2. Right for (. . .) { . . . textRight += tmp; } } void ParImparD::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(); D2D1_RECT_F rect; rect.left = 0.0f; rect.top = 0.0f; rect.right = size.width; rect.bottom = size.height; //_______________________________________________________________ 1. Left textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING); textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR); graphics.DrawTextX(textLeft, textFormat, rect, brushBlack); //_______________________________________________________________ 2. Right textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING); graphics.DrawTextX(textRight, textFormat, rect, brushBlack); graphics.EndDraw(true); } |
DrawText and DrawParagraph |
| DrawText and DrawParagraph draw text as the function TextOut does, however, they have some advanced options to draw text using GDI. DrawText y DrawParagraph dibujan texto como la función TextOut lo hace, sin embargo, estas tienen otras opciones avanzadas para dibujar texto usando GDI. |
| Problem 14 |
| Create a Window Application called ColorCode to draw the text as shown. Cree una aplicación de ventana llamado ColorCode para dibujar el texto como se muestra. |

| ColorCode.h |
| #pragma once //______________________________________ ColorCode.h #include "Resource.h" class ColorCode: public Win::Window { public: ColorCode() { } ~ColorCode() { } list<Sys::ColorText> text; . . . }; |
| ColorCode.cpp |
| . . . void ColorCode::Window_Open(Win::Event& e) { Sys::ColorText ct; ct.text = L"int"; ct.color =RGB(0, 0, 255); text.push_back(ct); // ct.text = L" numStudents = "; ct.color =RGB(0, 0, 0); text.push_back(ct); // ct.text = L"20"; ct.color =RGB(255, 0, 0); text.push_back(ct); // ct.text = L";"; ct.color =RGB(0, 0, 0); text.push_back(ct); } void ColorCode::Window_Paint(Win::Event& e) { CG::Gdi gdi(hWnd, true, false); SIZE sizeOccupied; gdi.ColorTextOut(0, 0, text, sizeOccupied); } |