TedN Posted March 21, 2007 Posted March 21, 2007 The following code causes a string to be written vertically on a form. The code runs automatically when the form is opened. 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 Quote
amir100 Posted March 22, 2007 Posted March 22, 2007 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. Quote Amir Syafrudin
amir100 Posted March 22, 2007 Posted March 22, 2007 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. Quote Amir Syafrudin
Administrators PlausiblyDamp Posted March 22, 2007 Administrators Posted March 22, 2007 (edited) Would something like this 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. Edited March 22, 2007 by PlausiblyDamp Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
MrPaul Posted March 22, 2007 Posted March 22, 2007 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: Quote Never trouble another for what you can do for yourself.
amir100 Posted March 22, 2007 Posted March 22, 2007 @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. Quote Amir Syafrudin
amir100 Posted March 22, 2007 Posted March 22, 2007 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 Quote Amir Syafrudin
Administrators PlausiblyDamp Posted March 22, 2007 Administrators Posted March 22, 2007 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). Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
TedN Posted March 22, 2007 Author Posted March 22, 2007 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. 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 Quote
MrPaul Posted March 22, 2007 Posted March 22, 2007 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 :) Quote Never trouble another for what you can do for yourself.
*Experts* Nerseus Posted March 22, 2007 *Experts* Posted March 22, 2007 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 Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
TedN Posted March 23, 2007 Author Posted March 23, 2007 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 Quote
MrPaul Posted March 23, 2007 Posted March 23, 2007 (edited) 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: 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 :) Edited March 23, 2007 by MrPaul Quote Never trouble another for what you can do for yourself.
TedN Posted March 23, 2007 Author Posted March 23, 2007 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: 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 Quote
TedN Posted March 28, 2007 Author Posted March 28, 2007 (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: 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 Edited March 29, 2007 by TedN Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.