Archive for June, 2006

Analogue Clock

Wednesday, June 21st, 2006

There are quite a few examples of C# analogue clock components or programs out there on the Interweb, and here’s another one. This one is slightly different in that it takes the form of a widget. I wrote this example for a few reasons:

  1. I have recently resigned from my job, and had nothing to do to while away the working hours
  2. I wanted to get some more experience in C#
  3. My girlfriend was jealous of the “fuzzy clock” on the Fedora Core 5 desktop, so I thought I’d write her one for her Windows desktop.
Here’s what the clock looks like:

Analogue Clock

The AnalogueClock program in written in C# and compiled under Visual Studio 2005. You may download the source to the application here.

The application window is made circular by setting the window’s Region property in it’s OnLoad event. This is acheived by creating a GraphicsPath object, adding an ellipse to the GraphicsPath. By creating a region from this GraphicsPath, and assigning it to the form:
this.Region = new Region( graphicsPath );
We can create a circular form without borders or a title bar, onto which we can draw our clock face. This corresponds to the Win32 SetWindowRegion function, and limits the areas of the form that are a) visible and b) respond to mouse events.
The old way to drag move and drag a window around by clicking on it’s client area was to write a new message handler for the WM_NCHITTEST message. To acheive this in C# we need to override the form’s WndProc method, and set the result of any WM_NCHITTEST messages received to HTCAPTION. One side-effect of this is that our form will no longer receive WM_LBUTTONDOWN or WM_RBUTTONDOWN messages, and therefore our right-click context menu will no longer appear. Instead, the form receives WM_NCRBUTTONDOWN (non-client area right mouse button down) messages, and we may intercept these in our new WndProc method and cause the context menu to pop-up manually:
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCHITTEST:
{
m.Result = new IntPtr(HTCAPTION);
break;
}
case WM_NCRBUTTONDOWN:
{
this.contextMenuStrip1.Show(new Point(m.LParam.ToInt32()));
break;
}
default:
{
base.WndProc(ref m);
break;
}
}
}

More Meaningful Variable Names

Monday, June 5th, 2006

Sorry, don’t mean to moan and whinge. Just couldn’t let these slip by without giving them an honourable mention:

procedure TDMInvRep_d.Synch_ADSBK_AA;
begin
ADSBK_AA.Close;
ADSBK_AA.Parameters.ParamByName(‘pclient’).Value := FClientNo;
ADSBK_AA.Open;
end;

QSECHOLD_WHERE = ‘ WHERE S.ClientNum = :pclient2 and (S.ExcludeFromReports <> ‘ + QQQ + ‘Y’ + QQQ + ‘)’;

wwQSECH_AAbAA_CA_D.AsFloat := (wwQSECH_AAbAA_CA.AsFloat / 100) * d;
wwQSECH_AAbAA_FI_D.AsFloat := (wwQSECH_AAbAA_FI.AsFloat / 100) * d;

I can pick almost any unit from the source code to this project, and find countless examples just like those above. I love this job.