Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

MirandaPlanner v.1.23

0.00/5 (No votes)
2 Feb 2004 3  
A low priority stealth application to keep track of time and notes.

Sample Image - Miranda.jpg

Introduction

Note 29.09.03: I now run Win XP and it works fine on this platform too. Also on an old NT 4.0. The same goes for Win ME. Also it compiles and builds 100% with VS 7.0.

Note 24.06.03: I've been updating this product for the past 2 or 3 weeks, made corrections to the code and some enhancements also. I think that the state it's in now is 'just it' and I can't think of any more functionality to add. So in other words - end of the project. If however I see small things wrong, I'll correct this and upload new zips and I don't plan to change ver.# for that reason. I will only change the date of this note.

What?

A low priority stealth application to keep track of time and notes on a daily basis. So, yes this is yet another calendar (my guess is that there are a few out on the market) - a simple one though, dealing with few classes only and very easy to go into and understand; I think and hope. I'll come back to the details in a moment and then I'll explain it from a design point of view. Main reason to do this was to have fast access to days, weeks and numbers of business weeks for a specific month, without going into Outlook. Also the exercise for me was to try to do some time-related programming around CTime and then put it all in some nice GUI context. I'm rather satisfied on that part - not saying that my specialized classes are in any way perfect, not at all. But for now, it's OK. And as for the 'stealth' in it, it's because MirandaPlanner (mp.exe) slides up/down/in/out depending on the location of the task bar - I like that behavior for a calendar hidden under a task bar.

Why?

Well, not because I can't sleep at night but because I'm out of a job for the time being, I couldn't let be playing around with sliding windows, ownerdrawn buttons and timers et cetera, now that I have the time - more or less addicted to the business. I used approximately 2 weeks for a first version 1.00 to emerge and I guess that there are much more to come when all you wise guys pinpoint all the mistakes, bugs and dislikes. But for now, this is it. And as always KISS - therefore only around 5000 MFC lines of mine to begin with. And why that name you may ask(?). Well, simply a name I read in my newspaper recently. So a name of someone that popped up while programming - sounded nice.

Details

I'm sick and tired of class diagrams, entities ditto and all that, so let me use some words instead. So here is my big picture. I made a class CTimeEx : public CTime and filled it with a bunch of methods to retrieve fx, a week number based on a time obj. This sport continued for some time and I ended up with the class you can see in the file timeex.hpp. This interface is split up in sections holding methods to deal with years, months, weeks, days and so on and is as such easy to go into and grasp. So if you are interested, take a look at timeex.hpp/cpp to begin with and pay special attention to how week numbers are calculated - tell me if something looks odd; please. I had a very hard time writing it (see const int GetWeek_No()). Apart from the time class itself, I use some specialized controls. Not that specialized but flat buttons, set up all of them as ownerdrawn and mostly maintained by the base clsss CCalBtn : public CButton and, a slim class CCalBtn_Radio : public CCalBtn to take care of radio buttons. Except for one rich edit, all controls are instantiated from these two classes and therefore what the application must do is to maintain a bunch of buttons basically. So this *is* simple as I said. So what you have is -

class CCalBtn : public CButton
{ ... };
class CCalBtn_Radio : public CCalBtn
{ ... };
class CCalEdit : public CRichEditCtrl
{ ... };

I use 26 CCalBtns, 42 CCalBtn_Radios and one CCalEdit. An awful lot of buttons ya' but I like the experiment. There seems to be *no* speed/refresh problems - even on my slow laptop. So speed and 1000 invalidates are no issue it seems. Another point. A rule is: A month can always be fitted into a radio group of 7 times 6 members. This ensures that I can always show any month using 42 radio buttons. A month will always take up a space less than 6 weeks. Days can be clicked in the radio group and as a consequence, the "display time" changes. I use the word "display time" inside the calendar class. Some words about that class now.

class CCalendar is nested inside the frame wnd (class CCalFrameWnd : public CFrameWnd) and has CCalFrameWnd as friend. Naturally, all time-stuff takes place inside the calendar class, including handling of notes (more about notes in a moment). So going back/forward in time now comes down to calling -

const void Go2_SpecificDay();
const void Go2_Today();
const void Offset_Days(const int);
const void Offset_Months(const int);
const void Offset_Years(const int);

in class CCalendar. There is a close relationship between the frame wnd and the calendar - calendar obj must sync to whatever the user decides to do in some situations and vice versa in other situations. I'll not go into further details about that, so please see for yourself and just keep in mind the big picture -

class CCalFrameWnd : public CFrameWnd
{
...
protected:
class CCalendar
{ ... };
...
};

And the calendar controls the "display time" using class CTimeEx underneath.

Life span

After InitInstance(...) has created the main frame, the window sets itself up as a palette window. Inside the frame wnd., I have a CalcDimension() which not only determines the final dimension of the MirandaPlanner window (needed to get the final dimension for BitBlt(...) while sliding the window into view) but also positions the window from where the task bar is found at the time of construction. This works even for an auto hidden taskbar. This gives us this final 'sliding behavior' -

  • TB at left: MirandaPlanner comes out in right/bottom corner of the taskbar at the time of construction and goes in at the same spot when hidden or shutdown. This means you have it in the left/bottom corner of your screen.
  • TB at top: MirandaPlanner comes down in right/bottom corner of the taskbar at the time of construction and goes up at the same spot when hidden or shutdown. This means you have it in the right/top corner of your screen.
  • TB at right: MirandaPlanner comes out in left/bottom corner of the taskbar at the time of construction and goes in at the same spot when hidden or shutdown. This means you have it in the right/bottom corner of your screen.
  • TB at bottom: MirandaPlanner comes up in top/right corner of the taskbar at the time of construction and goes down at the same spot when hidden or shutdown. This means you have it in the right/bottom corner of your screen.

MirandaPlanner can not be moved around. It appears and disappears. Moving the taskbar around while running MirandaPlanner will not confuse it. Also, as you can understand, it is always found around the system tray.

Now, back to how it is constructed/killed. After CCalFrameWnd's constructor has returned, OnCreate(...) calls ResourcesCreate() and Init(). The first one does this: m_pCalendar = new CCalendar(this) and approx. the same things go on, once again inside the CCalendar class, creating resources and initializing itself. ResourcesCreate() and Init() in the calendar are both long and rather trivial. Also buttons have this design. When killed UnInit() and ResourcesDestroy() are called - the opposite behavior so to speak. This ensures that all resources are killed and brought back to Windows as is appropriate and needed.

Notes

A day can have 0 or 1 note attached to it. If it has no notes, the edit will be empty and if it has one, the note is displayed in it when the day is selected. Days having a note are marked with a yellow checkmark. All notes are saved as files in a directory called notes. This directory is found in the same directory as Miranda as a subdirectory. You can have as many notes as you like anywhere in time, future and past. You can also navigate in notes using the yellow arrow keys. It works like this. When on a specific day, pressing '>' will show you the next note in the future (if any) and when pressing '<', the previous note in the past (if any). Pressing 'delete' will delete the current note and 'delete+' will delete all notes. You are warned first - see for yourself how this works not using any dialogs. All notes are unique and can coexist because I've named them yyyy.mm.dd.txt. This also gives me the advantage that sorting notes can be made lexically in their class.

All notes are instances of class CNote. This class is really simple and small and for now it only handles operators for <, == and > and a name/title of the note. To enable the calendar to navigate in them, it controls an array of all notes. It looks like this -

class CArrayEx : public CArray<TYPE, ARG_TYPE>
{ ... };
class CSingletonArrayEx : public CArrayEx<TYPE, ARG_TYPE>
{ ... };

Now using class CSingletonArrayEx, it handles (unique) notes. I've made a lazy Sort(...) in the base, sorting ascending in objs saying that a sort is only needed if Add(...) or AddSingletonObj(...) has been called (and not on RemoveSingletonObj(...) fx.). Sort(...) sets the sort-flag in the end to false and Add(...) sets it to true. That's the story for Sort(...) - and I know that my implementation is naive - this is OK.

What can it do?

Wow, do you play with it? Well this is it. With the 5 buttons you see at the top, below the caption holding the month and the year, you are able to go back and forward in time. First one: --1 month or --1 year (on ctrl. held down), second one: --1 day or --1 week (on ctrl. held down), middle one is today and the 2 last do the same as the 2 first, except going into the future. If a (browse) button is held down more than 0.8 s, its function repeats (I fire messages to its parent, if so). You can use the keyboard also. Arrow-keys up/down/left/right navigate in days and pressing the 'Delete' (key) on a day having a note, deletes it as you would expect.

Grayed numbers 18, 19, 20, 21 and 22 are numbers of the (business) week and 1, 2, ..., 31 are the days in the month. The one pressed in the radio group is the display-time - in this case, it's May, the 19'th 2003 *s*.

Arrow keys (light up in yellow on enabled) are made for browsing in notes - days having notes are checked with a yellow checkmark. Below the grayed arrows, you have a rich edit for editing a note, and in the bottom 2 buttons for deleting the current note and all notes. One day can have 0 or 1 note. These buttons also auto repeat.

All notes made are saved in files - one file per day making them all unique because they are named ... '2003.05.17', '2003.05.18', ... '2003.06.01', ... To scroll in the text of a note, use the mousewheel or arrows - I've removed the V-scrollbar for design reasons. Also now (from v.1.10) hovered day-buttons with notes bring up a hint showing you the first 32 characters of the note. A general note is also possible - it's the 'note' button.

See the red book in the system tray. On L-button down, the calendar slides up (depending on the location of the task bar) and the book lights up in bright red. By pressing it again, it slides down and the book is dimmed into a darker red. On R-button down, it shows a menu that has approximately the same things as the window itself. A balloon pops up telling you the date and week# when positioned over the book. At the first time launched, a shortcut is added to your startup folder if you are on W2K.

On double clicking tray icon holding ctrl. down, MirandaPlanner terminates.

Known problems

The menu is a nice XP-style menu from CodeProject itself by Yao Zhifeng. BUT it has some serious problems as I've stated in a thread to him. Unfortunately, he is not that interested in my remarks it seems (what other possible conclusion can I reach?). Even in his test app., the problem arises - menus are wiped clean and corrupted when using keys and that's serious. But it's a nice GUI and therefore I hope to get some response. I've changed it a little so it can show two lines in its vertical box.

Old name 'Miranda' seemed to confuse some people and therefore I've changed it into MirandaPlanner now. Number of versions are inherited from 'Miranda' and continued.

Revision history

  • Rel. 0.990, 18.05.2003. Remarks: Platform was W2K SP2 for the dev. ONLY tested on dev. machine. Dev env. was VS 6.0.
  • Rel. 0.991, 19.05.2003. Remarks: Minor fixes in handling (save/load of) notes. Minor fixes in enabling buttons for browsing notes. Minor fixes in an auto update-timer.
  • Rel. 1.00, 20.05.2003. Remarks: All over fixes and cleanup. Added runtime info. to button class and fixed the release-ver problem. Also now mousewheel-messages go to the edit, no matter what child is holding the focus.
  • Rel. 1.01, 23.05.2003. Remarks: Made ready for _UNICODE compile.
  • Rel. 1.10, 27.05.2003. Remarks: Hover-hints for days having notes (an option), more extensive error handling. From now on, its new name is MirandaPlanner. Versioning is continued. Fixed auto-update once again when running 'today' so that it will go on to the next day by itself.
  • Rel. 1.11, 09.06.2003. Remarks: Autocleanup of dangling hints, on pasting other CHARFORMAT into a note, it retains its original default format (made before pasted text are shown). Fixed error in CTimeEx-class.
  • Rel. 1.20, 12.06.2003. Remarks: Added a general note (see 'note' button.). Made color of check's display in gray if marking notes in the past and yellow if marking notes now or in the future. All over clean-up in the code.
  • Rel. 1.21, 16.06.2003. Remarks: Fixed save-problem when sliding window into invisible. Made enabling of arrow-buttons for browsing notes, consistent.
  • Rel. 1.23, 29.01.2004. Remarks: Fixed leap year problem.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here