Moving the Origin

原创 2001年05月22日 04:50:00

Moving the Origin

By default, a device context's origin is in the upper left corner of the display surface. Even if you change the mapping mode, the origin remains in the upper left corner. But just as you can change the mapping mode, you can also move the origin. MFC's CDC class provides two functions for moving the origin. CDC::SetWindowOrg moves the window origin, and CDC::SetViewportOrg moves the viewport origin. You'll normally use one but not both. Using both can be very confusing.

Suppose you'd like to move the origin to the center of the window so that you can center what you draw by centering your output around the point (0,0). Assuming that dc is a device context object, here's one way to do it:

CRect rect;
GetClientRect (&rect);
dc.SetViewportOrg (rect.Width () / 2, rect.Height () / 2);

Here's another way to accomplish the same thing, assuming that you're working in the MM_LOENGLISH mapping mode:

CRect rect;
GetClientRect (&rect);
CPoint point (rect.Width () / 2, rect.Height () / 2);
dc.SetMapMode (MM_LOENGLISH);
dc.DPtoLP (&point);
dc.SetWindowOrg (-point.x, -point.y);

It's easy to get SetViewportOrg and SetWindowOrg confused, but the distinction between them is actually quite clear. Changing the viewport origin to (x,y) with SetViewportOrg tells Windows to map the logical point (0,0) to the device point (x,y). Changing the window origin to (x,y) with SetWindowOrg does essentially the reverse, telling Windows to map the logical point (x,y) to the device point (0,0)—the upper left corner of the display surface. In the MM_TEXT mapping mode, the only real difference between the two functions is the signs of x and y. In other mapping modes, there's more to it than that because SetViewportOrg deals in device coordinates and SetWindowOrg deals in logical coordinates. You'll see examples of how both functions are used later in this chapter.

As a final example, suppose you're drawing in the MM_HIMETRIC mapping mode, where 1 unit equals 1/100 of a millimeter, positive x points to the right, and positive y points upward, and you'd like to move the origin to the lower left corner of the window. Here's an easy way to do it:

CRect rect;
GetClientRect (&rect);
dc.SetViewportOrg (0, rect.Height ());

Now you can draw with positive x and y values using coordinates relative to the window's lower left corner.

A Final Word on Coordinate Systems

When you talk about mapping modes, window origins, viewport origins, and other idioms related to the GDI's handling of coordinates, it's easy to get tangled up in the terminology. Understanding the difference between the device coordinate system and the logical coordinate system might help clear some of the cobwebs.

In the device coordinate system, distances are measured in pixels. The device point (0,0) is always in the upper left corner of the display surface, and the positive x and y axes always point right and downward. The logical coordinate system is altogether different. The origin can be placed anywhere, and both the orientation of the x and y axes and the scaling factor (the number of pixels that correspond to 1 logical unit) vary with the mapping mode. To be precise, they vary with the window extents and the viewport extents. You can change these extents in the MM_ISOTROPIC and MM_ANISOTROPIC mapping modes but not in the other mapping modes.

You'll sometimes hear Windows programmers talk about "client coordinates" and "screen coordinates." Client coordinates are simply device coordinates relative to the upper left corner of a window's client area. Screen coordinates are device coordinates relative to the upper left corner of the screen. You can convert from client coordinates to screen coordinates and vice versa using the CWnd::ClientToScreen and CWnd::ScreenToClient functions. Why these functions are useful will become apparent to you the first time you call a Windows function that returns screen coordinates and you pass them to a function that requires client coordinates, or vice versa.

Getting Information About a Device

Sometimes it's helpful to get information about a device before you send output to it. The CDC::GetDeviceCaps function lets you retrieve all kinds of information about a device, from the number of colors it supports to the number of pixels it can display horizontally and vertically. The following code initializes cx and cy to the width and height of the screen, in pixels:

CClientDC dc (this);
int cx = dc.GetDeviceCaps (HORZRES);
int cy = dc.GetDeviceCaps (VERTRES);

If the screen resolution is 1,024 by 768, cx and cy will be set to 1,024 and 768, respectively.

The table below lists some of the parameters you can pass to GetDeviceCaps to acquire information about the physical output device associated with a device context. How you interpret the results depends somewhat on the device type. For example, calling GetDeviceCaps with a HORZRES parameter for a screen DC returns the screen width in pixels. Make the same call to a printer DC and you get back the width of the printable page, once more in pixels. As a rule, values that imply any kind of scaling (for example, LOGPIXELSX and LOGPIXELSY) return physically correct values for printers and other hardcopy devices but not for screens. For a 600 dpi laser printer, both LOGPIXELSX and LOGPIXELSY return 600. For a screen, both will probably return 96, regardless of the physical screen size or resolution.

Interpreting the color information returned by the NUMCOLORS, BITSPIXEL, and PLANES parameters of GetDeviceCaps is a bit tricky. For a printer or a plotter, you can usually find out how many colors the device is capable of displaying from the NUMCOLORS parameter. For a monochrome printer, NUMCOLORS returns 2.

Useful GetDeviceCaps Parameters

Parameter Returns
HORZRES Width of the display surface in pixels
VERTRES Height of the display surface in pixels
HORZSIZE Width of the display surface in millimeters
VERTSIZE Height of the display surface in millimeters
LOGPIXELSX Number of pixels per logical inch horizontally
LOGPIXELSY Number of pixels per logical inch vertically
NUMCOLORS For a display device, the number of static colors; for a printer or plotter, the number of colors supported
BITSPIXEL Number of bits per pixel
PLANES Number of bit planes
RASTERCAPS Bit flags detailing certain characteristics of the device, such as whether it is palettized and whether it can display bitmapped images
TECHNOLOGY Bit flags identifying the device type—screen, printer, plotter, and so on

However, the color resolution of the screen (the number of colors that can be displayed onscreen simultaneously) is computed by multiplying BITSPIXEL and PLANES and raising 2 to the power of the result, as demonstrated here:

CClientDC dc (this);
int nPlanes = dc.GetDeviceCaps (PLANES);
int nBPP = dc.GetDeviceCaps (BITSPIXEL);
int nColors = 1 << (nPlanes * nBPP);

If this code is executed on a PC equipped with a 256-color video adapter, nColors equals 256. Calling GetDeviceCaps with a NUMCOLORS parameter, meanwhile, returns not 256 but 20—the number of "static colors" that Windows programs into the video adapter's color palette. I'll have more to say about the color characteristics of screens and video adapters and also about static colors in Chapter 15.

I'll use GetDeviceCaps several times in this book to adapt the sample programs' output to the physical attributes of the output device. The first use will come later in this chapter, when the screen's LOGPIXELSX and LOGPIXELSY parameters are used to draw rectangles 1 logical inch long and 1/4 logical inch tall in the MM_TEXT mapping mode.

ACM-贪心之Moving Tables——hdu1050

Moving Tables Problem Description The famous ACM (Advanced Computer Maker) Company has rented a fl...
  • lx417147512
  • lx417147512
  • 2013年10月21日 15:39
  • 2166

Poj_1083 Moving Tables(贪心,测试数据)

题意: 房间之间通过单通道抬桌子,一共有400个房间,分别按照图上顺序编号。每次交换需要10分钟,当两个交换路径不重叠时可以在同一个时间间隔内完成。给出所有的搬动需求,问最少需要的时间。 思路: 最开...
  • EaShion1994
  • EaShion1994
  • 2016年12月12日 21:20
  • 333

ACM--移动桌子--贪心--HDOJ 1050--Moving Tables

HDOJ题目地址:传送门 Moving Tables Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...
  • qq_26891045
  • qq_26891045
  • 2016年05月27日 21:24
  • 8682

精读As-Projective-As-Possible Image Stitching with Moving DLT

文章标题As-Projective-As-PossibleImage Stitching with Moving DLT,来自CVPR 2013,文章主页,PDF。 摘要 本文主要目的是做图像拼接,...
  • xuanwu_yan
  • xuanwu_yan
  • 2013年07月21日 20:31
  • 6188

图像算法---Image Deformation Using Moving Least Squares

本文转载了Image Deformation Using Moving Least Squares这篇论文的算法内容,跟大家分享一下!...
  • Trent1985
  • Trent1985
  • 2015年11月23日 12:01
  • 2409

LeetCode 346. Moving Average from Data Stream(数据流移动平均值)

原题网址: Given a stream of integers and...
  • jmspan
  • jmspan
  • 2016年05月01日 06:23
  • 1529

贪心算法——Hdu 1050 Moving Tables

Moving Tables Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...
  • code_pang
  • code_pang
  • 2012年12月03日 13:43
  • 6708

HDU 4717 The Moving Points (三分搜索)

The Moving Points Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other...
  • lwt36
  • lwt36
  • 2015年05月13日 11:54
  • 393

[leetcode] 346. Moving Average from Data Stream 解题报告

题目链接: Given a stream of integers ...
  • qq508618087
  • qq508618087
  • 2016年06月15日 13:15
  • 2106

bzoj 1982: [Spoj 2021]Moving Pebbles (博弈)

1982: [Spoj 2021]Moving Pebbles Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 172  Solved: 118 ...
  • clover_hxy
  • clover_hxy
  • 2016年12月24日 14:09
  • 246
您举报文章:Moving the Origin