Exploring the TimeCheck Application (Part 5)

Someone reported a problem with last week’s post (see Exploring the TimeCheck Application (Part 4)). It seems that frmReportConfigure has an accessibility problem. Even though the form doesn’t have any functionality built into it just yet, you can compile and run the application to see the problem. Try pressing Tab to move between the radio buttons. You’ll find that you can’t use the Tab key to select Project Report or Totals Report when User Report is selected. The same thing happens with the other selections. It’s impossible to use the Tab to move between the radio buttons even though the application is supposed to make each of the radio buttons a tab stop. Now, imagine that the Tab is your only means of navigating the form (or simply that you’re used to using the keyboard and using the mouse is normally too time consuming to meet your needs).

The problem is that pressing Tab after User Report has the focus selects Selected User. Press Tab again and you move to User’s Project, then to User’s Task, and then back to Close. What’s happening? At first I thought a change in tab order (TabIndex property setting) might do the trick, but that’s not the case. Then I thought about making just the radio buttons tab stops by setting the TabStop property on the ComboBox controls to False. However, not only does this break accessibility, but it didn’t solve the radio button problem. In fact, I spent several hours considering various solutions to the problem. None of the configuration changes I made corrected the problem. If someone has a configuration solution to the problem, please write me at John@JohnMuellerBooks.com.

I finally created a coded fix for the problem. When the user presses Tab on the Close button, the focus should always go to User Report. Likewise, when the user presses Tab for an unchecked radio button, the focus should go to the next radio button in line. When a radio button is checked, the focus should go to the controls associated with the radio button, and then move to the next radio button after the last control. With this in mind, I fixed the accessibility issue on this forum using the following code.

private void btnClose_Leave(object sender, EventArgs e)
{
   // Give the User Report radio button focus.
   rbUser.Focus();
}
 
private void rbUser_Leave(object sender, EventArgs e)
{
   // When User Report isn't checked, then give the focus
   // to the Project Report radio button.
   if (!rbUser.Checked)
      rbProject.Focus();
}
 
private void cbUserTask_Leave(object sender, EventArgs e)
{
   // Give the Project Report radio button focus.
   rbProject.Focus();
}
 
private void rbProject_Leave(object sender, EventArgs e)
{
   // When Project Report isn't checked, then give the focus
   // to the Totals Report radio button.
   if (!rbProject.Checked)
      rbTotals.Focus();
}
 
private void cbSelectedProject_Leave(object sender, EventArgs e)
{
   // Give the Totals Report radio button focus.
   rbTotals.Focus();
}

I appreciate readers keeping me on my toes, especially when it comes to accessibility issues. Next week, we’ll move on to building the database elements for this application. In the meantime, don’t be afraid to write with your questions and comments. You can read the next post in this series at Exploring the TimeCheck Application (Part 6).

 

Exploring the TimeCheck Application (Part 4)

Unlike many of the other applications I create for myself, this one isn’t any good without reports. It doesn’t do any good to track the time spent on a project when there isn’t any way to account for the time afterward. This post builds on the interfaces built in Exploring the TimeCheck Application (Part 2) and Exploring the TimeCheck Application (Part 3).

When it comes to reporting, people have all sorts of criteria on which to sort, filter, and display information. TimeCheck isn’t a complex program, but I still need a number of reports to make the information useful. With this in mind, I can create these reports using the current implementation of the application.

 

  • Total user hours by project.
  • Individual user login entries by project with a total.
  • Individual user login entries by project for a specific task with a total.
  • Individual user login entries by task with a total.
  • Total project hours for all users grouped by machine with the individual hours for each user.
  • Total hours for each machine.


When a user clicks Report on frmMain, the application must determine which of these reports to present. So, the application displays this configuration dialog box, frmReportConfigure, first (you add it using the same technique as shown for frmConfigure in the Exploring the TimeCheck Application (Part 3) post).

TimeCheck0401

Not all of these options will be available for regular users. Administrators will see all of these options, but a regular user will be limited to seeing the statistics for his/her login entries. Later, you’ll see that the Project Report and Totals Report options don’t even appear to a standard user and that the Selected User field is set to the logged in user’s name. So a regular user can see all his/her entries, those for a specific project, those for a specific task, or those for a specific task related to a particular project. The following table shows how to configure this form.

Control Property Value
Form1 (Name) frmReportConfigure
  AcceptButton btnShowReport
  CancelButton btnClose
  FormBorderStyle FixedDialog
  Size 300, 336
  Text Configure a Report
ToolTip1 (Name) toolTip1
Button1 (Name) btnShowReport
  AccessibleDescription Show the Requested Report
  Location 196, 12
  Size 85, 23
  TabIndex 0
  Text &Show Report
  ToolTip on toolTip1 Show the Requested Report
Button2 (Name) btnClose
  AccessibleDescription Close the Form Without Creating a Report
  DialogResult Cancel
  Location 196, 41
  Size 85, 23
  TabIndex 1
  Text &Close
  ToolTip on toolTip1 Close the Form Without Creating a Report
RadioButton1 (Name) rbUser
  AccessibleDescription Generate an Individual User Report
  Checked True
  Location 12, 12
  Size 104, 24
  TabIndex 2
  TabStop True
  Text &User Report
  ToolTip on toolTip1 Generate an Individual User Report
Label1 (Name) lblSelectedUser
  Location 31, 39
  Size 74, 13
  TabIndex 3
  Text S&elected User
ComboBox1 (Name) cbSelectedUser
  AccessibleDescription Provides a User Name for the Report
  DropDownStyle DropDownList
  Location 34, 55
  Size 155, 21
  TabIndex 4
  ToolTip on toolTip1 Provides a User Name for the Report
Label2 (Name) lblUserProject
  Location 31, 79
  Size 72, 13
  TabIndex 5
  Text User’s Pr&oject
ComboBox2 (Name) cbUserProject
  AccessibleDescription Defines Which User Project Log to Select
  DropDownStyle DropDownList
  Location 34, 95
  Size 155, 21
  TabIndex 6
  ToolTip on toolTip1 Defines Which User Project Log to Select
Label3 (Name) lblUserTask
  Location 31, 119
  Size 63, 13
  TabIndex 7
  Text User’s T&ask
ComboBox3 (Name) cbUserTask
  AccessibleDescription Defines Which User Task to Select
  DropDownStyle DropDownList
  Location 34, 135
  Size 155, 21
  TabIndex 8
  ToolTip on toolTip1 Defines Which User Task to Select
RadioButton2 (Name) rbProject
  AccessibleDescription Generate an Individual Project Report
  Location 12, 162
  Size 104, 24
  TabIndex 9
  TabStop True
  Text &Project Report
  ToolTip on toolTip1 Generate an Individual Project Report
Label4 (Name) lblSelectedProject
  Enabled False
  Location 31, 189
  Size 85, 13
  TabIndex 10
  Text Se&lected Project
ComboBox4 (Name) cbSelectedProject
  AccessibleDescription Provides a Project Name for the Report
  DropDownStyle DropDownList
  Enabled False
  Location 34, 205
  Size 155, 21
  TabIndex 11
  ToolTip on toolTip1 Provides a Project Name for the Report
RadioButton3 (Name) rbTotals
  AccessibleDescription Generate an Individual Machine Report
  Location 12, 232
  Size 104, 24
  TabIndex 12
  TabStop True
  Text &Totals Report
  ToolTip on toolTip1 Generate an Individual Machine Report
Label5 (Name) lblSelectedMachine
  Enabled False
  Location 31, 259
  Size 93, 13
  TabIndex 13
  Text Selected &Machine
ComboBox5 (Name) cbSelectedMachine
  AccessibleDescription Provides a Machine Name for the Report
  DropDownStyle DropDownList
  Enabled False
  Location 34, 275
  Size 155, 21
  TabIndex 14
  ToolTip on toolTip1 Provides a Machine Name for the Report

After the user configures the report, clicking Show Report displays the report on screen. There are many different ways to display the report information. TimeCheck uses a simple method for display because the report isn’t used anywhere except to obtain information for my personal use. This is one area where you may need to add your own embellishments (or I’ll be happy to explore them as part of any eBook I create for this application later). Here’s the simple frmReport dialog box (you can add this dialog box using the same technique as described earlier).

TimeCheck0402

The report appears in the RichTextEdit control. This particular dialog box is resizeable, so you can see the entire report. The following table describes the configuration for this dialog box.

Control Property Value
Form1 (Name) frmReport
  AcceptButton btnClose
  CancelButton btnClose
  Size 300, 300
  Text Configure a Report
ToolTip1 (Name) toolTip1
Button1 (Name) btnClose
  AccessibleDescription Closes the Report Dialog
  Anchor Top, Right
  DialogResult Cancel
  Location 197, 12
  Size 75, 23
  TabIndex 0
  Text &Close
  ToolTip on toolTip1 Closes the Report Dialog
RichTextEdit1 (Name) Report
  AccessibleDescription Contains the Report
  Anchor Top, Bottom, Left, Right
  Font Courier New, 10pt
  Location 12, 12
  ReadOnly True
  Size 179, 238
  TabIndex 1
  ToolTip on toolTip1 Contains the Report

Because this form is resizeable, you need to make some changes to the Anchor property to ensure that the controls resize as they should. The report also relies on a mono-spaced font to make aligning the content easier, so you need to change the Font property. If you wanted, you could make the report a lot fancier, but it would also require more code in order to provide a nice presentation.

At this point, you have all of the dialogs for this application created. Next week we’ll begin looking at the application code. This example has a few surprises due the security concerns and also because it stores data on a network (if desired). In addition, it relies on a hierarchy of folders to hold the data because you have to account for machines, users on those machines, and projects that the users work on. In the meantime, let me know about any questions you have configuring the forms for this application at John@JohnMuellerBooks.com.