Appointment Calendar for a month on one form

divjoy

Well-known member
Joined
Aug 25, 2013
Messages
159
Programming Experience
1-3
Hi,

I am trying to design a monthly calendar to be shown on a form at once.

I can do a week using a datagridview, showing each appointment by time and day of the week, but with 31 days it seems difficult to decide which way I should do it.

Do I add 31 datagridviews to a single form, that may be slow to draw so many all at once and show in one form?

Or compress all appointments into 1 string and show a rectangle for each day of the month, which could be easier to do and run a lot faster.

I'd be interested in what people think and a pointer in the best direction? Or even screenshot of how one might look?

kind regards
G
 
So what your saying is I first populate the datagridview cells with my text.
You populate your cells with your data, whatever that may be. It might be just the text or it might also contain some metadata regarding how the text will be displayed.
CellPainting will then pick up this text and assign it to e.Value ?
What happened when you tried it for yourself?
And then I can manipulate the graphics using GDI. What the difference between GDI and e.Graphics.Drawstring ?
GDI and GDI+ are two similar but different things. You're using GDI+ to draw the graphics. The difference between GDI+ and Graphics.DrawString is a nonsense. GDI+ is a technology for displaying graphics onscreen and Graphics.DrawString is a method for drawing text using GDI+.

Asking questions like that suggest that you haven't actually done any real research. If you want to know what GDI+ is, look it up on Bing or Google or whatever search engine you prefer. You shouldn't be asking anything here unless you've already searched for it and not been able to find anything or enough.
 
So here is my test code, but text disappears instantly for some reason?

'e.Handled = True 'complete cell painting!
You have comment out e.Handled.
If you manually paint the cell, set the HandledEventArgs.Handled property to true. If you do not set HandledEventArgs.Handled to true, the cell will paint over your customizations.
 
You have comment out e.Handled.
The one that is commented out is outside the If block, so that shouldn't make a difference. There is one inside the If block and that should be executed if painting is actually done. I don;t have time to look into it further right now but, while the behaviour sounds like that's the issue, the code doesn't look like it is.
 
Unfortunately I don't have a lot of time either. Thought vb.netforums would give me the info quickly!

On form load its paints the text but then the text disappears for some reason, it looks likes it's overwritten it with the FormLoad event ?

It appears to use the CellPainting right at the beginning, thn s when I add new text to the datagrid it cellpaint again.

All very messy. Cant seem to find a guide to show how to add text to the cell with event CellPainting its very confusing! Even trying to get the text to add appears confusing this is where I am at now...


VB.NET:
Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
          'e.Paint(e.ClipBounds, DataGridViewPaintParts.All)  'Draw all parts of the cell normally

        Dim cr = e.CellBounds
        e.PaintBackground(cr, True)  '//  (2)
        e.PaintContent(cr)


        If e.RowIndex >= 0 AndAlso e.ColumnIndex >= 0 Then
          
            Dim newRect As New Rectangle(e.CellBounds.Left, e.CellBounds.Y + 6, 12, 12)
            e.Graphics.FillRectangle(Brushes.Crimson, newRect) 'draws a red filled rectangle in each cell

            Dim RowHeight1 As Integer = 80 'DataGridView1.Rows(e.RowIndex).Height
            Dim newCell As Rectangle = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, False)

            '  newCell.X += DataGridView1.Left
            ' newCell.Y += DataGridView1.Top + RowHeight1

            Dim px As Point = PointToScreen(New Point(newCell.X, newCell.Y))

            Using font = New Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Point)
                Using Brush = New SolidBrush(Color.Blue) 'Pen Type
                   e.Graphics.DrawString(e.Value.ToString(), font, Brush, px)
         

                End Using
            End Using
        End If
        e.Handled = True  'complete cell painting!
      
    End Sub
 
Last edited:
The one that is commented out is outside the If block, so that shouldn't make a difference. There is one inside the If block and that should be executed if painting is actually done. I don;t have time to look into it further right now but, while the behaviour sounds like that's the issue, the code doesn't look like it is.
Ohh, I'm reading too fast again ?
 
Thats OK, It seems to do it and then quickly overwrites it without doing CellPainting.

So somewhere in the assigning data to the datagridivew cells it stop doing cellpainting and load the data directly on assignment! Weird!

I'll keep at it, but its not easy, as there are many many questions on the internet with very few answers, which is a shame as its a fabulous feature!
 
You start out using e.CellBounds and also use this to draw a rectangle in each cell, then you change to some other coordinates for text. What if you continue to use e.CellBounds also when drawing text?
 
You start out using e.CellBounds and also use this to draw a rectangle in each cell, then you change to some other coordinates for text. What if you continue to use e.CellBounds also when drawing text?
I'll try it tomorrow...
 
Here's some test code I tried:
VB.NET:
Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim fieldText = "Red
Green
Blue"
        Dim table As New DataTable

        table.Columns.Add("First", GetType(String))
        table.Columns.Add("Second", GetType(String))

        For i = 1 To 3
            table.Rows.Add(fieldText, fieldText)
        Next

        DataGridView1.DataSource = table
    End Sub

    Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
        If e.ColumnIndex >= 0 AndAlso e.RowIndex >= 0 AndAlso e.Value IsNot Nothing Then
            e.PaintBackground(e.ClipBounds, True)

            Dim prefix = String.Empty

            For Each line In CStr(e.Value).Split({Environment.NewLine}, StringSplitOptions.None)
                Dim lineText = prefix & line
                Dim colour = Color.FromName(line)

                Using brush As New SolidBrush(colour)
                    e.Graphics.DrawString(lineText, e.CellStyle.Font, brush, e.CellBounds)
                End Using

                prefix &= Environment.NewLine
            Next

            e.Handled = True
        End If
    End Sub

End Class
Here's the result:
CellPainting Demo.png


Note that I drew a multiline string one line at a time to draw each line in a different colour. I prefixed the text for each line with the required number of line breaks to push it down the appropriate distance.
 
Ohh, I'm reading too fast again ?
So im thinking about other options....
How about creating a list object assign text values colour in and then assign list object to a cell in datagridview.

No need for cellpainting event!
 
So im thinking about other options....
How about creating a list object assign text values colour in and then assign list object to a cell in datagridview.

No need for cellpainting event!
I don't know exactly what you mean by that but it certainly doesn't sound like something useful; at least, not on its own. If you don't handle that event or use a custom cell type that does its own custom painting, you're just going to end up with a single line of text in a single colour. Whatever data you store in the cell, you still need to interpret it somewhere to display it in the way you want, which is what the event handler is for.
 
Here's some test code I tried:
VB.NET:
Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim fieldText = "Red
Green
Blue"
        Dim table As New DataTable

        table.Columns.Add("First", GetType(String))
        table.Columns.Add("Second", GetType(String))

        For i = 1 To 3
            table.Rows.Add(fieldText, fieldText)
        Next

        DataGridView1.DataSource = table
    End Sub

    Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
        If e.ColumnIndex >= 0 AndAlso e.RowIndex >= 0 AndAlso e.Value IsNot Nothing Then
            e.PaintBackground(e.ClipBounds, True)

            Dim prefix = String.Empty

            For Each line In CStr(e.Value).Split({Environment.NewLine}, StringSplitOptions.None)
                Dim lineText = prefix & line
                Dim colour = Color.FromName(line)

                Using brush As New SolidBrush(colour)
                    e.Graphics.DrawString(lineText, e.CellStyle.Font, brush, e.CellBounds)
                End Using

                prefix &= Environment.NewLine
            Next

            e.Handled = True
        End If
    End Sub

End Class
Here's the result:
View attachment 4497

Note that I drew a multiline string one line at a time to draw each line in a different colour. I prefixed the text for each line with the required number of line breaks to push it down the appropriate distance.
Looks great I will copy your code and test. Can you change the background color and not wrap the text.
 
Can you [...] not wrap the text.
Given that the Graphics.DrawString method is what is being used to draw the text, maybe you should research that to see what it can and can't do. Look first, ask questions later.
 
Also can you center the top text line and left align lines below?
You probably hadn't read my previous post when you wrote this but I will repeat anyway: look first, ask questions later. DrawString is what draws the string so that is where you will control how the string is drawn. READ THE DOCUMENTATION.
 
Back
Top