Calendar

  • Thread starter Dino M. Buljubasic
  • Start date
D

Dino M. Buljubasic

I'd like to build a calendar displaying all days in a month in a grid so
that when I click on the header of a square representing a day of month, I
can add a new meeting etc. I know that .net provides a calendar control but
that one is not what I want. I want my callendar to fill whole form and
display only one month.

I would like to build someting like this:

+---------------+
| 8__________| cell header, shows day, clicking on it shows pop up menu
to add a meeting
| |
| | cell body, allows entering some text
+---------------+

This is one cell showing 8th day of the current month.

My question is what would be best way to do this? What control is good to
create calendar grid? A data grid? Panels? ...

Any help will be appreciated,
 
C

Cor

Hi Dino,
I have never done this, but I would just choose for dynamicly built
collection of flat style buttons direct on a form.
Very easy to handle.
Cor
 
D

Dino M. Buljubasic

How to add the day number, the button header(to be able to add new task,
meeting, etc) and button body (to be able to enter some text)?

Thanks
 
C

Cor

Hi Dino
I did make the calender,
You can paste it in the code from a new form.
It makes a calender (it works only for october 2003, but changing that date
is of course nothing).
When you see it, I think to add that to add the other buttons will be easy
for you.
(By example you can where I show the messagebox with a select case test what
is the status and what appointment has to be done)
\\\
Private mybutton(31) As Button
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim start As Integer = 4
Dim top As Integer = 25
Dim i As Integer
For i = 0 To System.DateTime.DaysInMonth(2003, 10) - 1
mybutton(i) = New Button
mybutton(i).TextAlign = ContentAlignment.MiddleCenter
mybutton(i).Width = 40
mybutton(i).Height = 20
mybutton(i).FlatStyle = FlatStyle.Flat
mybutton(i).BackColor = Drawing.Color.AntiqueWhite
mybutton(i).Location = New System.Drawing.Point(start, top)
mybutton(i).Text = (i + 1).ToString
mybutton(i).Cursor = Cursors.Hand
Me.Controls.Add(mybutton(i))
AddHandler mybutton(i).Click, AddressOf mybutton_Click
start = start + 40
If (i + 1) Mod 5 = 0 Then
top = top + 20
start = 4
End If
Next
End Sub
Private Sub mybutton_Click _
(ByVal sender As Object, ByVal e As System.EventArgs)
Dim month As Button = DirectCast(sender, Button)
MessageBox.Show("The day is: " & month.Text)
End Sub
End Class
///
I hope this helps a little bit
Cor
 
F

Fergus Cooney

Hi Dino,

This is quite a challenging project. ;-)

First some questions:
1. Is this for work or for your own use/fun?
2. Do you have a deadline?
3. Do you know Html?
4. If not, is it on your list of things to learn?

Now - the project.

The first thing to realise is that each Day is going to have several
elements. There will be the Header which will display the day number, and the
Body which will display a version of the Message for that Day. That Message
could be composed of one or more events or just be a single piece of text. It
may or may not fit inside the Body. You'll want to provide some way to
enter/edit that Message which will require a TextBox of some flavour. You'll
want a ContextMenu for your popup options. You might consider having a ToolTip
(.NET's or your own version of the same) which can display the Day's Message
when it is too big to fit inside the Body. A Day may belong to the current
month or it might be for the previous or next months. This Day will have to
work as well as the others but look different. Some Days may need to appear
different depending on, for example, the type of Message that they contain, eg
a birthday notification.

All of that just for one day. And a month's worth of all that for the
whole Form. To me, that screams UserControl in a very loud voice. It also says
that there are several classes which will be needed to manage all of this, eg
Message (or whatever you choose to call it). So I recommend that you start
your design off by considering how you'd like just a single Day to look and
behave.

Regards,
Fergus
 
D

Dino M. Buljubasic

Hi Cor,

thanks, I am sure your idea will be helpful. I was also playing with it and
I decided to go with panels instead of buttons since I need each panel that
represents a day of month to have also a header that will have a context
menu and that will show the number of the day. In addition, each cell needs
also a text box so I can enter something in it. That is the reason I
decided to go with panels instead of buttons. So, basically each cell is a
panel that contains a label (header with context menu) and a text box).

However, I am sure your code will be helpful. I saw already some
interesteing things for me there. Thank you, I am sure I can use some of
your logic with my panels.

I'll let you know how am I doing.

I appreciate your help,
 
D

Dino M. Buljubasic

Hi Fergus,

thanks for your reply.

This is quite a challenging project. ;-)

First some questions:
1. Is this for work or for your own use/fun?

This is my work project and yes, it is probably going to be big but I have
to build it anyways. :)
2. Do you have a deadline?

For sure but I don't know it yet, probably about a month of time left
3. Do you know Html?
Little bit, but the project is not web based, I am building it on windows
form
4. If not, is it on your list of things to learn?
I'd certainly like to learn it. Beside all that functionality, it has to
look good too, so I will probably have to customize some of the controls, I
did my first 'owner drawn' menu and it looks cool. Would really like to be
able to simillar with other controls.
Now - the project.

The first thing to realise is that each Day is going to have several
elements. There will be the Header which will display the day number, and the
Body which will display a version of the Message for that Day. That Message
could be composed of one or more events or just be a single piece of text. It
may or may not fit inside the Body. You'll want to provide some way to
enter/edit that Message which will require a TextBox of some flavour. You'll
want a ContextMenu for your popup options. You might consider having a ToolTip
(.NET's or your own version of the same) which can display the Day's Message
when it is too big to fit inside the Body. A Day may belong to the current
month or it might be for the previous or next months. This Day will have to
work as well as the others but look different. Some Days may need to appear
different depending on, for example, the type of Message that they contain, eg
a birthday notification.

All of that just for one day. And a month's worth of all that for the
whole Form. To me, that screams UserControl in a very loud voice. It also says
that there are several classes which will be needed to manage all of this, eg
Message (or whatever you choose to call it). So I recommend that you start
your design off by considering how you'd like just a single Day to look and
behave.

You are right, all that functionality is needed. I have designed everything
already and am building the gui. So far, I get 7X5 grid of panels
displayed. Now I have to add a label (header) and a text box (body) to each
of the cells and make somehow everthing resize appropriatelly as user
resizes the form.

Have one problem though. I am adding the labels and text boxes to each
panel in a loop. However, only first panel gets added a lable and a text
box to it, the others don't. I don't know why. Here is the code

Private Sub frmMonthlyCalendar_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Dim aPanelCollection As New Collection()

Dim pn As Panel
Dim lbl As Label
Dim txt As TextBox
Dim intI As Integer = 0

' upper right coordinates of panel, lable and text box
Dim pnX As Integer = 0, pnY As Integer = 20
Dim lbX As Integer = 0, lbY As Integer = 0
Dim txX As Integer = 0, txY As Integer = 15

' draw 35 panels each with a label and text box inside
While intI <= 35

pn = New Panel()
lbl = New Label()
txt = New TextBox()

If ((intI <> 0) And (intI Mod 7 <> 0)) Then
pn.Location = New Point(pnX, pnY)
pn.Size = New Size(85, 70)
pn.BorderStyle = BorderStyle.FixedSingle
lbl.Text = intI.ToString ' display number in the label

lbl.Location = New Point(pnX, lbY)
lbl.Size = New Size(85, 15)
lbl.BackColor = System.Drawing.Color.Gainsboro

txt.AutoSize = False
txt.Location = New Point(pnX, lbY + 15)
txt.Size = New Size(85, 55)
txt.BorderStyle = BorderStyle.None
txt.BackColor = System.Drawing.Color.White

' add label and text box to panel
pn.Controls.Add(lbl)
pn.Controls.Add(txt)

' add panel (calendar cell) to big panel. This panel holds
all small panels representing days
aCalendarPanel.Controls.Add(pn)
pnX = pnX + aCalendarPanel.Controls.Item(1).Size.Width

Else
' when moving to next row, reset coordinates
If intI = 0 Then
pnX = 0
pnY = 20
lbX = 0
lbY = 0
txX = 0
txY = 15
Else
pnX = 0
pnY = pnY + aCalendarPanel.Controls.Item(1).Size.Height
lbX = 0
lbY = lbY + aCalendarPanel.Controls.Item(1).Size.Height
txX = 0
txY = txY + aCalendarPanel.Controls.Item(1).Size.Height
End If

pn.Location = New Point(pnX, pnY)
pn.Size = New Size(85, 70)
pn.BorderStyle = BorderStyle.FixedSingle

lbl.Location = New Point(pnX, lbY)
lbl.Size = New Size(85, 15)
lbl.BackColor = System.Drawing.Color.Gainsboro

txt.AutoSize = False
txt.Location = New Point(pnX, lbY + 15)
txt.Size = New Size(85, 55)
txt.BorderStyle = BorderStyle.None
txt.BackColor = System.Drawing.Color.White

' add label and text box to the panel
pn.Controls.Add(lbl)
pn.Controls.Add(txt)

' add panel (calendar cell) to big panel. This panel holds
all small panels representing days
aCalendarPanel.Controls.Add(pn)
pnX = pnX + aCalendarPanel.Controls.Item(1).Size.Width

End If

' ad day panel to the collection
aPanelCollection.Add(pn)
intI += 1

End While

End Sub
 
D

Dino M. Buljubasic

Here is update of what I have done so far. Having still probles to display
all of my labels (cell headers) and text boxes(cell bodies). Hope to get
some help on this :)

I am building a calendar grid from panels containing a label(day header) and
a text box (day body).

I am adding each panel, label, text box programatically in a loop and all of
my panels are displayed on the form but only first label and first text box
are displayed, the others are not. How can I fix this?

Here is the code I use:

Dim aPanelCollection As New Collection()

' two dim array holding days of a calendar grid
Dim pn(5, 7) As Panel
Dim lbl(5, 7) As Label
Dim txt(5, 7) As TextBox
Dim intRow As Integer = 0
Dim intCol As Integer = 0
Dim intCounter As Integer

' starting upper left coordinates of first cell
Dim pnX As Integer = 0, pnY As Integer = 20
Dim lbX As Integer = 0, lbY As Integer = 0
Dim txX As Integer = 0, txY As Integer = 15

For intRow = 0 To 4
For intCol = 0 To 6

pn(intRow, intCol) = New Panel()
lbl(intRow, intCol) = New Label()
txt(intRow, intCol) = New TextBox()
intCounter += 1

' format panel. this panel represents a day
pn(intRow, intCol).Location = New Point(pnX, pnY)
pn(intRow, intCol).Size = New Size(85, 70)
pn(intRow, intCol).BorderStyle = BorderStyle.FixedSingle

' format label
lbl(intRow, intCol).Location = New Point(pnX, lbY)
lbl(intRow, intCol).Size = New Size(85, 15)
lbl(intRow, intCol).BackColor =
System.Drawing.Color.Gainsboro
lbl(intRow, intCol).Text = intCounter.ToString
lbl(intRow, intCol).Visible = True

' format text box
txt(intRow, intCol).Location = New Point(pnX, txY)
txt(intRow, intCol).Size = New Size(85, 55)
txt(intRow, intCol).BorderStyle = BorderStyle.None
txt(intRow, intCol).BackColor = System.Drawing.Color.White
txt(intRow, intCol).AutoSize = False
txt(intRow, intCol).Visible = True

' add label and text box to panels collection of controls
pn(intRow, intCol).Controls.Add(lbl(intRow, intCol))
pn(intRow, intCol).Controls.Add(txt(intRow, intCol))

' add this panel cell to big panel. This panel is
represents a month
aCalendarPanel.Controls.Add(pn(intRow, intCol))
pnX = pnX + aCalendarPanel.Controls.Item(1).Size.Width

' when moving to next row, reset upper left coordinates of a
cell
If ((intCol <> 0) And (intCol Mod 6 = 0)) Then
pnX = 0
pnY = pnY + aCalendarPanel.Controls.Item(1).Size.Height
lbX = 0
lbY = lbY + aCalendarPanel.Controls.Item(1).Size.Height
txX = 0
txY = txY + aCalendarPanel.Controls.Item(1).Size.Height
End If
Next
Next

Any help will be appreciated,
 
C

Cor

Hi Dino,
I was hoping you was from Serbia or Croatia, so I did want to answer to you:
for some good botles of wine and brandy Fergus and I will make it for you,
but I see now you are from Canada, and that is to cold for good wine or
brandy.

But the problem can not be that big, I think we will have fun to help you.

But for me not anymore tonight, answer if you will apriciate if I do it
tomorrow.

Fergus and I live in Europe, so I think if we succeed, (I do not promish it,
but don't see a problem) you will have your answer tomorrow based on your
solution.
Cor
 
D

Dino M. Buljubasic

Hey Cor,

thanks. Actually, I live in Vancouver, Canada, but I am originally from
Bosnia, and I can tell you, there is good wine there, too. :) And, there
is good wine in Canada as well.

Anyways, where from Europe are you guys?

Thanks for your help.
 
D

Dino M. Buljubasic

I got the display problem solved :)

..... was just adding the controls to invisible area of the panel. :) ...
damn ...
 
F

Fergus Cooney

Hi Dino,

The reason I asked about work vs home was that for a Dino project there is
no deadline and you can spend as much time as you like learning the things
that you need. But it <is> for work and you have a deadline. :-(

<digression>
The reason I asked about Html was that you could do the project using
Html - which would allow you to use the full power of Html, Css, Xml and IE
(assuming that it's your browser). IE has some truly amazing stuff that many
Html app programmers are completely ignorant of. One of these is 'behaviours'
and it's a way, similar to VB event handling, of separating the code from the
Html elements (controls).

You don't have to be doing a web site in order to utilise this stuff. For
example I've written two simple 'web' apps (diary and telephone directory) for
my computer at home and these are done in Html and JavaScript. They don't run
as web pages, though, because IE allows you to create applications from web
pages by changing the extension to .hta instead of .htm. (Try it on any web
page and see the difference.)
</digression>

I would <seriously> consider doing your Cells as UserControls. I'm
guessing that you haven't done them before but they really are very easy to
use. A UserControl is a bit like a Form in that it can contain a bunch of
Controls (your label and text box, etc), and can act on their behalf in the
way that a Form acts on behalf of its contents. But you can put UserControls
on a Form just as if they were a single Control. I've attached a small project
which shows you how you could use a UserControl for your calendar.

You'll see immediately that while you need code to position the Cells, you
need none for the Labels and TextBoxes because the UserControl handles it all.

Notice how the Dock and Anchor properties are used. Label docked at the
top, TextBox docked below. Panel docked to fill the UC. I've left gaps below
the TextBox and the Panel just so that there's somewhere to click when in the
designer. On running, however, the Dock Properties are set to Fill.

In the main Form you'll see how the Cells resize as the Form is resized.
There's a white gap at the right and bottom. This is because the Form can
change size by pixels, but the Cells (as a whole) must change 7 (W) or 5(H) at
a time. The difference is the white gap. The solution is to only allow the
Form to change W in increments of 7 and H in 5's. That's for another day,
though.

Have fun with it. ;-)

Regards,
Fergus
 
D

Dino M. Buljubasic

Hey Fergus,

thanks a lot. This is going to be really helpful. I already created a grid
with text boxes and labels with date numbers but the way you did it is way
better I think so I am goint to rewrite my code and use user control instead
of panels just as you did. I think it will also make me learn more about
user controls since I have never used them before.

I had two questions though. This calendar project is suppose to be a
module, just one part of a bigger application. I am doint it now as a
regular project (.exe) just so I can easily debug and trace my code. I
guess once I finish it, I can just copy all the code together with forms
into a module. Am I right? I have never done at school anything similar
:).

Also, the way how I did it so far, I am using panels, each holding a label
and a text box, looks really good but I would like to change to border of
each panel to a different color instead of default black. I don't know how
can I do that. Is there a way to do that?

Thanks again for this huge help, I am goint to have fun with it and learn
lots from your code. :)
 
F

Fergus Cooney

Hi Dino,

|| This calendar project is suppose to be a module

Yes - as it should be.

|| once I finish it, I can just copy all the code together with forms
|| into a module.

I was all ready for this question, but I was wainting to see how you'd
like the idea of UserControls.

Guess what - you can do the <whole Calendar> as a UserControl!!

|| Thanks again for this huge help, I am goint to have fun
|| with it and learn lots from your code. :)

You're welcome. :)

Doing UserControls when they are new to you has its own set of challenges
so don't be afraid to keep coming back on this. Let's keep it all in this
thread for now. Later, given that this is for work, you might want to go
private. My email address is valid.

Some of the issues regard the fact that the controls within the
UserControls are (should be) hidden from the outside world. If you want to
expose anything you have to do it explicitly.

|| I would like to change to border of each panel
|| to a different color instead of default black

And this is one example.

The user (Form) of the CalendarCell cannot access the Panel. You'd have to
create a Property in the UserControl which will allow the user to Get and Set
the background colour. The same will hold true for anything else that you want
to be optional. You are likely to end up with a very long list by the end. But
then, look at Controls in Intellisense - they have long lists, too.

A key point here is that <you> know that your CalendarCell uses a Panel.
Your users do not and nor should they. They are thinking in terms of Calendar
Cells which have a header displaying a date and a body displaying messages,
but whether this is done using Labels, TextBoxes, PictureBoxes or whatever, is
of no concern. You provide Properties in terms of what a conceptual
CalendarCell provides and do the mapping to the actual Controls on the
inside - privately. Then, if you decide that RichTextBox is better than
TextBox, or PictureBox is better than Panel, the change can be made without
breaking the users's code.

Class CalendarCell
Public Property BorderColour As Color
Get
pnlCell.BackColor = Value
End Get
Set
Return pnlCell.BackColor
End Set
End Property

As to drawing the border, there are a couple of ways. If you are using
Dock to make it easy to handle resizing, there won't be any border visible
that you can colour. In this case you could have a second panel which contains
the one you have. Make the inside one just a bit smaller and keep it in place
with Anchor LRT & B. Then you can use the background colour of the outside one
to give border colour to the inside one. Another way would be to have the
Label and TextBox just a bit smaller and have <them> anchored.

Regards,
Fergus
 
D

Dino M. Buljubasic

Hi Fergus,

thanks for your help. I really appreciate it, especially the way you
explain it so I can learn a lot. I am quite new to VB.net and .NET in
general, have about 5 months of experience, before that I was studying.

I am wondering if you could recommend me some good reference, or books for
desigining forms, GDI, etc for VB.net so I can do some reading in free time.

I feel that I need to upgrade my knowledge of OOP and GDI+ (actually about
GDI, I have never learned anything, so in that field I am a complete
beginer)

Thanks,
 
D

Dino M. Buljubasic

Hi Fergus,

thanks for your help.

I had a question though, I am having a very strange problem. I am basically
redoing my calendar and making the cells be objects just as you suggested
instead the way I did it previously. I am also using UserControl instead of
Panel.

That is fine, I get a grid of cells displayed and labels and rich textboxes
inside but strangelly my 'aCalendarPanel' panel acts little bit strange. I
checked in your code, and my settings for Dock property are the same. And
that is the probelm, I noticed that your 'aCalendarPanel' is Docked to
'Fill' but its Location is (0, 28) and also its size is to fill the empty
place between the header and futher panel.

However, when I set my 'aCalendarPanel' Dock property to Fill, my Location
changes always to (0, 0) as well as Size does so it covers all form. And
that is what creates the problem since lots of my cells get partially
visible then, they get hidden beside header panel (doceked to Top) and
futter panel (docked to Bottom).

I never had problem like this before (not that I used Dock lots before
but... ). How can I fix this?

Regards,
 
F

Fergus Cooney

Hi Dino,

I'm afraid it's so long since I was a beginner that I wouldn't have a
clue. I'm not keen to recommend books anyway as different people have
different learning styles.

One idea would be to start a new thread and get the group's ideas. Another
would be to nip over to Amazon, do a search on VB.NET and GDI and read some
reviews.

If you can get an afternoon off work to go to a decent sized computer
bookshop (with the company credit card, preferably!) you can pick and choose
something that will best suit you.

Regards,
Fergus
 
F

Fergus Cooney

Hi Dino,

The aCalendarPanel is just for the days of the month. This means that
there will have to be a separate panel for the month itself plus the headers
for the days of the week. That's the one at the top which takes up the first
28. (You may even choose to have two panels one for the month and one for the
day headers). This panel (I called it pnlDayHeaders) is Docked to Top.

At the bottom I put another panel, pnlOtherControls, as a just-in-case
measure. It can always come out again. But there will possibly be some
Controls which would be useful there - perhaps buttons for navigation between
the Months. This one is Docked to Bottom.

That leaves aCalendarPabel Docked to Fill and it will fill the space
available after the other docked Controls.

I've just reread your post and you have the same setup as me.

However, sometimes if you have multiple panels and the docking gets
confused, you have to undock them all and start again. I did that once or
twice with the Panels while figuring out what I was going to have on the Form.
I also tried Anchoring but that screwed the Docking up, so again I had to
reset it all.

If it still doesn't work, mail me the project and I'll have a look. But
first I'm off to bed. ;-)

Regards,
Fergus
 
D

Dino M. Buljubasic

Hi Fergus,

thanks for your help :)

I have some other problems with my calendar though I wanted to ask you for
help.

I have a panel containing week days abouve the panel containing month days
in my calendar (like "Sunday", "Monday", "Tuesday", ....)

My problem is that I can not resize them together, so that a weekday header
always stays about the column in the calendar for say Mondays of the current
month.

Can you help me with this please. The code is attached.

Thank you
Dino
 
D

Dino M. Buljubasic

Hi Fergus,

it's me again. I got the problem with resizing solved. :) It took me a
while. I have noticed that one have to be very careful when playing with
docking.

I am trying to remove the thin strip on the bottom and on the right of the
calendar that is shown due to resizing of 7X5.

Can you help me with that please

Thank you
Dino
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top