When I first released ToDoList more than 11 years ago it was as a consequence of exploring some UI ideas, the principal of which was using the non-client region of a tree-view control to draw attribute columns.

But while this satisfied my research goal it had a major drawback: The attribute columns could not move independently of the task titles meaning that if you displayed too many columns the task title got squeezed and some of the attribute columns might not be visible.

In addition there was no column reordering or resizing because I would have had to write this from scratch and that seemed too great an effort when the built-in Windows list-view gave you that for free. So I pushed the problem into the background and palmed-away questions as they came up.

Then sometime in 2012 I started to think about creating a Gantt plugin and I realised that the 'tree-part' and the 'bar-part' were going to have to be physically separate because the 'bar-part' was definitely going to need to scroll horizontally but that scrolling could not cause the 'tree-part' to be hidden. And I further realised that solving this might also provide the solution to Task-Tree attribute columns issue.

So I started work on a 'Tree-List-Syncer' whose primary goal was to synchronise the vertical scrolling of either a tree and a list or two lists, positioned side-by-side. Additionally the LHS widget had to hide its vertical scrollbar and instead respond to scroll events from the RHS widget.

The Gantt plugin was released with 6.7 in 2013 and proved successful as a solution yet it still took a couple more versions for me to summon up the courage to pull open the guts of the app to replace the Task-Tree and List-View. I think I was still hoping that the Gantt plugin would reveal a huge flaw in my approach so that I didn't have to do the work!

But here it is. Both the Task-Tree and List-View now have task attributes that can be scrolled horizontally without impacting the task titles. They are divided by a splitter bar (which can be effectively hidden in the preferences) giving total control over 'pane' widths. Attributes columns can be reordered and resized by dragging the column header dividers ala Explorer.

I do understand that some of you will find these changes upsetting but they had to made in order that other more important usability features could be included to keep ToDoList relevant.

Introduction

You know how it is - you start work on one project and halfway through, you find one or two side-projects crop up that have to be solved before you can continue on the original project.

This is one such project with the added twist that it too started its life as a side-project. Here's what happened:

<Cue wavy screen effect>

I can only imagine that the planets must have been in (mis-)alignment or something, because at one point a few months ago, I was suddenly fielding emails on four or five separate articles I had previously submitted to CodeProject, some asking for features and others for bug fixes.

Foolishly or otherwise, I largely agreed with all the points raised, and subsequently found myself with fourteen or fifteen separate issues to resolve.

The situation was also made worse because I was trying to use CodeProject to keep track of all the things I had agreed to do, meaning that I had to continuously trawl the comments section of each article to remind myself of what I was supposed to be working on.

It even got to the stage where I was worrying that I'd fail to deliver on something - silly I know, but there you are!

Keeping a list on paper was a definite step in the right direction, but since I do all my coding on the same machine, it seemed somewhat inelegant, and anyway, we all know what happens to crucial bits of paper left lying around on desks and such.

The next step was to hunt around on the web for a tool to meet the following requirements:

Simple interface

Support for hierarchical data

Numbered items/subitems

Open file format

Freeware

Simple, huh! not!

I will admit that I did not spend weeks searching, but I am still surprised at the general lack of software matching my needs.

On reflection, I think that the reason may be simple: people are so used to commercial software being 'feature-rich' that when they come to design software themselves, they (not unreasonably) think they too need to cram as much in as possible, often leading to software where a lot of essential functionality is hidden away in the menu bar.

So, surprise, surprise, I decided to write something myself.

However, it's fair to say that I did not originally intend to post it on CodeProject and am only really doing so because I had a heap of fun solving some very interesting problems and these are what I think make it worth it.

Using the Software

There's really very little I need to say here since every feature/function is explicitly visible in the interface.

Nevertheless, the following list of basic capabilities and omissions may go someway to answering any questions that arise:

Files are stored in XML format with .xml file extension.

Trying to load a non-tasklist file will generally fail (unless you read the code to see how to circumvent it).

The number of items/subitems is limited only by memory (although performance may be the deciding factor before you exhaust memory).

Marking a parent item as 'done' will also gray-out child items, but they are not disabled or automatically marked as 'done'.

An ellipsis (...) indicates that an item has sub-items.

All items can be expanded or collapsed (by double-clicking).

Top-level items and sub-items are created using different toolbar buttons.

There are task-specific context-menus.

The previously open tasklists are re-opened on startup.

The tasklist is automatically saved when closing the software or minimizing it to the system tray.

The priority of a task is shown as a grayscale box to the left of the item.

Points of Interest

Here's where we come to the side-projects I was talking about, the first two of which I intend to work up into follow-up articles.

They are:

The 'ordered' tree control, which incorporates a non-client gutter for displaying the item numbers.

The idea stemmed from research I did into alternative designs for a tree-list control, which did not solve it by creating a hybrid control incorporating a tree and a list.

The hybrid control seems such an obvious solution that I suspect few people have stopped to question it, but it has still always struck me as looking far too much like hard work to be truly elegant ('square pegs' and 'round holes' spring to mind).

One possible idea is to implement the 'list' portion entirely in the non-client area of the tree. I.e., shift the right hand client edge to the left and then render the list portion in the resulting non-client area.

Whilst I've yet to get round to building a proof of concept, it was nevertheless this ongoing mental debate which prompted me to try to solve the requirement for numbered items and subitems by rendering the item/subitem numbers in the non-client area.

Without going into too much detail (as this will subsequently be an article of its own), this is how I got it to work:

Handle TVM_INSERTITEM and TVM_DELETEITEM to know exactly when items are added and removed.

In these handlers recalculate the width of the gutter required to display the widest 'dotted' item/subitem number. (Note: this is not necessarily simply the deepest subitem.)

Handle WM_NCCALCSIZE when it does, and offset the left border by the required gutter width.

Handle WM_NCPAINT for painting the numbers.

This is necessarily an over-simplification, but it captures the essence of the solution, and all that essentially remains is lots of fiddling about to ensure the non-client area gets redrawn at the the right times to stay synchronized with the client area.

Embedding .RC control definition data directly in a .cpp file to break the dependency on binary resources (a.k.a. 'Runtime Dialogs').

This is an idea that has been floating about for quite some time and which has only recently gelled into a workable solution.

The problem, put simply, is that if you want to take advantage of the resource editor in Visual Studio (and who doesn't), then you very quickly find yourself stuck with having to load dialog templates from resources compiled into the binary file.

This further means that if you want to make use of a dialog across multiple projects, then either you need to copy and paste the dialog template between project .RC files, or you need to build the dialog into a DLL from which it can be accessed.

'Runtime Dialogs' (a snappy title I coined myself) is a solution that neatly sidesteps both the nuisance of copying dialog resources between resource files and the extra work (and maintenance) involved in packaging dialogs in DLLs.

And it works like this:

First, you design your dialog template in the resource editor, create a CDialog derived class using class wizard, and wire up all the controls just as you normally would.

Next, you #include "runtimedlg.h" and change all instances of CDialog to CRuntimeDlg.

Then, you cut and paste the control definition section from the appropriate section in the .RC file and embed it directly in the dialog's .cpp file as a static string (with a bit of tweaking to handle double quotes and such like).

Finally, in the constructor of your dialog, you simply call CRuntimeDlg::AddRCControls(...) passing the control definitions as a string.

And CRuntimeDlg takes care of the rest including, if required, auto-sizing the dialog to suit the control layout.

I'm certainly not suggesting that this is a 'win-win' solution for all situations but it certainly has merits in its closer coupling of dialog template to dialog code which makes sharing dialogs across multiple projects a breeze.

P.S.: In case it's not clear here, I used CRuntimeDlg to create CToDoCtrl which encapsulates the ordered tree together with the priority, date and comments controls as a single simple-to-instantiate control.

This is possibly the most satisfying aspect of the whole project because it was completely unexpected.

What I mean is that, until recently, my knowledge of DOM and XMLDOM was virtually non-existent, as it's only since I've become more interested in the presentation of AbstractSpoon that I've been forced to get to grips with the various implementations of DOM and XMLDOM out there.

I'm pleased to say that the code on my site works under IE 6.0, Netscape 7.1, and Mozilla, although custom code was required to achieve this.

Generic MFC Classes that may prove Useful to You

The following table lists a wide range of utility classes written for this project. They can all be included in any MFC project provided you include any class dependencies too. Feel free to ask any questions relating to these specific classes and how to use them.

Adds support for recognizing urls, clicking them and setting custom url callbacks

CWinClasses

Encapsulates the ::GetClassName Win32 functions

CXmlFile, CXmlItem

Non-Unicode class for reading and writing xml files

CXmlFileEx

Adds encryption capabilities to CXmlFile

CXmlFile, IEncryption

* CSubclassWnd was originally written by Paul DiLascia for MSJ magazine. The version I use has been heavily extended to suit my specific needs. The classes that depend on it here need this extended version.

Further Work

Whilst this tool was originally intended for my personal use only, it is now a 'community' project, so if you find it useful and want to make suggestions for enhancements or bug fixes, then post below.

History

7.0.13 (04 Feb 2016) - Mostly likely the last update of 7.0

Fixed uneven task row heights on Windows XP 64-bit

Fixed incorrect strike-through in Find Tasks dialog for incomplete parent tasks having all their subtasks completed

Fixed doubled-up Help Menu separator on XP

Fixed translation 'Cleanup' button not saving changes

Fixed XML encoding for Unicode tasklists

Fixed tasklist tab-bar resize bug after double-clicking on titlebar

7.0.12.1 (20 Jan 2016)

Fixed loading of Ansi tasklists

7.0.12 (14 Jan 2016)

Fixed bug where pasting a text fragment from Firefox would display the wrong source URL

Fixed List View selection render artifacts in full screen when resizing the title pane

Fixed inability to tab to Status field after making the field 'read-only'

Dan, I've had it my, uh, ToDoList to get back to you on this. I've had a number of starts and stops, using TDL to track client time, so I don't have extensive CSV logs to send you.

It takes time to form good habits:

- I start working on something, or reading a long email, or I get a phone call.- I look up the task list for the client, find an existing task or create a new one.- Decision: Is this an existing task, new activity under an existing project, or a totally new task.- Find or create, start the clock. (Auto-stops clock for any other task.)

I haven't yet gotten into the habit of exchanging data between the Android TDL app and the desktop, but I'd like to do that soon so that when I'm AFK I can still log my time.

So we have all of our time in CSVs, one file per client. When reporting to clients, they don't need the exact start/stop day/time, they just want to know the task and time for any given day. So the CSVs constantly need to be reformatted into another format.

I use the Export option to create a CSV of the tasklist, convert that to XSLT. Then I open my log.CSV. I have formulas which take the task ID from the log to xref against the exported tasklist to get a full path description of the task. For example, where task #102 is "Add User ID", I like to show my clients:... New partner portal > Reports > Recent Activity > Add User ID ...

Export allows creation of a CSV with custom fields. Great.The time log is fixed (modifiable through code of course but not via configuration).I'm looking for an elegant way to relate those files, to create a third document which includes just the information I want for clients.

If we could get more data into an XML export, then all of this could be done via XSLT. Example:- Task ID- Task Name- User ID- Start Date/Time, End Date/Time- Time SpentBut note that each log detail item needs to be nested in parent task nodes, the exact same structure as .TDL files.

I'm certainly open to other ideas, that's where my thoughts have led so far. I've been waiting for some time to write this out. As a C#/Java developer I'm prepared to write a utility that will re-process the data into a new XML document for subsequent transformation. But I don't want to start that until I know what you're planning.

I have set rich text as default in the comment field. When I copy rich text--whether from ToDoList or from another application--and paste it with "Paste (Normal)" into the comment field, its formatting, e.g., bold or italic type, underlining, indentation, list markers such as bullets and numbers, etc.--is gone. (This issue seems to have started occurring recently--I don't remember noticing it before.)

This is a bit off the topic: regarding the 2 paste choices for the comment field, "Paste (Normal)" and "Paste Simple", would it be possible to move them from the submenu to the main context menu--like the way the 3 paste options are positioned on the right-click menu for the tasktree--so that one could get to them with one fewer step? (I know I could type Ctrl+V, but I'm one of those keyboard-shortcut-challenged PC users who would choose clicking over typing whenever possible! )

On an old machine I had 6.7.8 - pressed "update" - Info: Do you want to update to 6.8.1?" - Answer: Yes - Update starts and works fine - Info: "Current version is 6.8. To you want to update?" - Yes - and again - and again ....

a, b, c show different results, but - a and b should show the same results- why c (complete) shows a number of "Incomplete Tasks"The following filters d) - f) displays always the same result from the previous selected filter (of a - c).

Same is with user-defined filters: Some show real(?) results, some (e.g. the filter "modified today") display nothing but the result of the previous filter.

Maybe I misunderstand the entire feature, but how should it work? What should be displayed, what not? What could be "wiped out", what is the right usage of filters?

From the earliest completion date to the latest completion, rounded to suit the date display resolution, which itself is calculated from the available graph width.

Pierre de la Verre wrote:

a, b, c show different results,

A burndown essentially displays the amount of work remaining as a function of time, where in our case the 'amount of work left to do' == 'number of incomplete tasks'. And in order to plot changes to the number of incomplete tasks, we also need information about when tasks are completed.

Therefore:

1. If the filter is set to 'All Tasks', the line will rise and fall as tasks are added and completed.2. If the filter is set to 'Incomplete Tasks' then the line will only ever rise because there are no completed tasks in the filter3. If the filter is set to 'Completed Tasks' then there will be an initial rise as tasks are added, after which the line will always eventually drop to zero because there are no incomplete tasks in the filter

So IMO the behaviour is correct even if not intuitive, and so long as you understand how it works, there may be value in all the filters.

I use the comment field very often, and have these 3 items on my wishlist for it:

1. Make the font picker show the default font and the recently-/frequently-used fonts in a section at the top of the font list.2. Make the text- and background-colour pickers retain the last-selected colors.3. Add a button for a horizontal-line separator, which can be wordwrapped like text as the comment field gets resized.

Lock = Read mode onlyUnlock = Read and Edit modeI think it is very useful because for example to securely store access passwords and codes in Comments and Title fields.In those cases is Unwanted any Editing and Accidental Deletion too.

I'll add a wish here too: An option that allows Ctrl-D (date/time stamp) to be followed by an optional character. In my case I'd like a Space. I frequently ctrl-D and then start typing, but I need to remember Ctrl-D+Space+text... Hey, I know it's stupid and trivial but things like this happen.

Right now, the "Maximize Tasklists" button is designed to toggle only between the maximized tasklist and the normal view. Could we have the "maximized comment field" view added to it, or could we maybe get a separate "Maximize Comments" button? Either way might be quicker than going to the View menu or using keyboard shortcuts.

In connection with maximizing the comment field, could you please also consider adding the option to show tasks (probably without the task-attribute columns) even when the comment field is maximized, to commplement "Show comments even when tasklist is maximized"?

Right now, the "Maximize Tasklists" button is designed to toggle only between the maximized tasklist and the normal view.

You can choose if only the tasklist gets maximized (=the edit fields are not shown) or if you want the comment field to be shown or not: Preferences>User Interface>Task Comments>Show comments even when tasklist is maximized.

Personally I doubt that hitting a button with the mouse is much quicker than using a shortcut since you have to move the mouse first to the button, but if you like to have a button "maximize comment field" you can add such a button: Preferences>User defined tools>new tool.

The 'tool' would be a very simple Autohotkey (AHK) script that you can use directly or make an exe file of it:

Send, {CTRLDOWN}{SHIFTDOWN}m{CTRLUP}{SHIFTUP}

This script assumes that the shortcut for maximizing the comments is 'CTRL+SHIFT+m'

If you like another icon than the typical AHK-icon: You'll find that easily in the www. I'd choose 16x16.

Please excuse my total inexperience with TDL's user-defined tools and autohotkey scripts. I did the following in Preferences>User defined tools>new tool:

1. Clicked "New Tool," and pasted "{CTRLDOWN}{SHIFTDOWN}m{CTRLUP}{SHIFTUP}" into the "Arguments" field;2, In the "Icon" field, browsed to one of the downloaded 16x16 ICO files and selected it; 3. Left the "Path" field blank;4. Edited the New Tool name into "Maximize Comments."

Then, after I clicked "Apply" and "OK", the new icon appeared next to the Preferences button, but clicking it only brought up a Windows Explorer window showing my TDL files, instead of maximizing the comment field. I must have blundered somewhere in the above process. Please enlighten me. Thanks!

1. Go to the autohotkey website (www.autohotkey.com[^])2. Download the little program and install it. It's useful for a thousand things you want to automate.3. Create a simple textfile (eg. maximize.txt). Open it and paste this code exactly into it:

Send, {CTRLDOWN}{SHIFTDOWN}m{CTRLUP}{SHIFTUP}

4. Save the file to a folder (e.g. to a sub folder of ToDoList that you can call 'scripts' 5. Rename the file to (eg. maximize.ahk)6. Put the icon you like to use for this script in the same folder (call it e.g. maximize.ico)

Done. That was the hard part

7. Now create a new tool in ToDoList.8. Put the path to your new tool and the name of the tool in the field 'path' (e.g. C:\ToDoList\scripts\maximize.ahk)9. Choose the icon in the 'icon field'.10. Hit: 'ok'.

Done. This time completely.

Enjoy.

P.S. Make sure that the CTRL+Shift+m is the assigned (preferences>Keyboard shortcuts>maximize comments). If it is not assigned assign it. Type this shortcut (by just pressing the keys!) in the field 'type the new shortcut key'. Hit the button 'assign' and then o.k.

And many thanks for introducing me to AutoHotkey, indeed a very useful tool, which will probably allow me to pester Dan less with simple feature requests, so that he may focus on the more important parts of ToDoList!

May I trouble you with a follow-up question about using AutoHotkey with user-defined tools in TDL: can one use it only with those commands listed in Keyboard Shortcuts in the preferences?

The question came out of my second sally into scripting with AutoHotkey: again following your helpful instructions, I made a script for "expand all tasks" (Ctrl+Shift+E), and, seeing that it is not togglable between the "expanded" and "collapsed" states, I made a second one for "collapse all tasks" (Ctrl+Shift+C). Expand All Tasks works fine, but Collapse All Tasks sometimes gets stuck for some reason, and needs to be "kick-started" by my manually collapsing one of the expanded tasks first.

Not being able to figure out what's causing that problem, I thought that if I could make a single command button do the work of two--i.e., make a togglable command, "Toggle Expanding and Collapsing All Tasks" (just like the togglable "Maximize Tasklists" or "Maximize Comments"), I would be able to side-step the whole issue, and also simplify the "clicking experience." But "toggle expanding and collapsing all tasks" is not one of listed commands in Keyboard Shortcuts; there is "Toggle Task Expanded State," but that seems to be for selected tasks only, and not for all tasks.

Hence the question: is it possible to modify one of the listed commands (and even to include a new one), then assign a keyboard shortcut to the modified (or new) command, and apply AHK to it?

1. is it possible to modify one of the listed commands (and even to include a new one), then assign a keyboard shortcut to the modified (or new) command, and apply AHK to it?

Notetaker wrote:

2. can one use it only with those commands listed in Keyboard Shortcuts in the preferences?

Basically: It is not possible to modify the listed commands. Otherwise you would have to rewrite the code of ToDoList.That is to say: if ToDoList doesn't offer a command like: "Toggle Task Expanded state for all tasks" there is none.

In this case you can ask Dan offer such a command or you try to find a workaround.

There is a workaround and this is the answer to question 2.

Regarding the toggling of the tasks: What you want to do is to combine commands.I'll give you a quick solution; not a very elegant one, but it works.

The combination of commands:1. The toggle command of ToDoList expands or collapses all tasks that are selected. The first step therefore is to select them all if you want to work on the whole list.2. Then we toggle the state of all tasks3. Since everything is selected now we have to move the cursor to de-select the tasks. There is no command for that.

; lines with a semi-colon at the beginning are comments
SetTitleMatchMode, 2
#IfWinActive, AbstractSpoon
PostMessage, 0x111, 34183,,, AbstractSpoon ; selects all tasks
Postmessage, 0x111, 34264,,, AbstractSpoon ; toggles the state
; Sleep, 10
; if you have plenty of tasks and a complex structure it might be necessary to activate the line
; with the sleep command and play with the number = make it larger
SendInput, {down}{up} ; moves the cursor to de-select the tasks
#IfWinActive

I have a feeling this is way over my head though! I'll save it for later, when I'll have more time to attempt it. Meanwhile, I'm very tempted to take the easy way out, asking Dan to add the "Toggle expanding and collapsing all tasks" to the keyboard command list.

You do not have to understand the code at this very moment to use it. Just copy the code in a textfile, rename the extension to 'ahk', create a new tool and find yourself an icon. That's all. Just like you did the last time.

Most users are not familiar with XSLT, and therefore, are not able Format Output to their Needs. Is there a tool available to WYSIWYG-compose XSLT for Output. Or, can any other Technology be utilized to achieve the Goal?

On updating Web Update Wizard - Common Build stops work, cannot resume the process and unzip the contents of the update zip.Unzipping 'WebUpdateSvc.exe' is not responding.The problem can be solved only by manual download and unzipping the new files.

I just fired up my PC. TDL usually starts in the tray, then loads my lists.

This time it came up to ask me my language and there is no recent list. The ini file reset itself. I lost preferences, user-defined tools, custom keys, etc.

I ensured the program was closed, copied a backup ini in from a few days ago, restarted TDL, and it doesn't seem to be reading that file at all.

I can reinstall and reinstate my ini but I'd rather keep this environment preserved to help diagnose the issue. I can also just install to another path and preserve the original. But I'd rather work through the problem.

This issue has been reported sporadically and I've no immediate solution but what I can say is that the fact that it asks for the language but doesn't display the setup dialog suggests it's stuck in an intermediate state.

Whilst I look at the code, can you send me the ini file pls?

ps. Not showing the 'Setup' dialog suggests that it knows the ini file is there, but displaying the 'Language' dialog suggests it can't read it, so maybe it's been truncated to zero length.

Well... Couldn't help myself. Promising signs - it is a portable app (important to get around work software restrictions), and it runs by itself without VS2005.

Unfortunately it is an xml editor. You load an xml file, load a xsl stylesheet, and it transforms it to HTML. You can then edit the XML, NOT the stylesheet. So effectively, in creating stylesheets, it takes the place of TDL in the process.It would be fantastic if it had a third tab, for showing / editing the xsl...

Also, I notice it gives different results to TDL. It shows some colour backgrounds the print preview doesn't, but seems to miss the odd piece of information in the heading, and doesn't seems to recognise rich text comments.

So it might be useful for some, but not really for the creation of stylesheets. zajchapp

If you scroll down on the page, it notes a free version. Haven't investigated further though, to know if it suits. "Download EditiX Free XML Editor 2008, Lite Version" - <a href=http://www.freexmleditorsite.com/download.html">http://www.freexmleditorsite.com/download.html