Click here to Skip to main content
15,940,246 members
Articles / Multimedia / GDI

Drawing Vertical Text

Rate me:
Please Sign up or sign in to vote.
3.37/5 (15 votes)
11 Sep 20064 min read 83K   2K   25   17
An extension to the GDI DrawText

Screenshot

Introduction

Did you ever want to draw vertical text, but the output was out of proportion? Here is the answer. A simple function written in plain Win32, no MFC required. The function behaves almost exactly the same as DrawText(), with the exception that the output is vertical.

Background

This started out when I wanted to print tables. The data within my app had its own method of being displayed, so it seemed pointless to add support for tables; I instead opted to draw them. A line here and a line there, it was easy and quick. The problem came when I wanted to insert the header text. Many English words are too long to be displayed horizontally in this manner, going vertical was the most reasonable thing to do. But I found no function capable of doing this with a pleasant output. So I made my own.

Using the Code

If you know the DrawText() function, then you will have no problems using this. It is almost identical. First, include the required files into your project. Anywhere you wish to use the function, include the header #include "VertDraw.h". The prototype for the function is:

C++
int DrawVertText(    HDC hdc,            // Handle to the Device context
        LPCTSTR lpString,                // Null terminated string
        int nCount,                      // Length of string in bytes
        LPRECT lpRect,                   // Pointer to a rect
        UINT uFormat,                    // Optional drawing flags
        UINT HcharSpacing = 3,           // Pixels between characters
        UINT VcharSpacing = 5 );         // Pixels between columns

The parameters are almost identical to DrawText(), with the exception of the last two.

The string provided to lpString must be NULL terminated. The function is fully MBCS and UNICODE compatible, so don't worry about your build configuration. To divide the string into columns, just do the same as you would with any other string. Anywhere you want a new column, add a newline character '\n'.

lpRect defines the area within which the function may draw. For best results, keep this rectangle as small as possible. Passing the whole client area will only serve to use up your processor time.

In the uFormat parameter, you may pass one or more of the following values:

DV_HCENTER Center the block of text horizontally May not be used in combination with DV_RIGHT
DV_RIGHT Align the block of text to the right of the provided rectangle May not be used in combination with DV_HCENTER
DV_VCENTER Center the block of text vertically May not be used in combination with DV_BOTTOM
DV_BOTTOM Align the block of text to the bottom of the provided rectangle May not be used in combination with DV_VCENTER
DV_CENTERALL Center the text both horizontally and vertically within the provided rectangle May not be used in combination with DV_BOTTOM or DV_RIGHT
DV_TEXTTOP Align the text to the top Aligns the text relative to the longest line
DV_TEXTCENTER Center the text Aligns the text relative to the longest line
DV_TEXTBOTTOM Align the text to the bottom Aligns the text relative to the longest line
DV_TEXTJUSTIFY Justify the text to the top and bottom Aligns the text relative to the longest line
DV_CALCRECT Calculate the rectangle needed to draw; but does not draw The rectangle is calculated relative to the one you provide in the lpRect parameter
DV_DOUBLEBUFFER Forces the use of an internal double buffer By default, no double buffer is used

HcharSpacing and VcharSpacing allow you to define how far apart you would like the characters and columns to be. Passing a value of 0 will result in the characters touching each other. For best results, leave them at their default values.

How It Works

The code will kick into a loop, drawing each character to a small monochrome bitmap of screen. Each of the bits is examined in this bitmap to determine the width and height of the character. Note, any character from any language will work, provided you have the correct locale set. The dimensions of each character are stored. When this loop is complete, the character positions are calculated relative to the longest line and the character spacing entered by the user. All that's left is to call the regular DrawText() function for each of the characters, drawing them to the newly calculated positions.

Limitations and Things to Come

I think I have fixed them all in the new version.

History

  1. Version 1.0 released - August 25th, 2006
  2. Version 1.1 released - September 10th, 2006
    • Removed all the slow off-screen drawing, implemented a storage of positions in its place
    • Added the DV_TEXTJUSTIFY and DV_DOUBLEBUFFER flags
    • Corrected the problem with Italic fonts
    • Corrected the problem with the background mode

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
China China
There is not much to say really, I first started programing using my Commodore Vic 20 when I was about 10 years old. I later had to give it up due to studies and work issues. In recent years I have started playing with C++.

Comments and Discussions

 
QuestionNo explicit license given or can i assume "The Code Project Open License (CPOL)" Pin
M__n1116-Jul-15 12:25
M__n1116-Jul-15 12:25 
GeneralMy vote of 3 Pin
Romul30-May-11 1:52
Romul30-May-11 1:52 
GeneralSeveral leaks Pin
Dandy Cheung11-Jan-08 18:23
Dandy Cheung11-Jan-08 18:23 
GeneralNice solution Pin
cudjo19-Oct-07 9:01
cudjo19-Oct-07 9:01 
GeneralThis is great!! Pin
Tongle The Great11-Sep-06 21:59
Tongle The Great11-Sep-06 21:59 
GeneralRe: This is great!! Pin
Waldermort11-Sep-06 23:52
Waldermort11-Sep-06 23:52 
GeneralRe: This is great!! Pin
Tongle The Great12-Sep-06 3:29
Tongle The Great12-Sep-06 3:29 
GeneralRe: This is great!! Pin
Waldermort12-Sep-06 6:35
Waldermort12-Sep-06 6:35 
GeneralRe: This is great!! Pin
Waldermort12-Sep-06 16:19
Waldermort12-Sep-06 16:19 
GeneralRe: This is great!! Pin
Tage13-Sep-06 8:03
Tage13-Sep-06 8:03 
GeneralRe: This is great!! Pin
Waldermort14-Sep-06 1:40
Waldermort14-Sep-06 1:40 
GeneralRe: This is great!! Pin
Tage14-Sep-06 7:59
Tage14-Sep-06 7:59 
GeneralRe: This is great!! Pin
Waldermort14-Sep-06 8:15
Waldermort14-Sep-06 8:15 
GeneralRe: This is great!! Pin
Tongle The Great14-Sep-06 0:17
Tongle The Great14-Sep-06 0:17 
QuestionBut why? Pin
Mihai Nita28-Aug-06 18:19
Mihai Nita28-Aug-06 18:19 
AnswerRe: But why? Pin
Waldermort28-Aug-06 23:14
Waldermort28-Aug-06 23:14 
GeneralRe: But why? Pin
Mihai Nita29-Aug-06 19:27
Mihai Nita29-Aug-06 19:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.