Q: How do I display text filled and in shape of a region?
A: Displaying text as non-rectangular is a bit of tricky. Here, I will explain how the text can be displayed as deformed to take the shape of a region. I am presenting the code in the form of a function (I have used the familiar name 'DrawText()' for this function), whose parameters are handles to the device context (as 'HDC'), the string to be displayed (as 'LPSTR') and the handle to the region (as 'HRGN').
The method used here is quite simple. What I did is to write the string in a memory device context and scale it to the region according to its minimum and maximum 'Y' value at each 'X' position. Sample comments are given at each steps.Code:void DrawText(HDC hdc, LPSTR lpstring, HRGN hrgn) { // Creates a memory device context HDC hMemDC = CreateCompatibleDC(hdc); if (hMemDC) { // Memory device context is created successfully // Gets the width and height of the string DWORD Size = GetTabbedTextExtent(hMemDC, lpstring, strlen(lpstring), 0, NULL); int Width = LOWORD(Size); int Height = HIWORD(Size); // Creates bitmap and selects to the memory device context HBITMAP hBitmap = CreateCompatibleBitmap(hdc, Width, Height); HBITMAP hOldBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap); // Paints memory device context in white RECT Rect; SetRect(&Rect, 0, 0, Width, Height); FillRect(hMemDC, &Rect, (HBRUSH) GetStockObject(WHITE_BRUSH)); // Sets color and background mode COLORREF Black = RGB(0, 0, 0); SetTextColor(hMemDC, Black); SetBkMode(hMemDC, TRANSPARENT); // Displays string in memory device context TextOut(hMemDC, 0, 0, lpstring, strlen(lpstring)); // Finds the text occupying area bounded by X0, Y0, X1, Y1 int X0 = -1; int X1 = -1; int Y0 = -1; int Y1 = -1; for (int iX = 0; iX <= Width; iX++) for (int iY = 0; iY <= Height; iY++) if (GetPixel(hMemDC, iX, iY) == Black) { X0 = X0 >= 0 ? (iX < X0 ? iX : X0) : iX; Y0 = Y0 >= 0 ? (iY < Y0 ? iY : Y0) : iY; X1 = X1 >= 0 ? (iX > X1 ? iX : X1) : iX; Y1 = Y1 >= 0 ? (iY > Y1 ? iY : Y1) : iY; } // Computes bounds of region GetRgnBox(hrgn, &Rect); // Gets current text color of device context COLORREF Color = GetTextColor(hdc); // Scans the region in X direction for (iX = Rect.left; iX <= Rect.right; iX++) { int X = X0 + (X1 - X0) * (iX - Rect.left) / (Rect.right - Rect.left); int YMin = -1, YMax = -1; // Computes bounds of Y for corresponding iX for (int iY = Rect.top; iY <= Rect.bottom; iY++) if (PtInRegion(hrgn, iX, iY)) { YMin = YMin >= 0 ? (iY < YMin ? iY : YMin) : iY; YMax = YMax >= 0 ? (iY > YMax ? iY : YMax) : iY; } // Scales string image for current Y limits if (YMax != YMin) for (iY = YMin; iY <= YMax; iY++) { int Y = Y0 + (Y1 - Y0) * (iY - YMin) / (YMax - YMin); if (GetPixel(hMemDC, X, Y) == Black) SetPixel(hdc, iX, iY, Color); } } // Deselects bitmap and deletes device context SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); } }
Here is a screen shot of what I got. Note that the region is shaded in gray for illustration.


Reply With Quote
Bookmarks