GDI Accessories and Tools: Pens |
|
Introduction to Pens |
In the previous lesson, we mentioned that, in order to draw, two primary objects are needed: a platform and a tool. So far, we were using the platform, called a device context. We introduced the main device context class as the CDC class. To draw, we have been using a pointer to CDC. Now, we need to realize that, declaring a CDC variable does not just give us access to the device context, it also initializes it. The device context is a combination of the platform on which the drawing is performed and the necessary tools to draw on it. As such, when declaring a CDC variable, it also creates and selects a black pen. This is why we have been able to draw lines and other shapes so far. |
A pen is referred to as cosmetic when it can be used to draw only simple lines of a fixed width, less than or equal to 1 pixel. A pen is geometric when it can assume different widths and various ends.
When you declare a CDC variable, it creates and selects a pen that can draw a 1-pixel width black line. If you want a more refined pen, the MFC provides the CPen class. Therefore, the first step in creating a pen is to declare a variable of CPen type, which can be done using the default constructor as follows: CPen NewPen; To create a pen, you must specify the desired characteristics. This can be done with another CPen constructor declared as follows: CPen(int nPenStyle, int nWidth, COLORREF crColor); Alternatively, if you want to use a variable declared using the default constructor, you can then call the CPen::CreatePen() method. Its syntax is: BOOL CreatePen(int nPenStyle, int nWidth, COLORREF crColor); The arguments of the second constructor and the CreatePen() method are used to specify the properties that the pen should have: The Style: This characteristic is passed as the nPenStyle argument. The possible values of this argument are:
To specify the type of pen you are creating, as cosmetic or geometric, use the bitwise OR operator to combine one of the above styles with one of the following:
If you are creating a cosmetic pen, you can also add (bitwise OR) the PS_ALTERNATE style to to set the pen at every other pixel. The Width: The nWidth argument is the width used to draw the lines or borders of a closed shape. A cosmetic pen can have a width of only 1 pixel. If you specify a higher width, it would be ignored. A geometric pen can have a width of 1 or more pixels but the line can only be solid or null. This means that, if you specify the style as PS_DASH, PS_DOT, PS_DASHDOT, or PS_DASHDOTDOT but set a width higher than 1, the line would be drawn as PS_SOLID. The Color: The default color of pen on the device context is black. If you want to control the color, specify the desired value for the crColor argument. Based this, using the second constructor, you can declare and initialize a CPen variable as follows: CPen NewPen(PS_DASHDOTDOT, 1, RGB(255, 25, 5)); The same pen can be created using the CreatePen() method as follows: CPen NewPen; NewPen.CreatePen(PS_DASHDOTDOT, 1, RGB(255, 25, 5)); After creating a pen, you can select it into the desired device context variable and then use it as you see fit, such as drawing a rectangle. Here is an example: void CExoView::OnDraw(CDC* pDC) { CExoDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CPen NewPen; NewPen.CreatePen(PS_DASHDOTDOT, 1, RGB(255, 25, 5)); pDC->SelectObject(&NewPen); pDC->Rectangle(20, 22, 250, 125); } Once a pen has been selected, any drawing performed and that uses a pen would use the currently selected pen. If you want to use a different pen, you can either create a new pen or change the characteristics of the current pen. After using a pen, between exiting the function or event that created it, you should get rid of it and restore the pen that was selected previously. Here is an example:
The Win32 API provides the LOGPEN structure that you can use to individually specify each characteristics of a pen. The LOGPEN structure is created as follows: typedef struct tagLOGPEN { UINT lopnStyle; POINT lopnWidth; COLORREF lopnColor; } LOGPEN, *PLOGPEN; To use this structure, declare a variable of LOGPEN type or a pointer. Then initialize each member of the structure. If you do not, its default values would be used and the line not be visible. The lopnStyle argument follows the same rules we reviewed for the nPenStyle argument of the second constructor and the CreatePen() method. The lopnWidth argument is provided as a POINT or a CPoint value. Only the POINT::x or the CPoint::x value is considered. The lopnColor argument is a color and can be provided following the rules we reviewed for colors. After initializing the LOGPEN variable, call the CPen::CreatePenIndirect() member function to create a pen. The syntax of the CreatePenIndirect() method is: BOOL CreatePenIndirect(LPLOGPEN lpLogPen); The LOGPEN value is passed to this method as a pointer. After this call, the new pen is available and can be selected into a device context variable for use. Here is an example:
If you want to know the currently selected pen used on a device context, you can call the CPen::GetLogPen() member function. Its syntax is: int GetLogPen(LOGPEN* pLogPen); To get the characteristics of the current pen, pass a pointer to the LOGPEN structure to this GetLogPen() method. The returned pLogPen value would give you the style, the width, and the color of the pen. |
|
||
Home | Copyright © 2003-2015, FunctionX | |
|