Skip to main content
Email Password   helpLost your password?

Sample Image - Ruler.jpg

Introduction

We're building a layout surface and need a ruler by which a user of an application containing the layout surface can judge the size of artifacts such as images, lines and boxes. Though I looked in CodeProject and other places I could not find any rulers written in C#. There are one or two in C++ and in VB but since we want all managed C# code these options did not fit the need so we are writing our own. Its a piece that will probably change as the layout surface project progresses but it may have use for some as it stands.

The image illustrates some sample rulers and the demo allows you to play with various properties to examine their effects.

Note that the ruler is not intended to be a replacement for a phyical ruler. It is not the purpose of the control that, somehow, an inch will be an inch on any display. Rather it is intended to provide a relative measurement. However, 72 points equals 1 inch so assuming that the printer is up to it, a ruler showing 6 inches and printed out should be 6 inches on paper.

Features

The control inherits from System.Windows.Forms.Control and the appearance of the ruler is controlled by 14 exposed a properties in addition to those of the underlying control:

Areas of interest

IMessageFilter

A control will, ordinarily, only receive mouse events when the mouse is over it. In this case, the control must receive mouse event information at all times while mouse tracking is enabled. To do this, the control also implements the interface IMessageFilter and calls Application.AddMessageFilter(this) to hook the message queue. The IMessageFilter interface requires the implementation of one method:

public void PreFilterMessage(Message m) {} 

The implementation in this control acts on all WM_MOUSEMOVE message to determine whether the mouse is within the control x-axis (horizontal ruler) or y-axis bounds (vertical ruler) but not both. If the mouse is with bounds, then:

There are some rulers written in VB that purport to track the mouse. Conveniently VB fires a controls MouseMove() event whereever a mouse moves. However the coordinates are relative to any control the mouse is over so it works fine while over another control that has an origin at the let or top egde of a ruler. But if it is not (like the ruler in Word) then such a control is much less useful. Morever, if the mouse passes over another, contained control, the problem get worse.

These issues do not affect this implementation because the control is looking at all mouse messages and retrieving the mouse position in screen corrdinate so is unaffected by the presence (or not) or ther controls.

Spreading

The main function in the control is the private function DrawControl(). This function draws the control using double-buffering and does so respecting the various property settings. As a result of the settings is it highly likely that the marks to be displayed do not fit conveniently into the number of pixels available. For example, if it is assumed that 53 pixels equals 1 centimeter and the user asks for 8 divisions, there are going to be 5 "spare" pixels. Allocating these pixels to, say, the last division guarantees that this division is going to look odd. Instead, this implementation uses a spreading algorithm such that spare pixels are allocated to divisions more evenly. The basic algorithm is:

int iRemaining = iWholeAmount;
for(i=0; i<iDivisionCount; i++)
{
 int iDivisionsToAllocate = (iDivisionCount-i);
 iAllocation = Convert.ToInt32(Math.Round((double)iRemaining/
   (double)iDivisionsToAllocate, 0));
 iRemaining -= iAllocation;
} 
Applying the algoritm to the example above and you get:
iDivisionCount=8; iWholeAmount=50;

i=0; iDivisionsToAllocate=8; iAllocation=7; iRemaining=46;
i=1; iDivisionsToAllocate=7; iAllocation=7; iRemaining=39;
i=2; iDivisionsToAllocate=6; iAllocation=7; iRemaining=32;
i=3; iDivisionsToAllocate=5; iAllocation=6; iRemaining=26;
i=4; iDivisionsToAllocate=4; iAllocation=7; iRemaining=19;
i=5; iDivisionsToAllocate=3; iAllocation=6; iRemaining=13;
i=6; iDivisionsToAllocate=2; iAllocation=7; iRemaining= 6;
i=7; iDivisionsToAllocate=1; iAllocation=6; iRemaining= 0; 
The actual implementation looks a little more complicated because the user might select a starting value of 1.4. In such a case the spreading must take place from division one but the effect cannot be taken into account until the amount spread is greater than the starting value.

Compiler constants

This code is usually compiled into a project and takes advantage of controls in related libraries. However these cannot be distributed. So the code uses a conditional compilation constant to exclude or replace code as necessary. This constant is FRAMEWORKMENUS and the code will not compile without it being defined.

Updates

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionNumber alignment Pin
Anandkumar.V
2:48 20 Nov '08  
AnswerRe: Number alignment Pin
Bill Seddon
3:09 20 Nov '08  
GeneralProcessor intensive! Pin
pedery
8:13 26 Sep '08  
GeneralFor negative start point scale doesn’t seems to have zero in scale Pin
talk2neeraj
22:17 6 Sep '07  
QuestionCode for setting enumeration to zero at mouse tracking position on mouse double click event Pin
MarkusVon
9:56 13 Jun '07  
AnswerRe: Code for setting enumeration to zero at mouse tracking position on mouse double click event Pin
Bill Seddon
10:05 13 Jun '07  
GeneralRe: Code for setting enumeration to zero at mouse tracking position on mouse double click event Pin
MarkusVon
13:12 13 Jun '07  
GeneralRe: Code for setting enumeration to zero at mouse tracking position on mouse double click event Pin
Bill Seddon
13:18 13 Jun '07  
GeneralTwo small changes [modified] Pin
Tefik Becirovic
1:50 7 Dec '06  
GeneralRe: Two small changes Pin
NikolayNikolaev
0:21 3 Jul '09  
GeneralRe: Two small changes Pin
Tefik Becirovic
21:57 3 Jul '09  
Generalvb version email please Pin
charlievs
11:46 3 Oct '06  
GeneralPretty cool but - what about custom scale??? Pin
thelazydogsback
16:54 4 Aug '06  
GeneralRe: Pretty cool but - what about custom scale??? Pin
LLKrisJ
12:04 14 Dec '08  
GeneralFix for paint and some comments Pin
StephanScheidl
4:35 18 May '06  
GeneralRe: Fix for paint and some comments Pin
Patrick Blackman
12:05 21 Jun '06  
GeneralCool control Pin
Vlad Stanciu
21:58 6 May '06  
GeneralPerfect! Pin
sparky909
2:31 25 Mar '06  
Generalhelp Pin
cooleader
1:07 28 Nov '05  
GeneralRe: help Pin
Bill Seddon
1:12 28 Nov '05  
GeneralREAD ME: Fix to -ve start value bug Pin
Bill Seddon
9:10 30 Sep '05  
GeneralRe: READ ME: Fix to -ve start value bug Pin
laughingandliving
14:47 17 Nov '05  
GeneralRe: READ ME: Fix to -ve start value bug Pin
DotNetSlut
2:33 5 Dec '08  
GeneralRe: READ ME: Fix to -ve start value bug Pin
Bill Seddon
4:20 5 Dec '08  
GeneralVB version Pin
marcrobitaille
7:27 20 Jun '05  


Last Updated 8 Aug 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009