Rotten Little "e" Is Driving Me Nuts

TedN

Freshman
Joined
Sep 25, 2006
Messages
35
The following code causes a string to be written vertically on a form. The code runs automatically when the form is opened.

Code:
Public Sub Form1_Load(ByVal sender As System.Object, _
    ByVal e As PaintEventArgs) Handles MyBase.Paint

        Dim sName As String = "TedN"

        With [B]e[/B].Graphics
            Dim oBrush As New SolidBrush(Color.Black)
            Dim oFont As New Font("Tahoma", 32, FontStyle.Bold)
            Dim oStrFormat As New StringFormat(StringFormatFlags.DirectionVertical)

            .DrawString(sName, oFont, oBrush, 0.0F, 0.0F, oStrFormat)
        End With
    End Sub

I would like to put the code in a simple little sub routine that would be called when the form loads or a button clicked, etc.

I've tried every whichway to get rid of the "e" component which I assume is tied to an event. I don't want the code to run directly from an event.

How the heck do I do that.

Thanks,
Ted
 
If I were in your situation then I'll be looking the Object represented by "e". That way you can subtitute e with the appropriate Object. I can't help much cause I currently don't have MSDN on my computer nor do I have the time to be browsing MSDN online.

Sorry if it didn't help much.
 
I've taken a little time to browse MSDN online. Here's what I got. e.Graphics is basically an object of type Graphics. Why not create a new Graphics object and replace e.Graphics with your new Graphics object.

Hope this helps.
 
Would something like this
Visual Basic:
Public Sub Form1_Paint(ByVal sender As System.Object, ByVal e As PaintEventArgs) Handles MyBase.Paint

DoStuff(e.Graphics)
      
End Sub

private Sub DoStuff(g as graphics)
Dim sName As String = "TedN"

Dim oBrush As New SolidBrush(Color.Black)
Dim oFont As New Font("Tahoma", 32, FontStyle.Bold)
Dim oStrFormat As New StringFormat(StringFormatFlags.DirectionVertical)

g.DrawString(sName, oFont, oBrush, 0.0F, 0.0F, oStrFormat)
  
end sub

be suitable.
 
Last edited:
Form_Load handles MyBase.Paint

Having a method called Form_Load handle the paint event is a little counter-intuitive. The event will not fire when the form loads, it will fire whenever part of the form needs repainting (which does happen when a form loads but also a lot of other times). It may even fire when none of the form needs repainting - Windows sends WM_PAINT messages to idle windows. Bear that in mind when writing code for the event, as anything too processing intensive could slow your application down horribly. A good idea is to check the e.ClipRectangle property to test which parts of the form, if any, require repainting.

Good luck :cool:
 
@PlausiblyDamp

I think of the same thing as you proposed. But then again TedN was trying to remove the necessity to use "e". That's because he wanted to call it from anywhere in the code, including places where "e" will not be defined. It is clear when TedN mentioned making a little sub routine and calling the subroutine from button click. I don't suppose your "DoStuff" works if it was called from a button click event handler.

CMIIW.
 
Re: Form_Load handles MyBase.Paint

@TedN

I'd put some thought about what MrPaul suggest. I totally agree with MrPaul. You should call the appropriate methods from specific Graphics object that needed drawing.

That's all I guess. :D
 
You could call my rather badly named DoStuff routine from anywhere - as long as you provide a Graphics object for it to draw into. Where this graphics object comes from or what it is isn't the routines problem though.

If TedN was just wanting to draw onto the form from any method / event handler in the form then using the form's .CreateGraphics method would provide a valid object to draw onto.

Personally I would go with MrPaul's suggestion of doing all graphics rendering in the Paint event - this way it will be called when it needs to be redrawn (including external reasons like your app being covered and uncovered by another window).
 
Thanks for all of your replies.

I've modified the code so that when the form loads it calls a sub routine which should cause vertical text to appear on a label.

The program runs but the label remains blank. Appreciate it if someone could point me to what I'm doing wrong.

Code:
Public Sub Form1_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load

        VertText(Label1)

    End Sub



    Private Sub VertText(ByVal control As Control)

        Dim sName As String = "TedN"
        Dim g As Graphics = control.CreateGraphics

        Dim oBrush As New SolidBrush(Color.Black)
        Dim oFont As New Font("Tahoma", 32, FontStyle.Bold)
        Dim oStrFormat As New StringFormat(StringFormatFlags.DirectionVertical)

        g.DrawString(sName, oFont, oBrush, 0.0F, 0.0F, oStrFormat)

    End Sub

Thanks,
TedN
 
How painting works

The problem is that when Form_Load fires the form is loaded but not yet visible. This means any drawing you do will be lost when the form becomes visible and paints itself.

I believe the problem is that you're treating forms and controls as if they remember what is drawn on them. In general, they do not, and any drawing you perform will be erased as soon as the form or control repaints itself (for example, when another window is moved over it). If you want a particular drawing operation to persist then it must be performed whenever the control paints itself.

In this case, since your drawing operation is simple, you can simply handle the label's Paint event and call VertText from there. However, if you were performing more complex drawing then I would suggest creating an Image to act as a backbuffer, portions of which can be drawn when required.

Good luck :)
 
If this is text on a label, I'd suggest creating your own label. There's a sample "vertical label" control here:
http://www.codeproject.com/vb/net/vertical_label.asp


If you need more generic drawing, I'd read through the posts again. First, make sure you do ALL your custom drawing in some kind of Paint event. And, if you're going to create your own Graphics object, make sure you Dispose of it when you're done. If you're using a Paint event that provides e.Graphics, then do NOT dispose of it. :)

-ner
 
I really appreciate all the advice. However, I think I'm reaching the end of the line here.

What I really wanted to do was to put vertical text in the column headers of a DataGridView. I have fairly lengthy column headers which can't really be shortened. This means that the columns are unnecessarily wide. This work was originally displayed on an Excel spreadsheet where there's no problem aligning the column header text vertically.

If I'm having this much of a problem with a simple label then I think that DataGridView column headers are well beyond my reach.

If anyone out there knows of an alternative to a DataGridView where column header text can be displayed vertically I'd appreciate knowing.

Thanks for your time.
Ted
 
DataGridView.CellPainting

This should be possible. You can handle the DataGridView's CellPainting event and if the cell being painted is a column header, the e.RowIndex property will return -1. You can then perform any drawing you want, using the e.ClipBounds and e.CellBounds properties to position the drawing. You should then set e.Handled to true to prevent the control painting over your drawing.

Something like this:

Visual Basic:
Private Sub MyDataGridView_CellPainting( _
    ByVal sender As Object, _
    ByVal e As DataGridViewCellPaintingEventArgs _
) Handles MyDataGridView.CellPainting

    If e.RowIndex = -1 Then
        'Paint default background
        e.PaintBackground(e.ClipBounds, True)
        'Render column header text in red
        e.Graphics.DrawString(e.Value.ToString(), Me.Font, Brushes.Red, e.CellBounds)
        'Stop default drawing
        e.Handled = True
    End If

End Sub

Good luck :)
 
Last edited:
Re: DataGridView.CellPainting

This should be possible. You can handle the DataGridView's CellPainting event and if the cell being painted is a column header, the e.RowIndex property will return -1. You can then perform any drawing you want, using the e.ClipBounds and e.CellBounds properties to position the drawing. You should then set e.Handled to true to prevent the control painting over your drawing.

Something like this:

Visual Basic:
Private Sub MyDataGridView_CellPainting( _
    ByVal sender As Object, _
    ByVal e As DataGridViewCellPaintingEventArgs _
) Handles MyDataGridView.CellPainting

    If e.RowIndex = -1 Then
        'Paint default background
        e.PaintBackground(e.ClipBounds, True)
        'Render column header text in red
        e.Graphics.DrawString(e.Value.ToString(), Me.Font, Brushes.Red, e.CellBounds)
        'Stop default drawing
        e.Handled = True
    End If

End Sub

Good luck :)

Thank you for this. It's beginning to sink in that with Graphics one needs a sub routine that repaints on an as required basis, as you mentioned in one of your previous posts.

I won't be able to get back to this until next week. But I look forward to trying this out and hopefully with some success.

Thank you again for all your help.

TedN
 
Re: DataGridView.CellPainting

This should be possible. You can handle the DataGridView's CellPainting event and if the cell being painted is a column header, the e.RowIndex property will return -1. You can then perform any drawing you want, using the e.ClipBounds and e.CellBounds properties to position the drawing. You should then set e.Handled to true to prevent the control painting over your drawing.

Something like this:

Visual Basic:
Private Sub MyDataGridView_CellPainting( _
    ByVal sender As Object, _
    ByVal e As DataGridViewCellPaintingEventArgs _
) Handles MyDataGridView.CellPainting

    If e.RowIndex = -1 Then
        'Paint default background
        e.PaintBackground(e.ClipBounds, True)
        'Render column header text in red
        e.Graphics.DrawString(e.Value.ToString(), Me.Font, Brushes.Red, e.CellBounds)
        'Stop default drawing
        e.Handled = True
    End If

End Sub

Good luck :)

Thanks for your code, it works fine. Very much appreciated. Just gotta find the way of increasing the header height.

Thanks again,
Ted
 
Last edited:
Back
Top