1. Introduction to Coordinates & Mapping Modes
MFC supports two kinds of coordinate systems. One is Device Coordinate and the other one is Logical Coordinate. In device coordinate, we point out all in terms of pixels. In logical coordinate, we measure each unit in terms of Metric Standard or British Standard. How each unit maps to the logical measure is called the mapping. We can mention the mapping using the Mapping Modes. In MFC, having the knowledge of Drawing Origin is the key to draw in the Client Area the way you want.
In this Example, we will walk through the examples and demo videos, which will help us in learning the Mapping Modes and doing the MFC drawing using the device contexts. We will also try the ViewPort Origin and Window Origin and how to use them while drawing using MFC GDI APIs.
2. Three MFC Coordinate Systems
The first step is creating the SDI Application with no document view architecture support. Once the application is ready, we can start our drawing using the OnPaint() handler. Now, have a look at the below picture:
In the above picture, the black screen is the desktop. Top left corner of the desktop (P1) is the Origin of the Screen Coordinate. The notepad application is displaying on top of the desktop screen. Point P2 specifies the Origin of the notepad window. We can say P2 is the origin of the Window Coordinate system. If there are three windows in the desktop area, then three such Window Coordinate exits. Means, one for each window. The client area of the window is nothing but the working area of the window. In the notepad’s case, the actual working area is the portion of the window in which we type our text content. Point P3 specifies the Origin of the Client Coordinate system. In these three Coordinate Systems, we can use the Device or Logical units. In Device Coordinate, MFC measures the drawing units in terms of pixels.
Below piece of code, we will start with the client coordinate and then will move to Mapping Mode and Logical Coordinate based drawing.
1 2 |
CRect rct; GetClientRect(&rct); |
When we run the SDI application it looks like below (Resized):
The screen marked in blue is termed as client area of the window.
GetClientRect()
function will help in getting the rectangular marked as blue in the above depiction. The function will get four values Left, Top, Right and Bottom and the picture also shows this above. Look at the below video that debugs and examines value after calling
GetClientRect()
function.
Video 1: Shows GetClientRect getting the Values in Device Units (Pixels)
3. Mapping Modes – MMISOTROPIC & MMANISOTROPIC
The Mapping Modes are useful to perform the real-world drawing. Say for example; let us say you are making software utility to perform an engineering drawing. When the drawing is printed out, you want to see the 10 mm line drawn in your monitor, measured as 10 mm in the hard copy, taken from the printer. Here, we need to represent how a single drawing unit measures to the real-world measuring standards. MFC supports eight mapping modes. The below picture shows these Mapping Modes:
For MM_TEXT Mapping Mode, the positive X moves from the default top left corner origin to the right side. This is true for other Modes as well. The picture shows how Y coordinate direction changes based on the mapping mode. MM_ISOTROPIC and MM_ANISOTROPIC have a user-defined coordinate system. In MM_ISOTROPIC MFC equally measures both x and y units. But in the MM_ANISOTROPIC mode X and Y can have different units of scale. The above picture shows for a given Mapping Mode how MFC calculates a single logical unit. The MM_TEXT mapping mode is the default mapping mode used by MFC. Using the SetMapMode function of the underlying Device Context, you can pick any of the mapping modes shown above.
A Device Context is Bag of Tools which defines property for the drawing action. It is a data structure in MFC. Let us say Drawing Board in a meeting room. The properties here are: White Drawing Board, Pen and it color, its thickness. Likewise, Device Context defines all the properties required for the drawing.
4. Drawing a Line Using MM_TEXT Mapping Mode
In the
OnPaint
handler, let us draw a line using
MM_TEXT
Mapping Mode. Remember from the previous picture that each unit you specify to the drawing function represents a pixel. For an example, if the length of line 100 means, it is 100 pixels long as the Mapping Mode is
MM_TEXT
. Next thing we should remember is that the origin is in the upper-left corner of the window. Here, Positive Y goes down. So for seeing the drawing of what we draw, we should specify both x & y units in positives (Look at the picture for reference). OK, let us draw a line. Have a look at the below code:
1 2 3 |
//Sample 02: Draw Line and see where the Origin is. dc.MoveTo(0,0); dc.LineTo(100,100); |
In the above code, first, we moved the drawing pen to the Origin 0,0 using
MoveTo
function. Then we asked MFC to draw a line by specifying the end point as 100,100 to the function
LineTo
. When we run the Example, we can see a line from origin 0,0 to the point at 100,100. This can be illustrated something like the below one:
For more explanation on how this work, watch the youtube video below.
Video 2: Drawing Using MM_TEXT Mapping Mode
What happens if we change the Mapping Mode from the default MM_TEXT to MM_LOMETRIC? The first thing one should know is that the Unit of measure changes from pixels to a millimetre. The second thing is that the Positive Y axis shifts its direction. Below is the Example that uses the MM_LOMETRIC as the mapping mode:
1 2 3 4 |
//Sample 03: Set New Mapping Mode dc.SetMapMode(MM_LOMETRIC); dc.MoveTo(0,0); dc.LineTo(100,-100); |
For More explanation look at the video below:
Video 3: Change the Mapping Mode to MM_LOMETRIC
5. Shifting Drawing Origin Via SetViewportOrg
In the previous examples, we saw that how we can set the Mapping Modes on the Device Context. Also, in the previous examples, MFC kept the drawing origin in the top left corner of the window which is the default origin. Device Context has the capability of changing this origin from the default left corner. We can do that via the
SetViewPortOrg
function call.
5.1 MFC SetViewportOrg Example
SetViewPortOrg
function expects the new location in terms of pixel and shifts the drawing origin from top left corner to the new location. Have a look at the below code:
1 2 3 4 5 |
//Sample 01: Client Rectangle. CRect rct; GetClientRect(&rct); //Sample 04.1: Shift the Origin to Screen Center dc.SetViewportOrg(rct.right/2, rct.bottom/2); |
In the
OnPaint()
handler, first we shift the Origin from the top left corner to the center of the window. The rct is the
CRect
object, which we used to get the Client Area dimensions in device Coordinate. So, we specify the center of the client area in terms of a pixel to the
SetViewportOrg
API of the
PaintDC
. Below is the picture which shows the shifted Origin:
The code in effect is shown in the above picture. The Red one is the origin before the shift, and the blue one is the origin after the shift via
SetViewportOrg
API. Here, we specified the new origin in terms of pixels. In the below code, we create a blue pen and then draw a line using
PaintDC
. Remember, we previously set the Mapping Mode as
MM_LOMETRIC
. But, we comment those piece of code before trying with Snippet 4.2 (Watch the video at the end of this section).
1 2 3 4 5 |
//Sample 04.2: Draw a blue Line MM_LOMETRIC CPen pen(PS_SOLID, 2, RGB(0,0,255)); CPen* OldPen = dc.SelectObject(&pen); dc.MoveTo(0,0); dc.LineTo(100,100); |
After drawing the blue line, we draw one more line in red. This time we use the
MM_LOENGLISH
Mapping Mode (British Standard). At this stage, since we have gained a good idea of Mapping Modes, we no need to explore that again. The code is below:
1 2 3 4 5 6 7 |
//Sample 04.2: Draw a Red Line using MM_LOENGLISH dc.SetMapMode(MM_LOMETRIC); CPen pen1(PS_SOLID, 10, RGB(255,0,0)); dc.SelectObject(&pen1); dc.MoveTo(0,0); dc.LineTo(100,100); dc.SelectObject(OldPen); |
Now running the entire code makes your drawing look like the one shown below (Note the shifted origin):
For More explanation look at the video below:
Video 4: Shifting the view-port origin using SetViewPortOrg API
6. Using the SetWindowOrg API
At this stage, we know what the
SetViewportOrg
API does. In a summary again, the
SetViewPortOrg
sets the drawing origin by specifying the values in terms of pixels. The
SetWindowOrg
function sets the given logical point as Lower Left Corner of the client Area Window.
Note the difference, View Port Origin is mentioned in terms of pixels and Window Origin is pointed out in terms of Logical units, which depends on the currently set Mapping Mode of the device context. Have a look at the below Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Sample 05.1 Set the Mapping Mode and Viewport origin dc.SetMapMode(MM_LOMETRIC); dc.SetViewportOrg(rct.left, rct.bottom); //Sample 05.2 Set this new location as top left of the client area dc.SetWindowOrg(-100 , -100); //Sample 05.3 Draw the Verticle and Horizontal line from //the Origin (Viewport) CPen pen1(PS_SOLID, 1, RGB(255,0,0)); CPen* OldPen = dc.SelectObject(&pen1); dc.MoveTo(0,0); dc.LineTo(0,500); dc.MoveTo(0,0); dc.LineTo(500,0); dc.SelectObject(OldPen); |
In this example, first we set the Mapping Mode as
MM_LOMETRIC
. Then we shifted the drawing origin to lower left corner of the screen by specifying the location to be shifted as pixels. Then using the
SetWindowOrg
function, we specify the logical unit -100, -100 should be at the lower left corner of the window. After this, we draw two lines using Red color Solid Pen. In those lines, one moves from the drawing origin(View Port Origin) to 500 unit in the positive X direction and other one moves 500 units in positive Y direction. Have a look at the below picture to understand this as it confuses most of MFC professionals:

MFC View-Port Origin and Window Origin (Window Origin @ Lower Left Corner, the Red Mark shows View Port Origin)
To get better insight on View Port Origin and Window Origin, watch the video below:
Video 5: VC++ MFC View Port Origin and Window Origin
Source Code: Download VC++ MFC Mapping Mode, Window and ViewPort Origin Example From Google Drive
Categories: MFC
Tags: Mapping Modes, MM_LOMETRIC, MM_TEXT, SetMapMode, SetViewPortOrg, SetWindowOrg
Thanks. It helped to know the basics of drawing. Great Article.
Great explantion!
Thank you very much Sir.
Glad you like it