Pens |
|
As mentioned already, 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 device context class as HDC. The device context is a combination of the platform on which the drawing is performed and the necessary tools to draw on it. A pen is a tool used to draw lines and curves on a device context. In the graphics programming, a pen is also used to draw the borders of a geometric closed shape such as a rectangle or a polygon. To make it an efficient tool, a pen must produce some characteristics on the lines it is asked to draw. These characteristics can range from the width of the line drawn to their colors, from the pattern applied to the level of visibility of the lines. To manage these properties, Microsoft Windows considers two types of pens: cosmetic and geometric.
To create a pen, you can call the CreatePen() function. Its syntax is: HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor); The fnPenStyle argument is characteristic is referred to as the style of the pen. 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. 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: #include <windows.h> LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX WndCls; static char szAppName[] = "ExoPen"; MSG Msg; WndCls.cbSize = sizeof(WndCls); WndCls.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; WndCls.lpfnWndProc = WindProcedure; WndCls.cbClsExtra = 0; WndCls.cbWndExtra = 0; WndCls.hInstance = hInstance; WndCls.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndCls.hCursor = LoadCursor(NULL, IDC_ARROW); WndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); WndCls.lpszMenuName = NULL; WndCls.lpszClassName = szAppName; WndCls.hIconSm = LoadIcon(hInstance, IDI_APPLICATION); RegisterClassEx(&WndCls); CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, szAppName, "Pens Fundamentals", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 420, 220, NULL, NULL, hInstance, NULL); while( GetMessage(&Msg, NULL, 0, 0) ) { TranslateMessage(&Msg); DispatchMessage( &Msg); } return static_cast<int>(Msg.wParam); } LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC hDC; PAINTSTRUCT Ps; HPEN hPen; switch(Msg) { case WM_PAINT: hDC = BeginPaint(hWnd, &Ps); hPen = CreatePen(PS_DASHDOTDOT, 1, RGB(255, 25, 5)); SelectObject(hDC, hPen); Rectangle(hDC, 20, 22, 250, 125); EndPaint(hWnd, &Ps); break; case WM_DESTROY: PostQuitMessage(WM_QUIT); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; }
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 create a new 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. This is done by calling the DeleteObject() function as follows: LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC hDC; PAINTSTRUCT Ps; HPEN hPen; switch(Msg) { case WM_PAINT: hDC = BeginPaint(hWnd, &Ps); hPen = CreatePen(PS_DASHDOTDOT, 1, RGB(255, 25, 5)); SelectObject(hDC, hPen); Rectangle(hDC, 20, 22, 250, 125); DeleteObject(hPen); EndPaint(hWnd, &Ps); break; case WM_DESTROY: PostQuitMessage(WM_QUIT); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; } The Win32 API provides the LOGPEN structure that you can use to individually specify each characteristics of a pen. The LOGPEN structure is defined 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 CreatePen() function. The lopnWidth argument is provided as a POINT value. Only the POINT::x
value is considered. After initializing the LOGPEN variable, call the CreatePenIndirect() function to create a pen. The syntax of the CreatePenIndirect() function is: HPEN CreatePenIndirect(CONST LOGPEN *lplgpn); 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: LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC hDC; PAINTSTRUCT Ps; HPEN hPen; LOGPEN LogPen; POINT Pt = { 1, 105 }; switch(Msg) { case WM_PAINT: hDC = BeginPaint(hWnd, &Ps); LogPen.lopnStyle = PS_SOLID; LogPen.lopnWidth = Pt; LogPen.lopnColor = RGB(235, 115, 5); hPen = CreatePenIndirect(&LogPen); SelectObject(hDC, hPen); Ellipse(hDC, 60, 40, 82, 80); Ellipse(hDC, 80, 20, 160, 125); Ellipse(hDC, 158, 40, 180, 80); Ellipse(hDC, 100, 60, 110, 70); Ellipse(hDC, 130, 60, 140, 70); Ellipse(hDC, 100, 90, 140, 110); DeleteObject(hPen); EndPaint(hWnd, &Ps); break; case WM_DESTROY: PostQuitMessage(WM_QUIT); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam); } return 0; }
If you want to know the currently selected pen used on a device context, you can call the GetObject() member function.
|
|
|
||
Previous | Copyright © 2003-2015, FunctionX, Inc. | Next |
|