|
| БЕСПЛАТНАЯ ежедневная online лотерея! Выигрывай каждый день БЕСПЛАТНО! |
|
|
Using Filled Shapes
This section illustrates how to use filled shape functions. The example uses the main window procedure from an application that enables the user to draw ellipses, rectangles, and rectangles with rounded corners.
The user draws a filled shape by selecting a particular shape from the menu, positioning the cursor at the upper left corner of the shape (or the shape's bounding rectangle in the case of an ellipse), and then dragging the mouse until the desired dimensions are obtained. The following illustration shows three filled shapes drawn using the sample code in this section.
To enable the user to draw filled shapes, include the following code in your application.
LRESULT APIENTRY MainWndProc(hwnd, uMsg, wParam, lParam) HWND hwnd; /* handle of window */ UINT uMsg; /* message */ WPARAM wParam; /* first message parameter */ LPARAM lParam; /* second message parameter */ { HDC hdc; /* handle of device context (DC) */ PAINTSTRUCT ps; /* paint data for Begin/EndPaint */ POINT ptClientUL; /* client area upper left corner */ POINT ptClientLR; /* client area lower right corner */
static HDC hdcCompat;/* handle of DC for bitmap */ static POINT pt; /* x- and y-coordinates of cursor */ static RECT rcTarget; /* rect to receive filled shape */ static RECT rcClient; /* client area rectangle */ static BOOL fSizeEllipse; /* TRUE if ellipse is sized */ static BOOL fDrawEllipse; /* TRUE if ellipse is drawn */ static BOOL fDrawRectangle; /* TRUE if rectangle is drawn */ static BOOL fSizeRectangle; /* TRUE if rectangle is sized */
static BOOL fSizeRoundRect; /* TRUE if rounded rect is sized */ static BOOL fDrawRoundRect; /* TRUE if rounded rect is drawn */ static int nEllipseWidth; /* width for round corners */ static int nEllipseHeight; /* height for round corners */ switch (uMsg) { case WM_COMMAND: switch (wParam) { /* * Set the appropriate flag to indicate which * filled shape the user is drawing.
*/ case IDM_ELLIPSE: fSizeEllipse = TRUE; break; case IDM_RECTANGLE: fSizeRectangle = TRUE; break; case IDM_ROUNDRECT: fSizeRoundRect = TRUE; break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam);
} break; case WM_CREATE: nEllipseWidth = 20; nEllipseHeight = 20; return 0; case WM_PAINT: BeginPaint(hwnd, &ps); /* * Because the default brush is white, select * a different brush into the device context * to demonstrate the painting of filled shapes. */ SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH));
/* * If one of the filled shape "draw" flags is TRUE, * draw the corresponding shape. */ if (fDrawEllipse) { /* draws ellipse */ Ellipse(ps.hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); fDrawEllipse = FALSE; rcTarget.left = rcTarget.right = 0; rcTarget.top = rcTarget.bottom = 0;
} if (fDrawRectangle) { /* Draws rectangle */ Rectangle(ps.hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); fDrawRectangle = FALSE; rcTarget.left = rcTarget.right = 0; rcTarget.top = rcTarget.bottom = 0; } if (fDrawRoundRect) { /* Draws rounded rectangle */ RoundRect(ps.hdc, rcTarget.left, rcTarget.top,
rcTarget.right, rcTarget.bottom, nEllipseWidth, nEllipseHeight); fDrawRectangle = FALSE; rcTarget.left = rcTarget.right = 0; rcTarget.top = rcTarget.bottom = 0; } EndPaint(hwnd, &ps); break; case WM_SIZE: /* * Convert the client coordinates of the client area * rectangle to screen coordinates and save them in a
* rectangle. The rectangle is passed to the ClipCursor * function during WM_LBUTTONDOWN processing. */ GetClientRect(hwnd, &rcClient); ptClientUL.x = rcClient.left; ptClientUL.y = rcClient.top; ptClientLR.x = rcClient.right; ptClientLR.y = rcClient.bottom; ClientToScreen(hwnd, &ptClientUL); ClientToScreen(hwnd, &ptClientLR); SetRect(&rcClient, ptClientUL.x, ptClientUL.y,
ptClientLR.x, ptClientLR.y); return 0; case WM_LBUTTONDOWN: /* * Restrict the cursor to the client area. * This ensures that the window receives a matching * WM_LBUTTONUP message. */ ClipCursor(&rcClient); /* Save the coordinates of the cursor. */ pt.x = (LONG) LOWORD(lParam); pt.y = (LONG) HIWORD(lParam);
/* * If the user chooses one of the filled shapes, * set the appropriate flag to indicate that the * shape is being sized. */ if (fDrawEllipse) fSizeEllipse = TRUE; return 0; case WM_MOUSEMOVE: /* * If one of the "size" flags is set, draw * the target rectangle as the user drags * the mouse.
*/ if ((wParam && MK_LBUTTON) && (fSizeEllipse || fSizeRectangle || fSizeRoundRect)) { /* draws target rect. */ /* * Set the mixing mode so that the pen color is the * inverse of the background color. The previous * rectangle can then be erased by drawing * another rectangle on top of it. */
hdc = GetDC(hwnd); SetROP2(hdc, R2_NOTXORPEN); /* * If a previous target rectangle exists, erase * it by drawing another rectangle on top. */ if (!IsRectEmpty(&rcTarget)) Rectangle(hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); /* * Save the coordinates of the target rectangle.
* Avoid invalid rectangles by ensuring that the * value of the left coordinate is greater than * that of the right, and that the value of the * bottom coordinate is greater than that of * the top. */ if ((pt.x < (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) SetRect(&rcTarget, pt.x, HIWORD(lParam),
LOWORD(lParam), pt.y); else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y > (LONG) HIWORD(lParam))) SetRect(&rcTarget, LOWORD(lParam), HIWORD(lParam), pt.x, pt.y); else if ((pt.x > (LONG) LOWORD(lParam)) && (pt.y < (LONG) HIWORD(lParam))) SetRect(&rcTarget, LOWORD(lParam), pt.y, pt.x, HIWORD(lParam));
else SetRect(&rcTarget, pt.x, pt.y, LOWORD(lParam), HIWORD(lParam)); /* Draw the new target rectangle. */ Rectangle(hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); ReleaseDC(hwnd, hdc); } return 0; case WM_LBUTTONUP: /* * If one of the "size" flags is TRUE, reset
* it to FALSE, and then set the corresponding * "draw" flag. * Invalidate the appropriate rectangle and issue * a WM_PAINT message. */ if (fSizeEllipse) { fSizeEllipse = FALSE; fDrawEllipse = TRUE; } if (fSizeRectangle) { fSizeRectangle = FALSE; fDrawRectangle = TRUE; }
if (fSizeRoundRect) { fSizeRoundRect = FALSE; fDrawRoundRect = TRUE; } if (fDrawEllipse || fDrawRectangle || fDrawRoundRect) { InvalidateRect(hwnd, &rcTarget, TRUE); UpdateWindow(hwnd); } /* Release the cursor. */ ClipCursor((LPRECT) NULL); return 0; case WM_DESTROY:
/* * Destroy the background brush, compatible bitmap, * and bitmap. */ DeleteDC(hdcCompat); PostQuitMessage(0); break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return (LRESULT) NULL; }
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
Использование Заполненное Формируется
Эта секция иллюстрирует как, чтобы использовать заполнившее функции формы. Пример использует основную процедуру окна из приложения, которое позволяет потребителя, чтобы делать эллипсами, прямоугольниками, и прямоугольниками с закругленными углами.
Пользователь делает заполненной формой выбираясь конкретную форму из меню, позиционирующую курсор в верхнем левом углу формы (или формировать bounding прямоугольник в случае эллипса), и затем таща мышь пока желаемые измерения не будут получены. Следующая иллюстрация показывает три заполнившее формы сделанные используя код образца в этой секции.
Для того, чтобы позволять пользователя, чтобы делать заполненными формами, включите следующее кода в ваше приложение.
LRESULT APIENTRY MainWndProc(hwnd, uMsg, wParam, lParam) HWND hwnd; /* ручка окна */ UINT uMsg; /* сообщение */ WPARAM wParam; /* первый параметр сообщения */ LPARAM lParam; /* параметр сообщения секунды */ { hdc HDC; /* ручка контекста устройства (DC) */ ps PAINTSTRUCT; /* закрасьте данные для Begin/EndPaint */ ТОЧКА ptClientUL; /* область клиента верхнего левого угла */ ТОЧКА ptClientLR; /* область клиента правого нижнего угла */
статический HDC hdcCompat;/* ручка DC для побитового отображения */ статическая ТОЧКА пт; /* x- и y-coordinates курсора */ статический RECT rcTarget; /* rect, чтобы получать заполненную форму */ статический RECT rcClient; /* прямоугольник области клиента */ статический BOOL fSizeEllipse; /* ИСТИНА если эллипс измерен */ статический BOOL fDrawEllipse; /* ИСТИНА если эллипс сделан */ статический BOOL fDrawRectangle; /* ИСТИНА если прямоугольник сделан */ статический BOOL fSizeRectangle; /* ИСТИНА если прямоугольник измерен */
статический BOOL fSizeRoundRect; /* ИСТИНА если закругленный rect измерен */ статический BOOL fDrawRoundRect; /* ИСТИНА если закругленный rect сделан */ статический int nEllipseWidth; /* ширина для круга ставится в безвыходное положение */ статический int nEllipseHeight; /* высота для круга ставится в безвыходное положение */ ключ (uMsg) { случай WM_COMMAND: ключ (wParam) { /* * Установите подходящий флаг, чтобы указывать какое * заполненная форма пользователь рисуется.
*/ случай IDM_ELLIPSE: fSizeEllipse = ИСТИНУ; прерывание; случай IDM_RECTANGLE: fSizeRectangle = ИСТИНА; прерывание; случай IDM_ROUNDRECT: fSizeRoundRect = ИСТИНА; прерывание; умолчание: возвращайте DefWindowProc(hwnd, uMsg, wParam, lParam);
} прерывание; случай WM_CREATE: nEllipseWidth = 20; nEllipseHeight = 20; возврат 0; случай WM_PAINT: BeginPaint(hwnd, &ps); /* * Поскольку по умолчанию щетка - белая, выбирать * другая щетка в контекст устройства *, чтобы демонстрировать картину заполненных форм. */ SelectObject(ps.hdc, GetStockObject(GRAY_BRUSH));
/* * Если одна из заполненной формы флагов "делает" является ИСТИНОЙ, * сделайте соответствующей формой. */ если (fDrawEllipse) { /* делает эллипсом */ Эллипс(ps.hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); fDrawEllipse = ЛОЖЬ; rcTarget.left = rcTarget.right = 0; rcTarget.top = rcTarget.bottom = 0;
} если (fDrawRectangle) { /* Делает прямоугольником */ Прямоугольник(ps.hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.низ); fDrawRectangle = ЛОЖЬ; rcTarget.left = rcTarget.right = 0; rcTarget.top = rcTarget.bottom = 0; } если (fDrawRoundRect) { /* Делает закругленным прямоугольником */ RoundRect(ps.hdc, rcTarget.left, rcTarget.top,
rcTarget.right, rcTarget.bottom, nEllipseWidth, nEllipseHeight); fDrawRectangle = ЛОЖЬ; rcTarget.left = rcTarget.right = 0; rcTarget.top = rcTarget.bottom = 0; } EndPaint(hwnd, &ps); прерывание; случай WM_SIZE: /* * Преобразовайте координаты клиента области клиента * прямоугольник, чтобы отгораживать координировать и сохранять им в a
* прямоугольник. Прямоугольник пройден на ClipCursor * функция в течение обработки WM_LBUTTONDOWN. */ GetClientRect(hwnd, &rcClient); ptClientUL.x = rcClient.left; ptClientUL.y = rcClient.top; ptClientLR.x = rcClient.right; ptClientLR.y = rcClient.bottom; ClientToScreen(hwnd, &ptClientUL); ClientToScreen(hwnd, &ptClientLR); SetRect(&rcClient, ptClientUL.x, ptClientUL.y,
ptClientLR.x, ptClientLR.y); возврат 0; случай WM_LBUTTONDOWN: /* * Ограничьте курсор в область клиента. * Это проверяет, что окно получает сопоставление * сообщение WM_LBUTTONUP. */ ClipCursor(&rcClient); /* Сохраните координаты cursor. */ pt.x = (ДОЛГО (ДЛИНОЙ)) LOWORD(lParam); pt.y = (ДОЛГО (ДЛИНОЙ)) HIWORD(lParam);
/* * Если пользователь выбирает одну из заполненных форм, * установите подходящий флаг, чтобы указывать это the * форма измеряется. */ если (fDrawEllipse), fSizeEllipse = ИСТИНУ; возврат 0; случай WM_MOUSEMOVE: /* * Если один из флагов "размера" установлены, сделайте * целевой прямоугольник как помехи пользователя * мышь.
*/ если ((wParam && MK_LBUTTON) && (fSizeEllipse || fSizeRectangle || fSizeRoundRect)) { /* делает целью rect. */ /* * Установите смешивающий режим чтобы цвет ручки являлся the * инверсия цвета фона. Предшествующий * прямоугольник может затем выстиран рисунком * другой прямоугольник на верхе этого. */
hdc = GetDC(hwnd); SetROP2(hdc, R2_NOTXORPEN); /* * Если предшествующий целевой прямоугольник существует, выстирайтесь * это рисуя другой прямоугольник на верхе. */ если (!IsRectEmpty ПРЯМОУГОЛЬНИКА(&rcTarget))(hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); /* * Сохраните координаты целевого прямоугольника.
* Избегайте неправильных прямоугольников гарантируя это the * оцените левую координату больше, чем * то самое право, и это величина the * нижняя координата больше, чем тот же самый * верх. */ если ((pt.x < (ДОЛГО (ДЛИНОЙ)) LOWORD(lParam)) && (pt.y > (ДОЛГО (ДЛИНОЙ)) HIWORD(lParam))) SetRect(&rcTarget, pt.x, HIWORD(lParam),
LOWORD(lParam), pt.y); еще если ((pt.x > (ДОЛГО (ДЛИНОЙ)) LOWORD(lParam)) && (pt.y > (ДОЛГО (ДЛИНОЙ)) HIWORD(lParam))) SetRect(&rcTarget, LOWORD(lParam), HIWORD(lParam), pt.x, pt.y); еще если ((pt.x > (ДОЛГО (ДЛИНОЙ)) LOWORD(lParam)) && (pt.y < (ДОЛГО (ДЛИНОЙ)) HIWORD(lParam))) SetRect(&rcTarget, LOWORD(lParam), pt.y, pt.x, HIWORD(lParam));
еще SetRect(&rcTarget, pt.x, pt.y, LOWORD(lParam), HIWORD(lParam)); /* Сделайте новой целью rectangle. */ Прямоугольник(hdc, rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom); ReleaseDC(hwnd, hdc); } возврат 0; случай WM_LBUTTONUP: /* * Если один из флагов "размера" является ИСТИНОЙ, восстановленной
* это в ЛОЖЬ, и затем установившее соответствовать * флаг "делает". * Аннулируйте подходящий прямоугольник и передачу * сообщение WM_PAINT. */ если (fSizeEllipse) {, fSizeEllipse = ЛОЖЬ; fDrawEllipse = ИСТИНУ; } если (fSizeRectangle) { fSizeRectangle = ЛОЖЬ; fDrawRectangle = ИСТИНА; }
если (fSizeRoundRect) { fSizeRoundRect = ЛОЖЬ; fDrawRoundRect = ИСТИНА; } если (fDrawEllipse || fDrawRectangle || fDrawRoundRect) { InvalidateRect(hwnd, &rcTarget, ИСТИНА); UpdateWindow(hwnd); } /* Выпустите cursor. */ ClipCursor((LPRECT) НЕДЕЙСТВИТЕЛЬНЫЙ); возврат 0; случай WM_DESTROY:
/* * Уничтожьте щетку фона, совместимого побитового отображения, * и побитовое отображение. */ DeleteDC(hdcCompat); PostQuitMessage(0); прерывание; умолчание: возвращайте DefWindowProc(hwnd, uMsg, wParam, lParam); } возврат (LRESULT) НЕДЕЙСТВИТЕЛЬНЫЙ; }
|
|
|
|
| |