programming windows phần 2 pps

128 225 0
programming windows phần 2 pps

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

• Polyline and PolylineTo Draw a series of connected straight lines. • PolyPolyline Draws multiple polylines. • Arc Draws elliptical lines. • PolyBezier and PolyBezierTo Draw Bezier splines. In addition, Windows NT supports three more line-drawing functions: • ArcTo and AngleArc Draw elliptical lines. • PolyDraw Draws a series of connected straight lines and Bezier splines. These three functions are not supported under Windows 98. Later in this chapter I'll also be discussing some functions that draw lines but that also fill the enclosed area within the figure they draw. These functions are • Rectangle Draws a rectangle. • Ellipse Draws an ellipse. • RoundRect Draws a rectangle with rounded corners. • Pie Draws a part of an ellipse that looks like a pie slice. • Chord Draws part of an ellipse formed by a chord. Five attributes of the device context affect the appearance of lines that you draw using these functions: current pen position (for LineTo, PolylineTo, PolyBezierTo, and ArcTo only), pen, background mode, background color, and drawing mode. To draw a straight line, you must call two functions. The first function specifies the point at which the line begins, and the second function specifies the end point of the line: MoveToEx (hdc, xBeg, yBeg, NULL) ; LineTo (hdc, xEnd, yEnd) ; MoveToEx doesn't actually draw anything; instead, it sets the attribute of the device context known as the "current position." The LineTo function then draws a straight line from the current position to the point specified in the LineTo function. The current position is simply a starting point for several other GDI functions. In the default device context, the current position is initially set to the point (0, 0). If you call LineTo without first setting the current position, it draws a line starting at the upper left corner of the client area. A brief historical note: In the 16-bit versions of Windows, the function to set the current position was MoveTo. This function had just three arguments the device context handle and x- and y-coordinates. The function returned the previous current position packed as two 16-bit values in a 32-bit unsigned long. However, in the 32-bit versions of Windows, coordinates are 32-bit values. Because the 32-bit versions of C do not define a 64-bit integral data type, this change meant that MoveTo could no longer indicate the previous current position in its return value. Although the This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com return value from MoveTo was almost never used in real-life programming, a new function was required, and this was MoveToEx. The last argument to MoveToEx is a pointer to a POINT structure. On return from the function, the x and y fields of the POINT structure will indicate the previous current position. If you don't need this information (which is almost always the case), you can simply set the last argument to NULL as in the example shown above. And now the caveat: Although coordinate values in Windows 98 appear to be 32-bit values, only the lower 16 bits are used. Coordinate values are effectively restricted to -32,768 to 32,767. In Windows NT, the full 32-bit values are used. If you ever need the current position, you can obtain it by calling GetCurrentPositionEx (hdc, &pt) ; where pt is a POINT structure. The following code draws a grid in the client area of a window, spacing the lines 100 pixels apart starting from the upper left corner. The variable hwnd is assumed to be a handle to the window, hdc is a handle to the device context, and x and y are integers: GetClientRect (hwnd, &rect) ; for (x = 0 ; x < rect.right ; x+= 100) { MoveToEx (hdc, x, 0, NULL) ; LineTo (hdc, x, rect.bottom) ; } for (y = 0 ; y < rect.bottom ; y += 100) { MoveToEx (hdc, 0, y, NULL) ; LineTo (hdc, rect.right, y) ; } Although it seems like a nuisance to be forced to use two functions to draw a single line, the current position comes in handy when you want to draw a series of connected lines. For instance, you might want to define an array of 5 points (10 values) that define the outline of a rectangle: POINT apt[5] = { 100, 100, 200, 100, 200, 200, 100, 200, 100, 100 } ; Notice that the last point is the same as the first. Now you need only use MoveToEx for the first point and LineTo for the successive points: MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ; for (i = 1 ; i < 5 ; i++) LineTo (hdc, apt[i].x, apt[i].y) ; Because LineTo draws from the current position up to (but not including) the point in the LineTo function, no coordinate gets written twice by this code. While overwriting points is not a problem with a video display, it might not look good on a plotter or with some drawing modes that I'll discuss later in this chapter. This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com When you have an array of points that you want connected with lines, you can draw the lines more easily using the Polyline function. This statement draws the same rectangle as in the code shown above: Polyline (hdc, apt, 5) ; The last argument is the number of points. We could also have represented this value by sizeof (apt) / sizeof (POINT). Polyline has the same effect on drawing as an initial MoveToEx followed by multiple LineTo functions. However, Polyline doesn't use or change the current position. PolylineTo is a little different. This function uses the current position for the starting point and sets the current position to the end of the last line drawn. The code below draws the same rectangle as that last shown above: MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ; PolylineTo (hdc, apt + 1, 4) ; Although you can use Polyline and PolylineTo to draw just a few lines, the functions are most useful when you need to draw a complex curve. You do this by using hundreds or even thousands of very short lines. If they're short enough and there are enough of them, together they'll look like a curve. For example, suppose you need to draw a sine wave. The SINEWAVE program in Figure 5-6 shows how to do it. Figure 5-6. The SINEWAVE program. This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com SINEWAVE.C /* SINEWAVE.C Sine Wave Using Polyline (c) Charles Petzold, 1998 */ #include <windows.h> #include <math.h> #define NUM 1000 #define TWOPI (2 * 3.14159) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("SineWave") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("Program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Sine Wave Using Polyline"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxClient, cyClient ; HDC hdc ; int i ; PAINTSTRUCT ps ; POINT apt [NUM] ; switch (message) { case WM_SIZE: cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; MoveToEx (hdc, 0, cyClient / 2, NULL) ; LineTo (hdc, cxClient, cyClient / 2) ; for (i = 0 ; i < NUM ; i++) { apt[i].x = i * cxClient / NUM ; apt[i].y = (int) (cyClient / 2 * (1 - sin (TWOPI * i / NUM))) ; } Polyline (hdc, apt, NUM) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The program has an array of 1000 POINT structures. As the for loop is incremented from 0 through 999, the x fields of the POINT structure are set to incrementally increasing values from 0 to cxClient. The program sets the y fields of the POINT structure to sine curve values for one cycle and enlarged to fill the client area. The whole curve is drawn using a single Polyline call. Because the Polyline function is implemented at the device driver level, it is faster than calling LineTo 1000 times. The results are shown in Figure 5-7. Figure 5-7. The SINEWAVE display. The Bounding Box Functions I next want to discuss the Arc function, which draws an elliptical curve. However, the Arc function does not make much sense without first discussing the Ellipse function, and the Ellipse function doesn't make much sense without first discussing the Rectangle function, and if I discuss Ellipse and Rectangle, I might as well discuss RoundRect, Chord, and Pie. The problem is that the Rectangle, Ellipse, RoundRect, Chord, and Pie functions are not strictly line-drawing functions. Yes, the functions draw lines, but they also fill an enclosed area with the current area-filling brush. This brush is solid white by default, so it may not be obvious that these functions do more than draw lines when you first begin experimenting with them. The functions really belong in the later section "Drawing Filled Areas", but I'll discuss them here regardless. The functions I've listed above are all similar in that they are built up from a rectangular "bounding box." You define the coordinates of a box that encloses the object the bounding box and Windows draws the object within this box. The simplest of these functions draws a rectangle: Rectangle (hdc, xLeft, yTop, xRight, yBottom) ; The point (xLeft, yTop) is the upper left corner of the rectangle, and (xRight, yBottom) is the lower right corner. A figure drawn using the Rectangle function is shown in Figure 5-8. The sides of the rectangle are always parallel to the horizontal and vertical sides of the display. This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Figure 5-8. A figure drawn using the Rectangle function. Programmers who have experience with graphics programming are often familiar with "off-by-one" errors. Some graphics programming systems draw a figure to encompass the right and bottom coordinates, and some draw figures up to (but not including) the right and bottom coordinates. Windows uses the latter approach, but there's an easier way to think about it. Consider the function call Rectangle (hdc, 1, 1, 5, 4) ; I mentioned above that Windows draws the figure within a "bounding box." You can think of the display as a grid where each pixel is within a grid cell. The imaginary bounding box is drawn on the grid, and the rectangle is then drawn within this bounding box. Here's how the figure would be drawn: The area separating the rectangle from the top and left of the client area is 1 pixel wide. As I mentioned earlier, Rectangle is not strictly just a line-drawing function. GDI also fills the enclosed area. However, because by default the area is filled with white, it might not be immediately obvious that GDI is filling the area. Once you know how to draw a rectangle, you also know how to draw an ellipse, because it uses the same arguments: Ellipse (hdc, xLeft, yTop, xRight, yBottom) ; A figure drawn using the Ellipse function is shown (with the imaginary bounding box) in Figure 5-9. This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Figure 5-9. A figure drawn using the Ellipse function. The function to draw rectangles with rounded corners uses the same bounding box as the Rectangle and Ellipse functions but includes two more arguments: RoundRect (hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse) ; A figure drawn using this function is shown in Figure 5-10. Figure 5-10. A figure drawn using the RoundRect function. Windows uses a small ellipse to draw the rounded corners. The width of this ellipse is xCornerEllipse, and the height is yCornerEllipse. Imagine Windows splitting this small ellipse into four quadrants and using one quadrant for each of the four corners. The rounding of the corners is more pronounced for larger values of xCornerEllipse and yCornerEllipse. If xCornerEllipse is equal to the difference between xLeft and xRight, and yCornerEllipse is equal to the difference between yTop and yBottom, then the RoundRect function will draw an ellipse. The rounded rectangle in Figure 5-10 was drawn using corner ellipse dimensions calculated with the formulas below. xCornerEllipse = (xRight - xLeft) / 4 ; yCornerEllipse = (yBottom- yTop) / 4 ; This is an easy approach, but the results admittedly don't look quite right because the rounding of the corners is more pronounced along the larger rectangle dimension. To correct this problem, you'll probably want to make xCornerEllipse equal to yCornerEllipse in real dimensions. The Arc, Chord, and Pie functions all take identical arguments: This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; Pie (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; A line drawn using the Arc function is shown in Figure 5-11; figures drawn using the Chord and Pie functions are shown in Figures 5-12 and 5-13. Windows uses an imaginary line to connect (xStart, yStart) with the center of the ellipse. At the point at which that line intersects the ellipse, Windows begins drawing an arc in a counterclockwise direction around the circumference of the ellipse. Windows also uses an imaginary line to connect (xEnd, yEnd) with the center of the ellipse. At the point at which that line intersects the ellipse, Windows stops drawing the arc. Figure 5-11. A line drawn using the Arc function. Figure 5-12. A figure drawn using the Chord function. Figure 5-13. A figure drawn using the Pie function. For the Arc function, Windows is now finished, because the arc is an elliptical line rather than a filled area. For the Chord function, Windows connects the endpoints of the arc. For the Pie function, Windows connects each endpoint of the arc with the center of the ellipse. The interiors of the chord and pie-wedge figures are filled with the current This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com brush. You may wonder about this use of starting and ending positions in the Arc, Chord, and Pie functions. Why not simply specify starting and ending points on the circumference of the ellipse? Well, you can, but you would have to figure out what those points are. Windows' method gets the job done without requiring such precision. The LINEDEMO program shown in Figure 5-14 draws a rectangle, an ellipse, a rectangle with rounded corners, and two lines, but not in that order. The program demonstrates that these functions that define closed areas do indeed fill them, because the lines are hidden behind the ellipse. The results are shown in Figure 5-15. Figure 5-14. The LINEDEMO program. This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... version of CHM2PDF Pilot 0 10 ~P & R2_MASKNOTPEN Simpo PDF Merge and0Split Unregistered Version D http://www.simpopdf.com 0011 ~P R2_NOTCOPYPEN 0100 P & ~D R2_MASKPENNOT 0101 ~D R2_NOT 0110 P^D R2_XORPEN 0111 ~(P & D) R2_NOTMASKPEN 1000 P&D R2_MASKPEN 1001 ~(P ^ D) R2_NOTXORPEN 1010 D R2_NOP 1011 ~P D R2_MERGENOTPEN 1100 P R2_COPYPEN (default) 1101 P ~D R2_MERGEPENNOT 1110 P D R2_MERGEPEN 1111 1 R2_WHITE... operation," or "ROP2." Windows defines 16 ROP2 codes that indicate how Windows combines the pen pixels and the destination pixels In the default device context, the drawing mode is defined as R2_COPYPEN, meaning that Windows simply copies the pixels of the pen to the destination, which is how we normally think about pens There are 15 other ROP2 codes Where do these 16 different ROP2 codes come from?... coordinates you specify in GDI functions are 32- bit values, only Windows NT can handle all 32 bits In Windows 98, coordinates are limited to 16 bits and thus may range only from - 32, 768 to 32, 767 Some Windows functions that use coordinates for the starting point and ending point of a rectangle also require that the width and height of the rectangle be 32, 767 or less Device Coordinates and Logical Coordinates... from 0 to 1: x(t) = (1 - t)3 x0 + 3t (1 - t )2 x1 + 3t2 (1 - t) x2 + t3 x3 y(t) = (1 - t)3 y0 + 3t (1 - t )2 y1 + 3t2 (1 - t) y2 + t3 y3 This document is created with the unregistered version of CHM2PDF Pilot YouSimpo PDF Merge and Split Unregistered98 To draw http://www.simpopdf.com splines, you simply don't need to know these formulas in Windows Version - one or more connected Bezier call PolyBezier... the 32- bit versions of Windows, you'd have to create your own Bezier splines using the Polyline function You would also need knowledge of the following parametric equations for the Bezier spline The begin point is (x0, y0), and the end point is (x3, y3) The two control points are (x1, y1) and (x2, y2) The curve is drawn for values of t ranging from 0 to 1: x(t) = (1 - t)3 x0 + 3t (1 - t )2 x1 + 3t2 (1... lines, but the two lines go in opposite directions If you doubt that Windows is clever enough to do this, the ALTWIND program in Figure 5 -21 demonstrates that it is Figure 5 -20 A figure in which winding mode does not fill all interior areas Figure 5 -21 The ALTWIND program This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com... shown in Figure 5 -22 Figure 5 -22 The ALTWIND display Brushing the Interior The interiors of the Rectangle, RoundRect, Ellipse, Chord, Pie, Polygon, and PolyPolygon figures are filled with the current brush (sometimes also called a "pattern") selected in the device context A brush is a small 8-pixel-by-8-pixel bitmap that is repeated horizontally and vertically to fill the area When Windows uses dithering... that is approximately 1/ 72 inch but that is often assumed in graphics programming to be exactly 1/ 72 inch A "twip" is 1 /20 point and hence 1/1440 inch "Isotropic" and "anisotropic" are actually real words, meaning "identical in all directions" and "not isotropic," respectively You can set the mapping mode by using This document is created with the unregistered version of CHM2PDF Pilot Simpo PDF Merge... or the destination color This drawing mode is indicated by the ROP2 code R2_BLACK Another possibility is that the line is drawn as black except when both the pen and destination are black, in which case the line is drawn as white Although this might be a little strange, Windows has a name for it The drawing mode is called R2_NOTMERGEPEN Windows performs a bitwise OR operation on the destination pixels... black if the pen color is white The R2_BLACK mode always draws black, regardless of the color of the pen or the background Likewise, the R2_WHITE mode always draws white The R2_NOP mode is a "no operation." It leaves the destination unchanged We've been examining the drawing mode in the context of a monochrome system Most systems are color, however On color systems Windows performs the bitwise operation . and (x2, y2). The curve is drawn for values of t ranging from 0 to 1: x(t) = (1 - t)3 x0 + 3t (1 - t )2 x1 + 3t2 (1 - t) x2 + t3 x3 y(t) = (1 - t)3 y0 + 3t (1 - t )2 y1 + 3t2 (1 - t) y2 + t3. cyClient / 2 ; apt[1].x = cxClient / 2 ; apt[1].y = cyClient / 4 ; apt [2] .x = cxClient / 2 ; apt [2] .y = 3 * cyClient / 4 ; apt[3].x = 3 * cxClient / 4 ; apt[3].y = cyClient / 2 ; return. coordinate values in Windows 98 appear to be 32- bit values, only the lower 16 bits are used. Coordinate values are effectively restricted to - 32, 768 to 32, 767. In Windows NT, the full 32- bit values are

Ngày đăng: 13/08/2014, 08:20

Mục lục

  • Cover

  • Author's Note

  • Section I: The Basics

    • Chapter 1 -- Getting Started

      • The Windows Environment

      • Windows Programming Options

      • Your First Windows Program

      • Chapter 2 -- An Introduction to Unicode

        • A Brief History of Character Sets

        • Wide Characters and C

        • Wide Characters and Windows

        • Chapter 3 -- Windows and Messages

          • A Window of One's Own

          • The Windows Programming Hurdles

          • Chapter 4 -- An Exercise in Text Output

            • Painting and Repainting

            • An Introduction to GDI

            • Scroll Bars

            • Building a Better Scroll

            • Chapter 5 -- Basic Drawing

              • The Structure of GDI

              • The Device Context

              • Drawing Dots and Lines

              • Drawing Filled Areas

              • The GDI Mapping Mode

              • Rectangles, Regions, and Clipping

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan