[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

Print a rotated text centered in a given rectangle

Posted on 2004-10-27
8
Medium Priority
?
393 Views
Last Modified: 2008-01-09
I'm trying to print some rotated text centered in a specific area of the printer form using windows API. This is the code I've written for this:
        '*************** create font *****************
        lf.lfHeight = -MulDiv(FontSize, GetDeviceCaps(hPrintDc, LOGPIXELSY), 72)
        'lf.lfWidth = 0
        lf.lfEscapement = Rotation * 10
        lf.lfOrientation = Rotation * 10
        If FontBold = 1 Then
            lf.lfWeight = FW_BOLD
        Else
            lf.lfWeight = FW_NORMAL
        End If
        lf.lfItalic = CByte(FontItal)
        lf.lfUnderline = CByte(FontUnder)
        lf.lfStrikeOut = CByte(FontStrk)
        lfCharSet = DEFAULT_CHARSET
        lfOutPrecision = OUT_DEFAULT_PRECIS
        lf.lfClipPrecision = CLIP_LH_ANGLES
        lf.lfQuality = DEFAULT_QUALITY
        lf.lfPitchAndFamily = DEFAULT_PITCH Or FF_DONTCARE
        lf.lfFaceName = FontName
        hFont = CreateFontIndirect(lf)  'Create the rotated font
        hOldfont = SelectObject(hPrintDc, hFont)
        OutAlign = DT_TOP
        If TextAlign = 0 Then
            OutAlign = OutAlign + DT_LEFT
        ElseIf TextAlign = 1 Then
            OutAlign = OutAlign + DT_RIGHT
        Else
            OutAlign = OutAlign + DT_CENTER
        End If
        If TextWordW = 1 Then
            OutAlign = OutAlign + DT_WORDBREAK
        End If
        '******** area for printing *************
        'note that there is a 270degrees rotation so "left/right" are inverted
        TextRect.Left = 2414
        TextRect.Top = 1386
        TextRect.Right = 2198
        TextRect.Bottom = 2883
        Result = SetTextColor(hPrintDc, ForeColor)
        Result = DrawText(hPrintDc, TextString, Len(TextString), TextRect, OutAlign)
        Result = SelectObject(hPrintDc, hOldfont)
        Result = DeleteObject(hFont)    'Delete the font object

Well, if I use DT_LEFT alignment it works fine but, if I use DT_RIGHT or DT_CENTER alignment it doesn't work. I can´t see any text.

Pls, can anybody tell me what is going wrong?

Thanks
    Leo
0
Comment
Question by:leorocha
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 2
8 Comments
 
LVL 3

Expert Comment

by:Egore
ID: 12427564
What is the return value from DrawText when the text does not display?  If it's 0, then we know that we're dealing with invalid parameters.
0
 

Author Comment

by:leorocha
ID: 12427873
Return value=211
Text to print="817439225"
Font=Arial,Normal,11
 
0
 
LVL 3

Expert Comment

by:Egore
ID: 12428003
My next thought would be to swap Left and Right values back to normal and try a 45 degree rotation.  See if the issue is with all rotation, or just with a 270 degree rotation.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:Egore
ID: 12428257
The following code is the quick-and-dirty code that I'm using to test with.  I think I see your problem.  Please try out this code in a new project.  I think I got all of the variables matched up properly and I'm using a "DrawFocusRect" routine to display the clipping rectangle.  You can use this code with the inverted Left and Right values as well, but "DrawFocusRect" doesn't accept them.

After running this with a few iterations, it appears that DT_LEFT, DT_RIGHT, and DT_CENTER have no idea that your text is rotated.  Therefore, when you do DT_RIGHT (in my code example) you will get vertical text that runs properly north/south, but that is the same distance from the right edge of the draw area as if it was never rotated.  You can see the same thing with DT_CENTER.  The text displays way to the left.  And, as you already know, DT_LEFT displays to the left of the display area and is therefore never drawn on-screen.

In a few minutes I'll post what I believe to be a solution.  I need to get the kinks worked out.  You can ignore my previous post.

----------------------------------

Option Explicit

Private Const DT_TOP = &H0
Private Const FW_NORMAL = 400
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function DrawText Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long
Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Const DEFAULT_CHARSET = 1
Private Const OUT_DEFAULT_PRECIS = 0
Private Const CLIP_LH_ANGLES = 16
Private Const DEFAULT_QUALITY = 0
Private Const DEFAULT_PITCH = 0
Private Const FF_DONTCARE = 0
Private Const DT_LEFT = &H0
Private Const DT_RIGHT = &H2
Private Const DT_CENTER = &H1
Private Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
Private Const LF_FACESIZE = 32
Private Type LOGFONT
        lfHeight As Long
        lfWidth As Long
        lfEscapement As Long
        lfOrientation As Long
        lfWeight As Long
        lfItalic As Byte
        lfUnderline As Byte
        lfStrikeOut As Byte
        lfCharSet As Byte
        lfOutPrecision As Byte
        lfClipPrecision As Byte
        lfQuality As Byte
        lfPitchAndFamily As Byte
        lfFaceName As String * LF_FACESIZE
End Type
Private Const LOGPIXELSY = 90
Private Declare Function DrawFocusRect Lib "user32" (ByVal hdc As Long, lpRect As RECT) As Long

Private Sub Form_Click()

    Dim hdc As Long
    Dim TextRect As RECT
    Dim Result As Long
    Dim TextString As String
    Dim hFont As Long
    Dim hOldFont As Long
    Dim lf As LOGFONT
    Dim Rotation As Integer
    Dim OutAlign As Long
    Dim TextAlign As Integer
    Dim FontName As String
   
    hdc = GetDC(Me.hwnd)
    Rotation = 270
    TextAlign = 1
    FontName = "Arial"
    TextString = "817439225"
   
    '*************** create font *****************
    lf.lfHeight = 0
    lf.lfEscapement = Rotation * 10
    lf.lfOrientation = Rotation * 10
    lf.lfWeight = FW_NORMAL
    lf.lfItalic = CByte(False)
    lf.lfUnderline = CByte(False)
    lf.lfStrikeOut = CByte(False)
    lf.lfCharSet = DEFAULT_CHARSET
    lf.lfOutPrecision = OUT_DEFAULT_PRECIS
    lf.lfClipPrecision = CLIP_LH_ANGLES
    lf.lfQuality = DEFAULT_QUALITY
    lf.lfPitchAndFamily = DEFAULT_PITCH Or FF_DONTCARE
    lf.lfFaceName = FontName
    hFont = CreateFontIndirect(lf)  'Create the rotated font
    hOldFont = SelectObject(hdc, hFont)
    OutAlign = DT_TOP
    If TextAlign = 0 Then
        OutAlign = OutAlign + DT_LEFT
    ElseIf TextAlign = 1 Then
        OutAlign = OutAlign + DT_RIGHT
    Else
        OutAlign = OutAlign + DT_CENTER
    End If
    '******** area for printing *************
    'note that there is a 270degrees rotation so "left/right" are inverted
    TextRect.Left = 50
    TextRect.Top = 50
    TextRect.Right = 500
    TextRect.Bottom = 500
    Result = DrawText(hdc, TextString, Len(TextString), TextRect, OutAlign)
    Result = DrawFocusRect(hdc, TextRect)
    Result = SelectObject(hdc, hOldFont)
    Result = DeleteObject(hFont)    'Delete the font object

End Sub

Private Sub Form_Load()

    Me.ScaleMode = vbPixels
    Me.WindowState = vbMaximized

End Sub
0
 
LVL 3

Expert Comment

by:Egore
ID: 12428579
I would highly suggest changing "DrawText" to "TextOut" unless you absolutely need the DT_WORDBREAK functionality.  It looks like "DrawText" is not suited to drawing anything other than 0 degree rotations.  You can easily hand-roll DT_LEFT, DT_RIGHT, and DT_CENTER routines.

If this will work for you and you need code for how to do left, right, and center alignment by hand, I'd be happy to code it for you.

On a side note, lfCharSet and lfOutPrecision are not being properly set by your code.  You forgot to put "lf." in front of them.  Turning on "Option Explicit" is great to catch those types of errors.
0
 

Author Comment

by:leorocha
ID: 12447602
Add DT_NOCLIP to DT_RIGHT and to DT_CENTER and the text appears. It seems to be centered between paper left margin and left side of the indicated rectangle.

Thanks
0
 
LVL 3

Expert Comment

by:Egore
ID: 12448909
Unfortunately, you're still not getting the effect that you want (namely, left-, right-, or center-justification).  Everything is off by a distance of the length of the text.  Try putting in a longer string, and you'll see that the text is shifted further to the side.  If you shorten the string, the text will be placed closer to where you would expect.

I would highly suggest looking at "TextOut".  Once again, you lose DT_WORDBREAK, but everything else works if you do a little math.  However, even DT_WORDBREAK can be done with a tiny bit of logic (not to metion that you won't get the results from that flag that you are expecting due to the rotation).  "DrawText" simply was not designed to work with rotated text, but TextOut was.

What I'm trying to get at is that you will have a heck of a time positioning text using DrawText since the RECT that you pass in is virtually meaningless.  Once again, if you need algorithms to left-justify, right-justify, and center your text, since this is a 500 point question, I would be happy to write them for you so that you can use TextOut instead of DrawText.
0
 
LVL 3

Accepted Solution

by:
Egore earned 750 total points
ID: 12448919
Oops, 250 point question, not 500.  Still plenty...
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Suggested Courses

649 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question