Приложение gdi windows что

Если вы видите это сообщение, значит, произошла проблема с загрузкой файлов в стилей (CSS) нашего сайта. Попробуйте сбросить кэш браузера (Ctrl+F5).
Если это не поможет, а вы находитесь в регионе, где возможны ограничения интернет-трафика с российских серверов — воспользуйтесь VPN.

По своей сути GDI+ (иначе Graphics Device Interface) представляет собой один из 3-х компонентов, который совместно с ядром, а также Windows API, образует общий пользовательский интерфейс, который мы и видим, отвечает за графику. Частенько его называют оконный менеджер GDI. Также GDI+ используется в максимально упрощенных играх, для которых шустрая графика не важна и они прибегают к возможностям GDI.

Видео, на котором при запуске Windows проскальзывает компонент GDI+

johnn­y marr
[27.6K]

9 лет назад 

GDI+ является библиотекой, пришедшей на смену библиотеке GDI (графическое ядро прежних версий Windows- до XP). Основной целью создания GDI+ был перенос (возможность использования) приложений на 64-битных платформах.

Использование GDI+ уже встроено в Windows XP. Чтобы приложения могли использоваться на других, более ранних версиях, нужно установить дистрибутив gdiplus_dnld.exe. найти его можно по ссылке.

Иерархию классов GDI+ можно посмотреть в таблице:

Людви­го
[148K]

9 лет назад 

GDI можно назвать подсистемой, которая составляет интерфейс пользовательский, или оконный менеджер Microsoft Windows. Он представляет графические изображения, а также отвечает за их передачу на такие носители, как мониторы и принтеры. Иначе говоря, та графика, которую мы видим, -это и есть работа GDI. Сейчас же ее совершенствуют, потому она получила свой плюсик.

Вот ее пример:

Letuz­assy
[368]

10 лет назад 

GDI+: графика нового поколения (Class-based API) вроде так)

Знаете ответ?

From Wikipedia, the free encyclopedia

The Graphics Device Interface in the architecture of Windows NT
For example GDK makes use of GDI.

The Graphics Device Interface (GDI) is a legacy component of Microsoft Windows responsible for representing graphical objects and transmitting them to output devices such as monitors and printers. It was superseded by DirectDraw API and later Direct2D API.[citation needed] Windows apps use Windows API to interact with GDI, for such tasks as drawing lines and curves, rendering fonts, and handling palettes. The Windows USER subsystem uses GDI to render such UI elements as window frames and menus. Other systems have components that are similar to GDI; for example: Mac OS had QuickDraw, and Linux and Unix have X Window System core protocol.

GDI’s most significant advantages over more direct methods of accessing the hardware are perhaps its scaling capabilities and its abstract representation of target devices. Using GDI, it is possible to draw on multiple devices, such as a screen and a printer, and expect proper reproduction in each case. This capability is at the center of most «What You See Is What You Get» applications for Microsoft Windows.

Simple games that do not require fast graphics rendering may use GDI. However, GDI is relatively hard to use for advanced animation, lacks a notion for synchronizing with individual video frames in the video card, and lacks hardware rasterization for 3D. Modern games usually use DirectX, Vulkan, or OpenGL instead.

In GDI, a device context (DC) defines the attributes of text and images for the output device, e.g., screen or printer. GDI maintains the actual context. Generating the output requires a handle to the device context (HDC). After generating the output, the handle could be released.

GDI uses Bresenham’s line drawing algorithm to draw aliased lines.[1]

GDI was present in the initial release of Windows. MS-DOS programs had manipulated the graphics hardware using software interrupts (sometimes via the Video BIOS) and by manipulating video memory directly. Code written in this way expects that it is the only user of the video memory, which was not tenable on a multi-tasked environment, such as Windows. The BYTE magazine, in December 1983, discussed Microsoft’s plans for a system to output graphics to both printers and monitors with the same code in the forthcoming first release of Windows.[2]

On Windows 3.1x and Windows 9x, GDI can use Bit blit features for 2D acceleration, if suitable graphics card driver is installed.[3]

With the introduction of Windows XP, GDI+ complemented GDI. GDI+ has been written in C++. It adds anti-aliased 2D graphics, floating point coordinates, gradient shading, more complex path management, intrinsic support for modern graphics-file formats like JPEG and PNG, and support for composition of affine transformations in the 2D view pipeline. GDI+ uses RGBA values to represent color. Use of these features is apparent in Windows XP components, such as Microsoft Paint, Windows Picture and Fax Viewer, Photo Printing Wizard, and the My Pictures Slideshow screensaver. Their presence in the basic graphics layer greatly simplifies implementations of vector-graphics systems such as Adobe Flash or SVG. Besides, .NET Framework provides a managed interface for GDI+ via the System.Drawing namespace.

While GDI+ is included with Windows XP and later, the GDI+ dynamic library can also be shipped with an application and used on older versions of Windows.[4]

Because of the additional text processing and resolution independence capabilities in GDI+, the CPU undertakes text rendering.[5] The result is an order of magnitude slower than the hardware-accelerated GDI.[6] Chris Jackson published some tests indicating that a piece of text rendering code he had written could render 99,000 glyphs per second in GDI, but the same code using GDI+ rendered 16,600 glyphs per second.

GDI+ is similar (in purpose and structure) to Apples QuickDraw GX subsystem, and the open-source libart and Cairo libraries.

In Windows Vista, all Windows applications including GDI and GDI+ applications run in the new compositing engine, Desktop Window Manager (DWM), which is hardware-accelerated. As such, the GDI itself is no longer hardware-accelerated.[7][8][9] Because of the nature of the composition operations, window moves can be faster or more responsive because underlying content does not need to be re-rendered by the application.[8]

Windows 7 includes GDI hardware acceleration for blitting operations in the Windows Display Driver Model v1.1. This improves GDI performance and allows DWM to use local video memory for compositing, thereby reducing system memory footprint and increasing the performance of graphics operations. Most primitive GDI operations are still not hardware-accelerated, unlike Direct2D. GDI+ continues to rely on software rendering in Windows 7.[10]

A GDI printer or Winprinter (analogous to a Winmodem) is a printer designed to accept output from a host computer running Windows. The host computer does all print processing: GDI renders a page as a bitmap, which the printer driver receives, processes, and sends to the associated printer.[11][12] The combination of GDI and the driver is bidirectional; they receive information from the printer such as whether it is ready to print or is out of paper.

Printers that do not rely on GDI require hardware, firmware, and memory for page rendering while a GDI printer uses the host computer for this. However, a printer with its own control language can accept input from any device with a suitable driver, while a GDI printer requires a PC running Windows. GDI printers can be made available to computers on a network if they are connected as shared printers on a computer which is on and running Windows. Some «generic» GDI drivers such as pnm2ppa have been written; they aim to make GDI printers compatible with non-Windows operating systems such as FreeBSD, but they cannot support all printers.[11]

In order to allow simpler creation of drivers for Winprinters, the Microsoft Universal Printer Driver was created. This allows printer vendors to write Generic Printer Description (GPD) «minidrivers», which describe the printer’s capabilities and command set in plaintext, rather than having to do kernel mode driver development.

Microsoft has moved away from this printing model with Open XML Paper Specification.

Each window consumes GDI objects. As the complexity of the window increases, with additional features such as buttons and images, its GDI object usage also increases. When too many objects are in use, Windows is unable to draw any more GDI objects, leading to misbehaving software and frozen and unresponsive program operation.[13] Many applications are also incorrectly coded and fail to release GDI objects after use, which further adds to the problem.[14] The total available GDI objects varies from one version of Windows to the next: Windows 9x had a limit of 1,200 total objects; Windows 2000 has a limit of 16,384 objects; and Windows XP and later have a configurable limit (via the registry) that defaults to 10,000 objects per process (but a theoretical maximum of 65,536 for the entire session).[15][16] Windows 8 and later increase the GDI object limit to 65,536 per user login session.

Earlier versions of Windows such as Windows 3.1 and Windows 98 included a Resource Meter program to allow the user to monitor how much of the total system GDI resources were in use. This resource meter consumed GDI objects itself. Later versions such as Windows 2000 and Windows XP can report GDI object usage for each program in the Task Manager, but they cannot tell the user the total GDI capacity available.

Overflowing GDI capacity can affect Windows itself, preventing new windows from opening, menus from displaying, and alert boxes from appearing. The situation can be difficult to clear and can potentially require a forced reset of the system, since it prevents core system programs from functioning. In Windows 8 and 8.1, a forced log-off occurs as a result of GDI capacity overflow, instead of a reboot.

Direct2D is the successor of GDI and GDI+. Its sibling, DirectWrite, replaces Uniscribe. They were shipped with Windows 7 and Windows Server 2008 R2, and were available for Windows Vista and Windows Server 2008 (with Platform Update installed). Later, Microsoft developed Win2D, a free and open-source GDI-like class library. Win2D’s target audience are developers that use C++, C#, and Visual Basic.NET to develop Universal Windows Platform apps.[17]

  • WinG
  • Microsoft Windows library files

Notes and references

[edit]

  1. ^ Steven, White; David, Coulter; Mike, Jacobs (31 May 2018). «Comparing Direct2D and GDI Hardware Acceleration». Windows Developer. Microsoft.
  2. ^ Butler, John (December 1983). «Device-Independent Graphics Output for Microsoft Windows». BYTE. p. 49. Retrieved 20 October 2013.
  3. ^ «CL-GD543X Applications and Errata Book — Revision 1.2» (PDF). Cirrus Logic. April 1994. Retrieved January 4, 2025.
  4. ^ Platform SDK Redistributable: GDI+
  5. ^ «2D Drawing APIs in Windows -«. DirectX Developer Blog. MSDN Blogs. May 12, 2009. Retrieved July 19, 2012.
  6. ^ Jackson, Chris. «GDI vs. GDI+ Text Rendering Performance». Chris Jackson’s Semantic Consonance. Microsoft.
  7. ^ MSDN: Comparing Direct2D and GDI Hardware Acceleration
  8. ^ a b GDI is not hardware accelerated in Windows Vista
  9. ^ Layered windows…SW is sometimes faster than HW. Avalite on MSDN Blogs.
  10. ^ Thomas Olsen (October 29, 2008). «Introducing the Microsoft Direct2D API».
  11. ^ a b «Generic GDI Printer». Open Printing. The Linux Foundation. Retrieved 21 July 2021.
  12. ^ «Windows-only printers». Linux Documentation Project. Retrieved October 29, 2019.
  13. ^ Microsoft Knowledgebase article 838283 — Desktop application menus are improperly displayed if a process exceeds its GDI object quota in Windows XP or in Windows 2000 http://support.microsoft.com/kb/838283
  14. ^ Microsoft Developer Network Blog — GDI leak in Outlook 2007 causes problems when GDI usage reaches 10,000 objects http://blogs.msdn.com/rgregg/archive/2007/09/03/outlook-2007-gdi-leak-hotfix.aspx
  15. ^ Microsoft Developer Network — GDI Object limits http://msdn.microsoft.com/en-us/library/ms724291(VS.85).aspx
  16. ^ Microsoft Knowledge base Article 894500 — .NET programs designed on newer NT operating systems may malfunction on older Win 95 / Win 98 / Win ME due to lower GDI usage limits http://support.microsoft.com/kb/894500
  17. ^ «Win2D». microsoft/Win2D repo. Microsoft. Retrieved 21 July 2021 – via GitHub.com.
  • Microsoft’s GDI+ page
  • Bob Powell’s GDI+ FAQ list
  • MSDN article on GDI overview
  • Microsoft Security Bulletin MS04-028
  • F-Secure: Critical vulnerability in MS Windows may escalate the virus threat Archived 2009-02-04 at the Wayback Machine
  • IGDI+ — Delphi Open Source GDI+ library.

  1. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Основные понятия
    В Windows приложения не имеют непосредственного доступа к устройствам отображения, таким как монитор или принтер. Вместо этого они обращаются к интерфейсу графического устройства Windows, а он, в свою очередь, транслирует эти обращения к драйверам устройств отображения, обеспечивая аппаратную независимость приложений.
    Интерфейс графического устройства (Graphics Device Interface, GDI) – часть Windows API, которая представляет собой библиотеку функций, обеспечивающих графический вывод на различные устройства отображения.
    С выходом Windows XP появилась библиотека GDI+, призванная заменить устаревшую библиотеку GDI. Библиотека GDI+ содержит в себе все возможности GDI предшественника и предоставляет множество новых. В новых версиях Windows приложения, использующие GDI, выполняются, но при создании приложений рекомендуется использовать GDI+.
    В библиотеке GDI+ используется объектно-ориентированный подход к работе с графическими объектами. Библиотека GDI+ содержит около 40 классов. Документация по классам GDI+ в Platform Software Development Kit (Platform SDK).

    Обработка ошибок в GDI+

    Большинство функций и методов классов GDI+ после выполнения возвращают одно из значений перечисляемого типа Status, определенного в заголовочном файле gdiplustypes.h. В случае успешного выполнения возвращается значение Ok. Остальные значения типа Status указывают на причину возникновения ошибки. Подробное описание значений перечисляемого типа Status в документации Platform SDK.
    Большинство классов GDI+ содержат метод GetLastStatus, который возвращает значение, указывающее причину возникновения ошибки (или ее отсутствие) в последнем вызове одного из методов этих классов.
    При создании объектов одного из классов GDI+ можно вызвать метод GetLastStatus этого объекта, для того чтобы определить успешно или нет был создан объект. В случае успешного создания метод GetLastStatus возвращает значение Ok. При создании объектов некоторых классов GDI+ в случае возникновения ошибки метод GetLastStatus независимо от ее причины может вернуть значение OutOfMemory, указывающее на нехватку памяти для создания объекта.
    Цвет в GDI+

    31​
    …​
    24​
    23​
    …​
    16​
    15​
    …​
    08​
    07​
    …​
    00​
    альфа-фактор
    (alpha-value)
    красный (red)
    зеленый (green)
    синий (blue)

    Параметры цвета могут принимать 28=256 значений, от 255 (максимальная яркость) до 0 (отсутствие цвета). Параметр прозрачности от 255 (отсутствие прозрачности) до 0 (полная прозрачность)
    Методы класса Color

    Метод Описание
    BYTE GetAlpha, BYTE GetA Возвращает значение альфа-фактора
    BYTE GetBlue, BYTE GetB Возвращает значение синего компонента цвета
    BYTE GetGreen, BYTE GetG Возвращает значение зеленого компонента цвета
    BYTE GetRed, BYTE GetR Возвращает значение красного компонента цвета
    ARGB GetValue Возвращает значение цвета в формате ARGB
    MakeARGB(BYTE a, BYTE r, BYTE g, BYTE b) Собирает значения альфа-фактора и компонентов цвета в одно значение цвета в формате ARGB
    SetFromCOLORREF(COLORREF rgb) Задает значение цвета в формате COLORREF
    SetValue(ARGB argb) Задает значение цвета в формате ARGB

    Классы GDI+ для работы с координатами и размерами

    Класс Поля Описание
    Point X, Y Пара целых чисел, представляющих собой координаты точки
    PointF X, Y Пара вещественных чисел, представляющих собой координаты точки
    Size Width, Height Пара целых чисел, представляющих собой ширину и высоту
    SizeF Width, Height Пара вещественных чисел, представляющих собой ширину и высоту
    Rect X, Y, Width, Height Набор из четырех целых чисел, определяющих расположение и размер прямоугольника
    RectF X, Y, Width, Height Набор из четырех вещественных чисел, определяющих расположение и размер прямоугольника

    Point и PointF
    Классы Point и PointF используются для представления координат точек в двумерной прямоугольной системе координат. В классе Point у полей X и Y тип int, в классе PointF – float. В остальном классы Point и PointF идентичны.
    Size и SizeF
    Классы Size и SizeF используются для представления пары чисел, которые определяют ширину и высоту. В классе Size у полей Width и Height тип int, в классе SizeF – float. В остальном классы Size и SizeF идентичны.
    Rect и RectF
    Классы Rect и RectF используются для представления прямоугольников. Классы Rect и RectF в основном идентичны, в классе Rect поля X, Y, Width и Height имеют тип int, в классе RectF – float.
    Методы класса Rect

    Метод Описание
    Rect* Clone Клонирует текущий объект класса Rect.
    Возвращает указатель на созданный объект класса Rect, который должен быть удален вызовом оператора delete после того как станет не нужен
    BOOL Contains(Point &pt)
    BOOL Contains(INT x, INT y)
    Возвращает TRUE, если прямоугольник, представленный текущим объектом класса Rect, включает указанную точку, и FALSE – в противном случае
    BOOL Contains(Rect &rect) Возвращает TRUE, если прямоугольник, представленный текущим объектом класса Rect, включает прямоугольник, указанный параметром rect, и FALSE – в противном случае
    BOOL Equals(Rect &rect) Возвращает TRUE, если прямоугольник, представленный текущим объектом класса Rect, равен прямоугольнику, указанному параметром rect, и FALSE – в противном случае
    INT GetBottom() Возвращает координату по оси Y нижней стороны прямоугольника
    void GetBounds(Rect *rect) Возвращает прямоугольник, представленный текущим объектом класса Rect. Результат сохраняется в объекте класса Rect, на который указывает параметр rect
    INT GetLeft() Возвращает координату по оси X левой стороны прямоугольника
    void GetLocation(Point *point) Возвращает расположение прямоугольника, представленного текущим объектом класса Rect. Результат сохраняется в объекте класса Point, на который указывает параметр point
    INT GetRight() Возвращает координату по оси X правой стороны прямоугольника
    void GetSize(Size *size) Возвращает размер прямоугольника, представленного текущим объектом класса Rect. Результат сохраняется в объекте класса Size, на который указывает параметр size
    void Inflate(INT dx, INT dy) Расширяет прямоугольник, представленный текущим объектом класса Rect, на значение dx c левой и правой стороны и dy с верхней и нижней стороны
    void Inflate(Point &point) Расширяет прямоугольник, представленный текущим объектом класса Rect, на значение point.X c левой и правой стороны и point.Y с верхней и нижней стороны
    BOOL Intersect(Rect &c, Rect &a, Rect &b) Находит пересечение прямоугольников, указанных параметрами a и b. Результат сохраняется в объекте класса Rect, на который указывает параметр c.
    Возвращаемое значение равно TRUE, если пересечение найдено, и FALSE – в противном случае
    BOOL Intersect(Rect &rect) Находит пересечение прямоугольника, представленного текущим объектом класса Rect, и прямоугольника, указанного параметром rect. Результат сохраняется в текущем объекте класса Rect.
    Возвращаемое значение равно TRUE, если пересечение найдено, и FALSE – в противном случае
    BOOL IntersectsWith(Rect &rect) Возвращает TRUE, если прямоугольник, представленный текущим объектом класса Rect, пересекается с прямоугольником, указанным параметром rect, и FALSE – в противном случае
    BOOL IsEmptyArea() Возвращает TRUE, если поля Width и Height текущего объекта класса Rect меньше или равны нулю, и FALSE – в противном случае
    void Offset(INT dx, INT dy) Перемещает прямоугольник, представленный текущим объектом класса Rect, на значение dx по горизонтали и dy по вертикали
    void Offset(Point &point) Перемещает прямоугольник, представленный текущим объектом класса Rect, на значение point.X по горизонтали и point.Y по вертикали
    BOOL Union(Rect &c, Rect &a,
    Rect &b)
    Находит объединение прямоугольников, указанных параметрами a и b. Результат сохраняется в объекте класса Rect, на который указывает параметр c. Возвращаемое значение равно TRUE, если объединение найдено, и FALSE – в противном случае

    Последнее редактирование: 10 янв 2025


    Thetrik и MaKsIm нравится это.

  2. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Графические объекты GDI+

    Библиотека GDI+ содержит набор графических объектов, обеспечивающих выполнение различных графических операций. К таким объектам относятся кисти, перья, шрифты и изображения.

    Кисти

    Замкнутая фигура (например, такая как окружность или многоугольник) закрашивается с помощью кисти (brush). В GDI+ имеется несколько классов для работы кистями, каждый из которых является производным от класса Brush.
    Большинство классов GDI+ для работы кистями (включая класс Brush) определено в заголовочном файле gdiplusbrush.h.

    Сплошные кисти

    Сплошная кисть используется для заполнения замкнутой фигуры однородным цветом.
    Класс SolidBrush имеет следующий конструктор:
    SolidBrush(Color &color);
    Конструктор создает объект класса SolidBrush на основе объекта класса Color, который задает цвет сплошной кисти.
    В классе SolidBrush определены два метода – GetColor и SetColor, которые работают с цветом кисти. Эти методы имеют следующие прототипы:
    GetColor(Color *color)
    SetColor(Color &color);
    Метод GetColor сохраняет текущее значение цвета кисти в объект класса Color, на который указывает параметр color, метод SetColor задает новое значение цвета кисти.
    Цвет кисти можно задать как в конструкторе класса SolidBrush, так и позднее, для уже созданного объекта класса SolidBrush

    Штриховые кисти

    Штриховая кисть (класс HatchBrush) позволяет заполнять замкнутую фигуру с использованием определенного узора.
    Класс HatchBrush имеет следующий конструктор:
    HatchBrush(HatchStyle hatchStyle, Color &foreColor, Color &backColor = Color());
    Этот конструктор создает объект класса HatchBrush на основе предопределенного стиля штриховой кисти, который задает его первый параметр – hatchStyle. Этот параметр должен принимать одно из значений перечисляемого типа HatchStyle, приведенных в таблице. Второй параметр, foreColor, задает цвет, который используется при отображении линий узора штриховой кисти, третий параметр, backColor, задает цвет фона штриховой кисти

    Значения параметра hatchStyle

    Значение hex Узор
    HatchStyle05Percent 6
    HatchStyle10Percent 7
    HatchStyle20Percent 8
    HatchStyle25Percent 9
    HatchStyle30Percent A
    HatchStyle40Percent B
    HatchStyle50Percent C
    HatchStyle60Percent D
    HatchStyle70Percent E
    HatchStyle75Percent F
    HatchStyle80Percent 10
    HatchStyle90Percent 11
    HatchStyleBackwardDiagonal 3
    HatchStyleCross 4
    HatchStyleDarkDownwardDiagonal 5
    HatchStyleDarkHorizontal 1D
    HatchStyleDarkUpwardDiagonal 15
    HatchStyleDarkVertical 1C
    HatchStyleDashedDownwardDiagonal
    HatchStyleDashedHorizontal
    HatchStyleDashedUpwardDiagonal
    HatchStyleDashedVertical
    HatchStyleDiagonalBrick
    HatchStyleDiagonalCross
    HatchStyleDivot
    HatchStyleDottedDiamond
    HatchStyleDottedGrid
    HatchStyleForwardDiagonal
    HatchStyleHorizontal
    HatchStyleHorizontalBrick
    HatchStyleLargeCheckerBoard
    HatchStyleLargeConfetti
    HatchStyleLightDownwardDiagonal
    HatchStyleLightHorizontal
    HatchStyleLightUpwardDiagonal
    HatchStyleLightVertical
    HatchStyleNarrowHorizontal
    HatchStyleNarrowVertical
    HatchStyleOutlinedDiamond
    HatchStylePlaid
    HatchStyleShingle
    HatchStyleSmallCheckerBoard
    HatchStyleSmallConfetti
    HatchStyleSmallGrid
    HatchStyleSolidDiamond
    HatchStyleSphere
    HatchStyleTrellis
    HatchStyleVertical
    HatchStyleWave
    HatchStyleWeave
    HatchStyleWideDownwardDiagonal
    HatchStyleWideUpwardDiagonal
    HatchStyleZigZag

    Методы класса HatchBrush

    В таблице перечислены методы класса HatchBrush, которые могут быть полезны при работе с объектами этого класса.

    Метод Описание
    GetBackgroundColor( Color *color) Возвращает цвет, который используется при отображении узора штриховой кисти.
    Результат сохраняется в объект класса Color, на который указывает параметр color
    GetForegroundColor( Color *color) Возвращает цвет фона штриховой кисти. Результат сохраняется в объект класса Color, на который указывает параметр color
    HatchStyle GetHatchStyle() Возвращает стиль штриховой кисти

    Текстурные кисти

    Текстурная кисть (TextureBrush) позволяет заполнять замкнутую фигуру с использованием изображения.
    Класс TextureBrush имеет следующие конструкторы:
    TextureBrush(Image *image, WrapMode wrapMode = WrapModeTile);
    TextureBrush(Image *image, WrapMode wrapMode, RectF &dstRect);
    TextureBrush(Image *image, WrapMode wrapMode, RectF &dstRect, ImageAttributes *imageAttributes = NULL);
    TextureBrush(Image *image, WrapMode wrapMode, Rect &dstRect, ImageAttributes *imageAttributes = NULL);
    TextureBrush(Image *image, WrapMode wrapMode, Rect &dstRect);
    TextureBrush(Image *image, WrapMode wrapMode, REAL dstX, REAL dstY, REAL dstWidth, REAL dstHeight);
    TextureBrush(Image *image, WrapMode wrapMode, INT dstX, INT dstY, INT dstWidth, INT dstHeight);
    Все эти конструкторы создают объект класса TextureBrush на основе объекта класса Image, на который указывает параметр image. Объект класса Image, который в GDI+ используется для работы с изображениями, содержит изображение, используемое для создания текстурной кисти.

    Параметр wrapMode задает режим заполнения, когда изображение меньше заполняемой области. Этот параметр должен принимать одно из значений перечисляемого типа WrapMode:
    Параметр dstRect, а также параметры dstX, dstY, dstWidth и dstHeight, определяют часть изображения, которая будет использоваться для создания кисти.
    Параметр imageAttributes, указывает на объект класса ImageAttributes, задающий свойства изображения. Этот параметр может быть установлен в NULL.
    В классе TextureBrush определено несколько методов, которые могут быть полезны при работе с объектами этого класса. Основные методы этого класса перечислены в таблице

    Методы класса TextureBrush

    Метод Описание
    Image* GetImage() Возвращает указатель на объект класса Image, который использовался при создании текстурной кисти
    WrapMode GetWrapMode() Возвращает режим заполнения
    SetWrapMode( WrapMode wrapMode) Задает режим заполнения

    Полный перечень методов класса TextureBrush, а также их описание, можно найти в документации Platform SDK.

    Кисти линейного градиента

    Кисть линейного градиента (класс LinearGradientBrush) используется для заполнения замкнутой фигуры цветовым градиентом, в котором цвет меняется параллельно некоторой линии.
    Класс LinearGradientBrush имеет следующие конструкторы:
    LinearGradientBrush(PointF &point1, PointF &point2, Color &color1, Color &color2);
    LinearGradientBrush(Point &point1, Point &point2, Color &color1, Color &color2);
    LinearGradientBrush(RectF &rect, Color &color1, Color &color2, LinearGradientMode mode);
    LinearGradientBrush(Rect &rect, Color &color1, Color &color2, LinearGradientMode mode);
    LinearGradientBrush(RectF &rect, Color &color1, Color &color2, REAL angle, BOOL isAngleScalable = FALSE);
    LinearGradientBrush(Rect &rect, Color &color1, Color &color2, REAL angle, BOOL isAngleScalable = FALSE);
    Все эти конструкторы создают объект класса LinearGradientBrush на основе двух объектов класса Color, которые задают начальный и конечный цвет в линейном градиенте (соответственно параметры color1 и color2).

    В первом и втором конструкторах класса LinearGradientBrush параметры point1 и point2 задают, соответственно, начальную и конечную точку линейного градиента, которые образуют вектор. Как видно на рисунке, длина этого вектора определяет плавность градиента, а его направление – направление градиента
    В третьем и четвертом конструкторах класса LinearGradientBrush параметр rect задает прямоугольник, в котором определены начальная и конечная точки линейного градиента. При этом на определение этих точек влияет параметр mode, который должен принимать одно из значений перечисляемого типа LinearGradientMode:
    На рисунке показаны возможные варианты расположения начальной и конечной точки линейного градиента, определяемого прямоугольником.
    В пятом и шестом конструкторах класса LinearGradientBrush параметр rect задает прямоугольник, в верхнем левом углу которого находится начальная точка линейного градиента, а в правом нижнем углу – конечная точка. Параметр angle задает угол (в градусах) по часовой стрелке от верхней границы заданного прямоугольника. При этом если параметр isAngleScalable принимает значение равное FALSE, параметр angle задает угол, определяющий направление градиента. Если же параметр isAngleScalable принимает значение равное TRUE, параметр angle задает базовый угол, из которого рассчитывается угол, определяющий направление градиента, по следующей формуле:
    [math]\beta =\operatorname{arctg}\left (\frac{\displaystyle width}{\displaystyle height}\times\operatorname{tg}(\alpha)\right )[/math] где [math]\beta[/math]– угол, определяющий направление градиента; [math]width[/math] и [math]heigth[/math] – ширина и высота прямоугольника; [math]\alpha[/math] – базовый угол. Формула справедлива если [math]\alpha<90^{o}[/math].

    Последнее редактирование: 19 янв 2025


    Thetrik и MaKsIm нравится это.

  3. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Кисть линейного градиента, определяемая прямоугольником и углом, который задается (а) или вычисляется из базового угла (б)
    Для изменения начального и конечного цвета линейного градиента в классе LinearGradientBrush определен метод SetLinearColors:
    SetLinearColors(Color &color1, Color &color2);
    Параметры color1 и color2 задают начальный и конечный цвет линейного градиента.
    В классе LinearGradientBrush имеется метод GetLinear.Colors, который возвращает начальный и конечный цвет градиента:
    GetLinearColors(Color *colors)
    Параметр colors указывает на массив из двух объектов класса Color, в которые будут сохранены значения начального и конечного цвета линейного градиента.
    цвет в линейном градиенте может меняться не только между двумя цветами. В классе LinearGradientBrush есть метод SetInterpolationColors, позволяющий задать несколько цветов интерполяции, между которыми будет изменяться цвет в линейном градиенте.
    SetInterpolationColors(Color *presetColors, REAL *blendPositions, INT count);
    Первый параметр, presetColors, указывает на массив объектов класса Color, каждый из которых хранит значение цветов интерполяции в линейном градиенте.
    Второй параметр, blendPositions, указывает на массив значений типа float, которые задают положение цвета в градиенте. Значение каждого элемента этого массива находится в диапазоне от 0 до 1.0, 0 указывает начало градиента, 1.0 – окончание градиента. В массиве, на который указывает параметр blendPositions, должно быть, по крайней мере, два элемента: начало градиента и его окончание.
    Третий параметр, count, задает количество элементов в массиве presetColors. Количество элементов в массиве presetColors должно быть таким же, как и в массиве blendPositions.
    Создание градиентной кисти, определяемой тремя цветами

    1.  // создаем кисть линейного градиента
    2. LinearGradientBrush linGrBrush(Rect(0, 0, 200, 200), Color::White, Color::Black, 45.f);
    3. // изменяем параметры кисти линейного градиента…
    4. Color colors[3] = { Color(255, 255, 0, 0), // красный цвет
    5. Color(255, 0, 0, 255), // синий цвет
    6. Color(255, 0, 255, 0)}; // зеленый цвет
    7. float pos[3] = {0.0f, // начало градиента
    8.  0.3f, // 30% от начала градиента до его конца
    9.  1.0f}; // конец градиента
    10. linGrBrush.SetInterpolationColors(colors, pos, 3);

    Линейный градиент, определяемый тремя цветами​

    Определить количество установленных цветов интерполяции в линейном градиенте можно с помощью метода GetInterpolationColorCount, а получить значения этих цветов и их позиции в градиенте можно с помощью метода GetInterpolationColors.
    INT GetInterpolationColorCount()
    GetInterpolationColors(Color *presetColors, REAL *blendPositions, INT count)
    Первый параметр, presetColors, указывает на массив объектов класса Color, в который будут сохранены значения цветов интерполяции в линейном градиенте.
    Второй параметр, blendPositions, указывает на массив типа float, в который будут сохранены позиции цветов в градиенте.
    Третий параметр, count, задает количество элементов в массиве presetColors. При этом количество элементов в массиве presetColors должно быть таким же, как и в массиве blendPositions.
    По умолчанию цвет в линейном градиенте меняется однородным образом. Однако можно настроить линейный градиент так, чтобы изменение цвета осуществлялось неоднородным образом. В классе LinearGradientBrush есть метод SetBlend, который позволяет настраивать способ градиентного изменения цвета при движении от начала до конца градиента.
    SetBlend(REAL *blendFactors, REAL *blendPositions, INT count);
    Первый параметр, blendFactors, указывает на массив значений типа float, которые задают факторы наложения. Значение каждого элемента в этом массиве определяет процент от конечного цвета линейного градиента и должно задаваться в пределах от 0 до 1.0.
    Второй параметр, blendPositions, указывает на массив значений типа float, которые задают положение фактора наложения в градиенте. Значение каждого элемента этого массива должно находиться в диапазоне от 0 до 1.0, где 0 указывает начало градиента, а 1.0 – окончание градиента.
    Третий параметр, count, задает количество элементов в массиве blendFactors. При этом количество элементов в массиве blendFactors должно быть таким же, как и в массиве blendPositions.
    Пример демонстрирует создание кисти линейного градиента, изображенного на рисунке б.
    Создание градиентной кисти с неоднородным изменением цвета

    1.  // создаем кисть линейного градиента
    2.  LinearGradientBrush linGrBrush( Point(0, 0), Point(0, 200),
    3.  Color::Red, // красный цвет
    4.  Color::Blue); // синий цвет
    5.  // изменяем параметры кисти линейного градиента…
    6.  0.0f, // 0% синего цвета, соответственно 100% красного
    7.  0.4f, // 40% синего цвета, соответственно 60% красного
    8.  0.6f, // 60% синего цвета, соответственно 40% красного
    9.  1.0f}; // 100% синего цвета, соответственно 0% красного
    10.  0.0f, // начало градиента
    11.  0.2f, // 20% от начала градиента до его конца
    12.  0.8f, // 80% от начала градиента до его конца
    13.  1.0f}; // конец градиента
    14.  linGrBrush.SetBlend(factors, pos, 4);

    Определить количество установленных факторов наложения в линейном градиенте можно с помощью метода GetBlendCount, а получить значения этих факторов и их позиции в градиенте можно с помощью метода GetBlend. Прототипы этих методов имеют следующий вид:
    INT GetBlendCount()
    GetBlend(REAL *blendFactors, REAL *blendPositions, INT count)
    Первый параметр, blendFactors, указывает на массив типа float, в который будут сохранены значения факторов наложения в линейном градиенте.
    Второй параметр, blendPositions, указывает на массив значений типа float, в который будут сохранены позиции факторов наложения в градиенте.
    Третий параметр, count, задает количество элементов в массиве blendFactors. При этом количество элементов в массиве blendFactors должно быть таким же, как в массиве blendPositions.
    Чтобы интенсивность цветов в линейном градиенте была распределена более равномерно, можно включить гамма-коррекцию. Для этого в классе LinearGradientBrush определен метод SetGammaCorrection:
    SetGammaCorrection(BOOL useGammaCorrection);
    Параметр useGammaCorrection определяет, будет ли включена гамма-коррекция или нет. Если значение этого параметра равно TRUE, гамма-коррекция будет включена. По умолчанию гамма-коррекция отключена.
    На рисунке два линейных градиента: в одном гамма-коррекция отключена (а), в другом – включена (б).
    Определить включена или нет гамма-коррекция можно с помощью метода GetGammaCorrection() Если гамма-коррекция включена, метод возвращает значение TRUE, в противном случае – FALSE .
    Класс LinearGradientBrush (подобно классу TextureBrush) позволяет определить режим заполнения, когда размер линейного градиента меньше заполняемой области. Для этого у него есть два метода – GetWrapMode и SetWrapMode, которые, соответственно, возвращает и задает режим заполнения. Методы имеют следующие прототипы:
    GetWrapMode()
    SetWrapMode(WrapMode wrapMode);
    На рисунке а показан пример мозаичного заполнения прямоугольника линейным градиентом, представленным на рисунке б.
    Также класс LinearGradientBrush позволяет определить границы линейного градиента с помощью метода GetRectangle:
    GetRectangle(Rect *rect);
    GetRectangle(RectF *rect);
    Параметр rect указывает на объект класса Rect (или RectF), в который будет сохранен прямоугольник, определяющий границы линейного градиента.
    Кисти градиента контура
    Кисть градиента контура (класс PathGradientBrush) используется для заполнения замкнутой фигуры цветовым градиентом, в котором цвет меняется от центральной точки наружу до границы, определяемой замкнутым контуром.
    Класс PathGradientBrush определен в заголовочном файле gdipluspath.h и имеет следующие конструкторы:
    PathGradientBrush(GraphicsPath *path);
    PathGradientBrush(Point *points, INT count, WrapMode wrapMode = WrapModeClamp);
    PathGradientBrush(Point *points, INT count, WrapMode wrapMode = WrapModeClamp);
    Первый конструктор создает объект класса PathGradientBrush на основе объекта класса GraphicsPath, который в GDI+ используется для работы с контурами. Второй и третий конструкторы создают объект класса PathGradientBrush на основе массива точек, на который указывает параметр points, а параметр count задает количество элементов в этом массиве. Параметр wrapMode задает режим заполнения мозаичного заполнения. По умолчанию заполнение не производится.
    В следующем примере продемонстрировано создание кисти градиента контура на основе контура треугольной формы.
    Пример создания кисти градиента контура

    1.  Point points[3] = { Point(100, 0), Point(200, 200), Point(0, 200)};
    2.  // создаем кисть градиента контура
    3.  PathGradientBrush pthGrBrush(points, 3);

    Рассмотрим на основе этого примера некоторые методы класса PathGradientBrush, которые могут пригодиться при работе кистями градиента контура. Полный перечень и подробное описание методов класса PathGradientBrush в документации Platform SDK.
    Класс PathGradientBrush позволяет определять отдельные цвета для центра, границы и даже для каждой точки на границе контура. Для работы с цветом центра контура в классе PathGradientBrush определены два метода – GetCenterColor и SetCenterColor:
    GetCenterColor(Color *color);
    SetCenterColor(Color &color);
    Метод GetCenterColor сохраняет текущее значение цвета центра контура в объект класса Color, на который указывает параметр color, а метод SetCenterColor задает новое значение цвета для центра контура.
    Для задания цвета границы контура в классе PathGradientBrush определен метод SetSurroundColors:
    SetSurroundColors(Color *colors, INT *count);
    Первый параметр, colors, указывает на массив объектов класса Color, каждый из которых хранит значение цветов.
    Второй параметр, count, указывает на переменную типа int, которая должна содержать количество задаваемых цветов. Если метод SetSurroundColors будет выполнен успешно, в переменную, на которую указывает этот параметр, будет сохранено количество заданных цветов.
    В листинге продемонстрирован пример задания отдельных цветов для центра и точек на границе контура для кисти, созданной в предыдущем примере. Полученный результат показан на рисунке а.
    Пример задания цветов для кисти градиента контура

    1.  // задаем цвет центра контура
    2.  pthGrBrush.SetCenterColor(Color::Red);
    3.  // задаем цвета для каждой точки на границе контура…
    4.  Color colors[3] = { Color::DarkGreen, Color::Aqua, Color::Blue};
    5.  pthGrBrush.SetSurroundColors(colors, &n);

    Следующий пример демонстрирует задание цветов для центра и для всей границы контура для кисти из примера в листинге. Результат представлен на рисунке б.
    Еще один пример задания цветов для кисти градиента контура

    1.  // задаем цвет центра контура
    2.  pthGrBrush.SetCenterColor(Color::Aqua);
    3.  // задаем цвет границы контура…
    4.  Color color = Color::Blue;
    5.  pthGrBrush.SetSurroundColors(&color, &n);

    Различные варианты градиента контура: а – каждая точка на границе имеет свой цвет; б – общий цвет для всей границы
    Еще один пример задания цветов для кисти градиента контура

    1. // задаем цвет центра контура
    2.  pthGrBrush.SetCenterColor(Color::Aqua);
    3.  // задаем цвет границы контура…
    4.  Color color = Color::Blue;
    5.  pthGrBrush.SetSurroundColors(&color, &n);

    Определить количество установленных цветов в градиенте контура можно с помощью метода GetSurroundColorCount, а получить значения этих цветов можно с помощью метода GetSurroundColors. Прототипы этих методов записываются следующим образом:
    INT GetSurroundColorCount();
    GetSurroundColors(Color *colors, INT *count);
    Первый параметр, colors, указывает на массив объектов класса Color, в который будут сохранены значения цветов.
    Второй параметр, count, указывает на переменную типа int, которая должна содержать количество запрашиваемых цветов. Если метод GetSurroundColors будет выполнен успешно, в переменную, на которую указывает этот параметр, будет сохранено количество полученных цветов.
    Цвет центра используется не только в центральной точке, но и везде в пределах внутреннего контура. Класс PathGradientBrush позволяет настраивать внутренний контур, увеличивая размер фокуса с помощью метода SetFocusScales:
    SetFocusScales(REAL xScale, REAL yScale);
    Параметры xScale и yScale задают коэффициенты масштабирования, соответственно по шкале x и y.
    На рисунке показан эффект применения коэффициентов масштабирования к фокусу кисти градиента контура, который можно получить, если добавить в предыдущий пример следующий программный код:

    1. // применим коэффициенты масштабирования
    2.  pthGrBrush.SetFocusScales(0.3f, 0.7f);

    Масштабирование фокуса кисти градиента контура​

    Чтобы получить установленные коэффициенты масштабирования фокуса нужно использовать метод GetFocusScales:
    GetFocusScales(REAL *xScale, REAL *yScale);
    Параметры xScale и yScale указывают на переменные типа float, в которые будут записаны коэффициенты масштабирования, соответственно по шкале x и y.
    По умолчанию центральной точкой кисти градиента контура является центр контура, используемого при создании этой кисти. Положение центральной точки можно изменить с помощью метода SetCenter.Point класса PathGradientBrush:
    SetCenterPoint(Point &point);
    SetCenterPoint(PointF &point);
    Параметр point ссылается на объект класса Point (или PointF), в котором представлены координаты новой центральной точки.
    На рисунке а показан результат изменения положения центральной точки, который можно получить, если добавить в пример из листинга следующий программный код:

    1.  // изменяем положение центральной точки
    2.  pthGrBrush.SetCenterPoint( Point(80,120) );

    В качестве центральной точки кисти градиента контура можно установить точку, которая лежит вне контура. На рисунке б показан результат задания центральной точки вне контура, представленного в следующем фрагменте программного кода:

    1.  // изменяем положение центральной точки
    2.  pthGrBrush.SetCenterPoint( Point(10,210) );

    Текущее положение центральной точки определяют с помощью метода GetCenterPoint:
    GetCenterPoint(Point *point);
    GetCenterPoint(PointF *point);
    Параметр point указывает на объект класса Point (или PointF), в который будут сохранены координаты центральной точки.
    Нужно отметить, что в классе PathGradientBrush также имеются методы аналогичные тем, что были рассмотрены в классе LinearGradientBrush. Вот эти методы:

    • GetBlend;
    • GetBlendCount;
    • GetGammaCorrection;
    • GetInterpolationColorCount;
    • GetInterpolationColors;
    • GetRectangle;
    • GetWrapMode;
    • SetBlend;
    • SetGammaCorrection;
    • SetInterpolationColors;
    • SetWrapMode.

    Перечисленные методы класса PathGradientBrush дают несколько другой эффект чем аналогичные методы класса LinearGradientBrush. В листинге показан пример использования метода SetInterpolationColors для того, чтобы изменить созданную кисть градиента контура, как показано на рисунке.

    Градиент контура, определяемый тремя цветами​

    Создание кисти с неоднородным изменением цвета

    1. // изменяем параметры кисти градиента контура…
    2.  Color colors[3] = { Color::DarkGreen, Color::Aqua, Color::Blue};
    3.  float pos[3] = { 0.0f, // начало градиента
    4.  0.4f, // 40% от начала градиента до его конца
    5.  1.0f}; // конец градиента
    6.  pthGrBrush.SetInterpolationColors(colors, pos, 3);

    Класс Brush
    Класс Brush является родительским для классов SolidBrush, HatchBrush, TextureBrush, LinearGradientBrush и PathGradientBrush. Однако в отличие от своих потомков сам по себе класс Brush практически бесполезен, так как его нельзя использовать непосредственно.
    Различные классы GDI+ в своих методах, выполняющих заполнение замкнутой фигуры, требуют указывать в качестве аргумента именно объект класса Brush. Это сделано только для того, чтобы такие методы могли работать идентично вне зависимости от кисти, используемой для заполнения. Дело в том, что все классы для работы кистями, являясь производными от класса Brush, могут использоваться в качестве аргумента в методах, которые требуют объект класса Brush.
    Следует также отметить, что класс Brush имеет несколько методов, которые наследуют все потомки этого класса. Среди этих методов есть уже рассмотренный ранее метод GetLastStatus.
    В классе также есть метод Clone, который клонирует текущий объект класса производного от класса Brush. Метод Clone имеет следующий прототип:
    Brush* Clone() ;
    В случае успеха метод возвращает указатель на объект класса Brush, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.
    В листинге пример использования метода Clone для клонирования объекта класса SolidBrush. При этом если аргумент brush указывает не на объект класса SolidBrush, клонирование не выполняется.

    Последнее редактирование: 6 янв 2025

  4. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Создание кисти с неоднородным изменением цвета

    1.  // изменяем параметры кисти градиента контура…
    2.  Color colors[3] = { Color::DarkGreen, Color::Aqua, Color::Blue};
    3.  float pos[3] = { 0.0f, // начало градиента
    4.  0.4f, // 40% от начала градиента до его конца
    5.  1.0f}; // конец градиента
    6.  pthGrBrush.SetInterpolationColors(colors, pos, 3);

    Класс Brush
    Класс Brush является родительским для классов SolidBrush, HatchBrush, TextureBrush, LinearGradientBrush и PathGradientBrush. В отличие от своих потомков сам по себе класс Brush практически бесполезен, так как его нельзя использовать непосредственно.
    Различные классы GDI+ в своих методах, выполняющих заполнение замкнутой фигуры, требуют указывать в качестве аргумента объект класса Brush. Это сделано только для того, чтобы такие методы могли работать идентично вне зависимости от кисти, используемой для заполнения. Все классы для работы кистями, являясь производными от класса Brush, могут использоваться в качестве аргумента в методах, которые требуют объект класса Brush.
    Класс Brush имеет несколько методов, которые наследуют все потомки этого класса. Среди этих методов GetLastStatus.
    В классе есть метод Clone, который клонирует текущий объект класса производного от класса Brush. Метод Clone имеет следующий прототип:
    Brush* Clone();
    В случае успеха метод возвращает указатель на объект класса Brush, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.
    В листинге продемонстрирован пример использования метода Clone для клонирования объекта класса SolidBrush. Если аргумент brush указывает не на объект класса SolidBrush, клонирование не выполняется.
    Функция клонирования объекта класса SolidBrush

    1.  SolidBrush* CloneSolidBrush(Brush *brush)
    2.  {  SolidBrush *result = dynamic_cast<SolidBrush *>(brush);
    3.  result = (SolidBrush *)result->Clone();

    Функцию из предыдущего примера можно использовать следующим образом:

    1.  SolidBrush *cloneBrush = NULL;
    2.  // создаем сплошную кисть
    3.  SolidBrush solidBrush(Color::Red);
    4.  // создаем штриховую кисть
    5.  HatchBrush hatchBrush(HatchStyleCross, Color::Blue);
    6.  // клонируем объект solidBrush
    7.  // результат — указатель новый экземпляр класса SolidBrush
    8.  cloneBrush = CloneSolidBrush(&solidBrush);
    9.  delete cloneBrush, cloneBrush = NULL;
    10.  // клонируем объект hatchBrush
    11.  cloneBrush = CloneSolidBrush(&hatchBrush);

    Определить тип кисти можно и без использования оператора dynamic_cast. В классе Brush есть метод GetType, который возвращает тип кисти. Прототип метода GetType имеет следующий вид:
    BrushType GetType();
    Метод возвращает одно из следующих значений перечисляемого типа BrushType:

    • BrushTypeSolidColor – сплошная кисть;
    • BrushTypeHatchFill – штриховая кисть;
    • BrushTypeTextureFill – текстурная кисть;
    • BrushTypePathGradient – кисть градиента контура;
    • BrushTypeLinearGradient – кисть линейного градиента.

    В следующем примере продемонстрирована видоизмененная функция, которая клонирует объект класса SolidBrush:
    Функция клонирования объекта класса SolidBrush

    1.  SolidBrush* CloneSolidBrush(Brush *brush)
    2.  { BrushType type = brush->GetType();
    3.  if (type == BrushTypeSolidColor)
    4.  return (SolidBrush *)brush->Clone();
    5.  return NULL; } // CloneSolidBrush

    Перья

    Для рисования линий, кривых и границ (контуров) различных фигур используется перо (pen), которое определяет графические атрибуты такие, как цвет, толщина, стиль штриха и т.п. Работа с перьями в GDI+ осуществляется с помощью класса Pen, который определен в заголовочном файле gdipluspen.h.
    Класс Pen имеет следующие конструкторы:
    Pen(Color &color, REAL width = 1.0f);
    Pen(Brush *brush, REAL width = 1.0f);
    Первый конструктор создает объект класса Pen на основе объекта класса Color. Второй конструктор создает объект класса Pen на основе объекта класса Brush. Параметр width задает толщину пера в логических единицах.
    В следующем примере показаны два способа создания пера красного цвета и толщиной 4.

    1.  // просто создаем объект класса Pen
    2.  Pen pen1(Color(255, 0, 0), 4.f);
    3.  // сперва создаем сплошную кисть
    4.  SolidBrush sBrush(Color::Red); // красный цвет
    5.  // а затем создаем объект класса Pen на основе объекта sBrush

    Прежде чем перейти к изучению основных методов класса Pen, следует отметить, что в этом классе (как и в классе Brush) есть методы GetLastStatus и Clone. Метод Clone имеет следующий прототип:
    Pen* Clone();
    В случае успеха метод Clone возвращает указатель на объект класса Pen, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.

    Цвет пера

    Цвет пера определяет цвет рисуемых линий. В классе Pen определены два метода – GetColor и SetColor, которые работают с цветом пера. Эти методы имеют следующие прототипы:
    GetColor(Color *color);
    SetColor(Color &color);
    Метод GetColor сохраняет текущее значение цвета пера в объект класса Color, на который указывает параметр color, а метод SetColor задает новое значение цвета пера.

    Толщина и выравнивание пера

    Толщину пера можно указать в качестве одного из параметров конструктора класса Pen при создании объекта это класса. Можно также изменять толщину пера с помощью метода SetWidth:
    SetWidth(REAL width);
    Параметр width задает новую толщину пера. Определить текущую толщину пера можно с помощью метода GetWidth класса Pen:
    REAL GetWidth();
    Если толщина пера больше 1.0, при рисовании замкнутого контура можно указать положение такого пера относительно рисуемого контура. Для этого используется метод SetAlignment класса Pen:
    SetAlignment(PenAlignment penAlignment);
    Параметр penAlignment задает положение пера. Этот параметр может принимать одно из значений перечисляемого типа PenAlignment:
    На рисунке показаны различные варианты положения пера при рисовании окружности.
    Создание кисти с неоднородным изменением цвета

    1.  // изменяем параметры кисти градиента контура…
    2.  Color colors[3] = { Color::DarkGreen, Color::Aqua, Color::Blue};
    3.  float pos[3] = { 0, // начало градиента
    4.  0.4, // 40% от начала градиента до его конца
    5.  pthGrBrush.SetInterpolationColors(colors, pos, 3);

    Класс Brush
    Как уже было сказано ранее класс Brush является родительским для классов SolidBrush, HatchBrush, TextureBrush, LinearGradientBrush и PathGradientBrush. Однако в отличие от своих потомков сам по себе класс Brush практически бесполезен, так как его нельзя использовать непосредственно.
    Несмотря на это, различные классы GDI+ в своих методах, выполняющих заполнение замкнутой фигуры, требуют указывать в качестве аргумента именно объект класса Brush. Это сделано только для того, чтобы такие методы могли работать идентично вне зависимости от кисти, используемой для заполнения. Дело в том, что все классы для работы кистями, являясь производными от класса Brush, могут использоваться в качестве аргумента в методах, которые требуют объект класса Brush.
    Следует также отметить, что класс Brush имеет несколько методов, которые наследуют все потомки этого класса. Среди этих методов есть уже рассмотренный ранее метод GetLastStatus.
    В классе есть метод Clone, который клонирует текущий объект класса производного от класса Brush. Метод Clone имеет следующий прототип:
    Brush* Clone();
    В случае успеха этот метод возвращает указатель на объект класса Brush, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.
    В листинге продемонстрирован пример использования метода Clone для клонирования объекта класса SolidBrush. При этом если аргумент brush указывает не на объект класса SolidBrush, клонирование не выполняется.
    Функция клонирования объекта класса SolidBrush

    1.  SolidBrush* CloneSolidBrush(Brush *brush)
    2.  {  SolidBrush *result = dynamic_cast<SolidBrush *>(brush);
    3.  result = (SolidBrush *)result->Clone();

    Функцию из предыдущего примера можно использовать следующим образом:

    1.  SolidBrush *cloneBrush = NULL;
    2.  // создаем сплошную кисть
    3.  SolidBrush solidBrush(Color::Red);
    4.  // создаем штриховую кисть
    5.  HatchBrush hatchBrush(HatchStyleCross, Color::Blue);
    6.  // клонируем объект solidBrush
    7.  // результат — указатель новый экземпляр класса SolidBrush
    8.  cloneBrush = CloneSolidBrush(&solidBrush);
    9.  delete cloneBrush, cloneBrush = NULL;
    10.  // клонируем объект hatchBrush
    11.  cloneBrush = CloneSolidBrush(&hatchBrush);

    Определить тип кисти можно и без использования оператора dynamic_cast. В классе Brush есть метод GetType, который возвращает тип кисти. Прототип метода GetType имеет следующий вид:
    BrushType GetType();
    Этот метод возвращает одно из следующих значений перечисляемого типа BrushType:

    • BrushTypeSolidColor – сплошная кисть;
    • BrushTypeHatchFill – штриховая кисть;
    • BrushTypeTextureFill – текстурная кисть;
    • BrushTypePathGradient – кисть градиента контура;
    • BrushTypeLinearGradient – кисть линейного градиента.

    В следующем примере продемонстрирована видоизмененная функция, которая клонирует объект класса SolidBrush:
    Функция клонирования объекта класса SolidBrush

    1.  SolidBrush* CloneSolidBrush(Brush *brush)
    2.  {   BrushType type = brush->GetType();
    3.  if (type == BrushTypeSolidColor)
    4.  return (SolidBrush *)brush->Clone();

    Перья

    Для рисования линий, кривых и границ (контуров) различных фигур используется перо (pen), которое определяет графические атрибуты такие, как цвет, толщина, стиль штриха и т.п. Работа с перьями в GDI+ осуществляется с помощью класса Pen, который определен в заголовочном файле gdipluspen.h.
    Класс Pen имеет следующие конструкторы:
    Pen(Color &color, REAL width = 1.0);
    Pen(Brush *brush, REAL width = 1.0);
    Первый конструктор создает объект класса Pen на основе объекта класса Color. Второй конструктор создает объект класса Pen на основе объекта класса Brush. Параметр width задает толщину пера в логических единицах.
    В следующем примере показаны два способа создания пера красного цвета и толщиной 4.

    1.  // способ первый: просто создаем объект класса Pen
    2.  Pen pen1(Color(255, 0, 0), 4.0);
    3.  // способ второй:  сперва создаем сплошную кисть
    4.  SolidBrush sBrush(Color::Red); // красный цвет
    5.  // а затем создаем объект класса Pen на основе объекта sBrush

    Прежде чем перейти к изучению основных методов класса Pen, следует отметить, что в этом классе (как и в классе Brush) есть методы GetLastStatus и Clone. Метод Clone имеет следующий прототип:
    Pen* Clone();
    В случае успеха метод Clone возвращает указатель на объект класса Pen, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.

    Цвет пера

    Цвет пера определяет цвет рисуемых линий. В классе Pen определены два метода – GetColor и SetColor, которые работают с цветом пера. Эти методы имеют следующие прототипы:
    GetColor(Color *color);
    SetColor(Color &color);
    Метод GetColor сохраняет текущее значение цвета пера в объект класса Color, на который указывает параметр color, а метод SetColor задает новое значение цвета пера.

    Толщина и выравнивание пера

    Толщину пера можно указать в качестве одного из параметров конструктора класса Pen при создании объекта это класса. Можно также изменять толщину пера с помощью метода SetWidth:
    SetWidth(REAL width);
    Параметр width задает новую толщину пера. Определить текущую толщину пера можно с помощью метода GetWidth класса Pen:
    REAL GetWidth();
    Если толщина пера больше 1.0, при рисовании замкнутого контура можно указать положение такого пера относительно рисуемого контура. Для этого используется метод SetAlignment класса Pen:
    SetAlignment(PenAlignment penAlignment);
    Параметр penAlignment задает положение пера. Этот параметр может принимать одно из значений перечисляемого типа PenAlignment:

    • PenAlignmentCenter – перо располагается по центру контура рисуемой фигуры;
    • PenAlignmentInset – перо располагается с внутренней стороны контура рисуемой фигуры.

    По умолчанию перо имеет положение по центру контура. Определить текущее положение пера относительно контура можно с помощью метода GetAlignment класса Pen:
    PenAlignment GetAlignment();

    Стиль штриха

    Стиль штриха определяет, каким образом будут рисоваться различные линии и контуры. Например, они могут рисоваться непрерывно или пунктиром, или еще как-нибудь. В классе Pen есть метод SetDashStyle, который задает стиль штриха. Этот метод имеет следующий прототип:
    SetDashStyle(DashStyle dashStyle);
    Параметр dashStyle определяет новый стиль штриха. Этот параметр должен принимать одно из значений перечисляемого типа DashStyle:

    • DashStyleSolid – сплошная линия;
    • DashStyleDash – обычный штрих;
    • DashStyleDot – точки;
    • DashStyleDashDot – штрих-пунктир;
    • DashStyleDashDotDot – штрих-две точки.

    На рисунке представлены варианты линий, нарисованных с различными стилями штриха.

    Положение пера при рисовании окружности

    По умолчанию перо имеет положение по центру контура. Определить текущее положение пера относительно контура можно с помощью метода GetAlignment класса Pen:
    PenAlignment GetAlignment();

    Стиль штриха

    Стиль штриха определяет, каким образом будут рисоваться различные линии и контуры. Например, они могут рисоваться непрерывно или пунктиром, или еще как-нибудь. В классе Pen есть метод SetDashStyle, который задает стиль штриха. Этот метод имеет следующий прототип:
    SetDashStyle(DashStyle dashStyle);
    Параметр dashStyle определяет новый стиль штриха. Этот параметр должен принимать одно из значений перечисляемого типа DashStyle:
    По умолчанию перо рисует сплошную линию. Определить текущий стиль штриха можно с помощью метода GetDashStyle класса Pen:
    DashStyle GetDashStyle();
    Если стандартные стили штрихов не подходят, можно использовать собственный шаблон штриха. В классе Pen есть метод SetDashPattern, который задает шаблон штриха. Этот метод имеет следующий прототип:
    SetDashPattern(REAL *dashArray, INT count);

    1. dashArray, указывает на массив значений типа float, каждое из которых определяет длину штрихов и пробелов между ними. Все значения в этом массиве должны быть больше нуля.
    2. count, определяет количество элементов в массиве, на который указывает параметр dashArray.

    В следующем примере показано, как можно задавать шаблон штриха с помощью метода SetDashPattern класса Pen.
    Пример задания шаблона штриха

    1.  // массив штрихов и пробелов
    2.  float dash[8] = { 6.0, // штрих длиной 6
    3.  // создаем перо черного цвета и толщиной 2
    4.  Pen pen(Color::Black, 2.0);
    5.  pen.SetDashPattern(dash, 8);

    В приведенном примере шаблон штриха создается на основе массива {6, 3, 1, 2, 1, 2, 1, 3}. Умножив элементы этого массива на толщину пера, равную 2, получим массив {12, 6, 2, 4, 2, 4, 2, 6}. Получившиеся штрихи будут иметь длину 12 и 2, а длина промежутков между ними будет равна 6 или 4. Нарисованная с помощью такого пера линия показана на рисунке.

    Пример штриховой линии​

    Если для пера установлен шаблон штриха, определить количество элементов в массиве, задающем длину штрихов и пробелов, можно с помощью метода GetDashPatternCount класса Pen, получить значения этого массива с помощью метода GetDashPattern.
    INT GetDashPatternCount();
    GetDashPattern(REAL *dashArray, INT count);

    1. dashArray, указывает на массив типа float, в который будут сохранены длины штрихов и пробелов в установленном шаблоне штриха.
    2. count, задает количество элементов в массиве, на который указывает параметр dashArray.

    Стиль штриха определяет не только длину штрихов, но и форму их концов. В классе Pen есть метод SetDashCap, который указывает форму обоих концов каждого штриха. Метод SetDashCap имеет следующий прототип:
    SetDashCap(DashCap dashCap);
    Параметр dashCap задает форму концов штриха. Этот параметр должен принимать одно из значений перечисляемого типа DashCap:
    На рисунке представлены линии, нарисованные с различными концами штриха.
    Штрихованные линии с различными формами концов штриха
    По умолчанию перо использует прямоугольную форму для обоих концов штриха. Определить текущую форму конца штриха можно с помощью метода GetDashCap класса Pen: GetDashCap();
    При рисовании линий также можно указать расстояние от начала линии до начала штриха. На рисунке, показана линия, для которой расстояние от начала линии до начала штриха равно 0, а на рисунке б – линия, для которой такое расстояние равно 3. При этом в обоих случаях используется шаблон штриха из примера в листинге.
    В классе Pen есть два метода – GetDashOffset и SetDashOffset. Метод GetDashOffset возвращает текущее расстояние от начала линии до начала штриха, а метод SetDashOffset изменяет это расстояние.
    REAL GetDashOffset();
    SetDashOffset(REAL dashOffset);

    Соединение и концы линий

    Соединение линий – это область, образуемая двумя линиями с соприкасающимися концами. Стиль соединения линий является атрибутом. После задания стиля соединения линий для объекта класса Pen этот стиль будет применяться ко всем соединенным линиям, для рисования которых используется данный объект.
    Для задания стиля соединения линий в классе Pen служит метод SetLineJoin:
    SetLineJoin(LineJoin lineJoin);
    Параметр lineJoin задает новый стиль соединения линий. Этот параметр должен принимать одно из значений перечисляемого типа LineJoin:

    LineJoin hex
    LineJoinMiter 0 угловое соединение со скосом в 45°. Получается острый (рис. а) или обрезанный угол (рис. б) в зависимости от того, превышает ли длина среза ограничение по срезу
    LineJoinBevel 1 скошенное соединение. Получается угол при диагонали
    LineJoinRound 2 круговое соединение. Получается ровная круговая дуга между двумя линиями
    LineJoinMiterClipped 3 угловое соединение со скосом в 45°. Получается острый (рис. а) или срезанный угол (рис. б) в зависимости от того, превышает ли длина среза ограничение по срезу

    По умолчанию перо использует угловое соединение. Определить текущий стиль соединения линий можно с помощью метода GetLineJoin класса Pen: GetLineJoin();
    Для того чтобы установить ограничение по срезу следует использовать метод SetMiterLimit класса Pen: SetMiterLimit(REAL miterLimit);
    Параметр miterLimit задает новое ограничение по срезу. Если значение параметра miterLimit меньше 1, оно будет заменено на 1.
    По умолчанию ограничение по срезу имеет значение 10. Определить текущее значение ограничения по срезу можно с помощью метода GetMiterLimit класса Pen:
    REAL GetMiterLimit();
    Еще одним атрибутом является форма концов линии. Для указания формы концов линий в классе Pen есть два метода – SetStartCap и SetEndCap. Метод SetStartCap задает форму начала линии, а метод SetEndCap – форму окончания линии. Прототипы этих методов имеют следующий вид:
    SetStartCap(LineCap startCap);
    SetEndCap(LineCap endCap);
    Параметр startCap (endCap) определяет форму начала (окончания) линии. Этот параметр должен принимать одно из значений перечисляемого типа LineCap:
    ▪ LineCapFlat – прямоугольная форма;
    ▪ LineCapSquare – квадратная форма;
    ▪ LineCapRound – круглая форма;
    ▪ LineCapTriangle – треугольная форма;
    ▪ LineCapNoAnchor – без маркера;
    ▪ LineCapSquareAnchor – квадратный маркер;
    ▪ LineCapRoundAnchor – круглый маркер;
    ▪ LineCapDiamondAnchor – маркер в форме ромба;
    ▪ LineCapArrowAnchor – маркер в форме стрелки.
    По умолчанию на обоих концах перо использует плоское завершение. Определить текущую форму можно с помощью двух методов класса Pen – GetStartCap и GetEndCap. Метод GetStartCap определяет форму начала линии, а метод GetEndCap – форму окончания линии.
    GetStartCap();
    GetEndCap();
    На рисунке показаны различные стили соединений в сочетании с разными формами начала и окончания ломаной линии.
    Ломаные линии с различными стилями соединений в сочетании с разными формами начала и окончания
    Обратите внимание на рисунок, на котором представлены варианты линий, на обоих концах которых нарисованы специальные фигуры, называемые маркерами.
    Линии с различными типами маркеров
    Нужно отметить, что в классе Pen имеется метод SetLineCap, который позволяет сразу задать форму для обоих концов линии и форму для концов штриха. Метод имеет SetLineCap следующий прототип:
    SetLineCap(LineCap startCap, LineCap endCap, DashCap dashCap);
    Параметры startCap и endCap определяют форму, соответственно, начала и окончания линии. Эти параметры должны принимать одно из значений перечисляемого типа LineCap.
    Последний параметр, dashCap, определяет форму обоих концов каждого штриха. Этот параметр должен принимать одно из значений перечисляемого типа DashCap.

    Последнее редактирование: 8 янв 2025


    MaKsIm и Thetrik нравится это.

  5. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Составные перья

    Составное перо рисует составную (сложную) линию, состоящую из параллельных линий и разделяющих их промежутков.
    Класс Pen позволяет делать из обычного пера составное перо. Для этого в классе Pen есть метод SetCompoundArray:
    SetCompoundArray(REAL *compoundArray, INT count);

    1. compoundArray, указывает на массив значений типа float, определяющих составное перо. Значения в массиве должны быть в порядке возрастания и находиться в диапазоне от 0 до 1.0.
    2. count, определяет количество элементов в массиве, на который указывает параметр compoundArray.

    В листинге приведен пример создания составного пера, которым нарисованы контуры для фигур, изображенных на рисунке.
    Пример создания составного пера

    1.  // создаем перо черного цвета и толщиной 10
    2.  Gdiplus::Pen pen(Color::Black, 10.f);
    3.  // массив, определяющий составное перо
    4.  float comp[6] = { 0.0f, 0.2f, // 1-я линия: от 0% до 20% от толщины пера
    5.  0.3f, 0.7f, // 2-я линия: от 30% до 70% от толщины пера
    6.  0.8f, 1.0f}; // 3-я линия: от 80% до 100% от толщины пера
    7.  pen.SetCompoundArray(comp, 6); // делаем из пера составное перо

    Рисование контуров составным пером​

    Если перо является составным, определить количество элементов в массиве, определяющем это составное перо, можно с помощью метода GetCompoundArrayCount класса Pen, получить значения этого массива с помощью метода GetCompoundArray.
    INT GetCompoundArrayCount();
    GetCompoundArray(REAL *compoundArray, INT count);

    1. compoundArray, указывает на массив типа float, в который будут сохранены значения массив, определяющего это составного перо.
    2. count, задает количество элементов в массиве, на который указывает параметр compoundArray.

    Перья с текстурным заполнением

    Вместо рисования линий сплошным цветом можно нарисовать их с текстурной заливкой, например, как на рисунке. Для рисования линий с текстурной заливкой необходимо создать объект класса TextureBrush, определяющего текстурную кисть, и передать этот объект конструктору класса Pen при создании пера.

    Рисование пером с текстурным наполнением​

    Шрифты

    Для отображения текста используется шрифт (font), который определяет форму букв отображаемого текста. Работа с шрифтами в GDI+ осуществляется с помощью класса Font, который определен в заголовочном файле gdiplusheaders.h.
    Класс Font имеет следующие конструкторы:
    Font(HDC hdc);
    Font(HDC hdc, LOGFONTA *logfont);
    Font(HDC hdc, LOGFONTW *logfont);
    Font(HDC hdc, HFONT hfont);
    Font(FontFamily *family, REAL emSize, INT style = FontStyleRegular, Unit unit = UnitPoint);
    Font(WCHAR *familyName, REAL emSize, INT style = FontStyleRegular, Unit unit = UnitPoint, FontCollection *fontCollection = NULL);
    Первый конструктор создает объект класса Font на основе дескриптора контекста устройства, на который указывает параметр hdc.
    Второй и третий конструкторы создают объект класса Font на основе дескриптора контекста устройства и структуры LOGFONT, на которую указывает параметр logfont. Структура LOGFONT используется в библиотеке GDI для создания шрифтов.
    Четвертый конструктор создает объект класса Font на основе дескриптора контекста устройства и дескриптора шрифта, на который указывает параметр hfont. Дескриптор шрифта возвращают функции библиотеки GDI, которые создают шрифт, – CreateFont и CreateFontIndirect.
    Пятый и шестой конструкторы создают объект класса Font на основе имени гарнитуры шрифта, одними из известных гарнитур являются Arial, Times New Roman и Courier New. В пятом конструкторе имя гарнитуры определяется объектом класса FontFamily, на который указывает параметр family, а в шестом – строкой в формате Unicode, на которую указывает familyName.
    Параметр emSize задает размер шрифта в единицах измерения, задаваемых параметром unit. Параметр unit должен принимать одно из значений перечисляемого типа Unit.
    Параметр style задет стиль шрифта. Этот параметр должен принимать одно (или комбинацию) из значений перечисляемого типа FontStyle:

    FontStyle hex
    FontStyleRegular 0 обычный текст
    FontStyleBold 1 полужирный текст
    FontStyleItalic 2 курсивный текст
    FontStyleBoldItalic 3 полужирный и курсивный текст
    FontStyleUnderline 4 подчеркнутый текст
    FontStyleStrikeout 8 перечеркнутый текст

    Параметр fontCollection указывает на объект класса FontCollection. Класс FontCollection используется в GDI+ для представления набора шрифтов, из которого будет выбираться шрифт, подходящий под задаваемые параметры, при создании объекта класса Font. Если этот параметр установлен в NULL, шрифт будет выбираться из набора шрифтов, установленных в операционной системе.
    В следующем примере показаны два способа создания шрифта Times New Roman размером 14 пт., который соответствует курсивному и перечеркнутому тексту.
    Пример создания шрифта

    1.  // способ первый: просто создаем объект класса Font
    2.  Font font1(L«Times New Roman», 14.0,
    3.  FontStyleItalic|FontStyleUnderline);
    4.  // способ второй: сперва объект класса FontFamily,
    5.  FontFamily family(L«Times New Roman»);
    6.  // а затем объект класса Font
    7.  Font font2(&family, 14.0, FontStyleItalic|FontStyleUnderline);

    На рисунке показаны различные варианты гарнитур Arial, Times New Roman и Courier New в сочетании с различными стилями.
    Варианты шрифтов с различными стилями
    В классе Font определено несколько методов, которые могут быть полезны при работе с объектами этого класса. Основные методы этого класса перечислены в таблице. Подробное описание методов класса Font можно найти в документации Platform SDK.
    Методы класса Font

    Метод Описание
    Font* Clone() Клонирует текущий объект класса Font.
    Возвращает указатель на созданный объект класса Font, который должен быть удален вызовом оператора delete после того как станет не нужен
    GetFamily(FontFamily *family) Возвращает имя гарнитуры шрифта. Результат сохраняется в объекте класса FontFamily, на который указывает параметр family
    REAL GetHeight(REAL dpi);
    REAL GetHeight(Graphics *graphics);
    Возвращает значение междустрочного интервала шрифта
    GetLastStatus() Возвращает значение, указывающее на причину возникновения ошибки (или ее отсутствие) в последнем вызове одного из методов класса Font
    GetLogFontA(Graphics *g, LOGFONTA *logfontA);
    GetLogFontW(Graphics *g, LOGFONTW *logfontW)
    Возвращает информацию о шрифте.
    Результат сохраняется в структуру LOGFONTA (LOGFONTW), на которую указывает параметр logfontA (logfontW)
    REAL GetSize() Возвращает размер шрифта
    INT GetStyle() Возвращает стиль шрифта
    Unit GetUnit() Возвращает единицы изменения, в которых задается размер шрифта
    BOOL IsAvailable() Возвращает TRUE, если объект класса Font успешно создан, в противном случае – FALSE

    Изображения

    Для работы с изображениями в GDI+ имеется класс Image и два его потомка Metafile и Bitmap. Все эти классы определены в заголовочном файле gdiplusheaders.h.

    Векторные изображения

    Для работы с векторным изображением в GDI+ используется класс Metafile, который является потомком класса Image.
    Конструктор класса Metafile: Metafile(WCHAR *filename);
    Конструктор создает объект класса Metafile на основе метафайла (metafile). Параметр filename указывает на Unicode-строку, содержащую имя метафайла.
    В примере показано, как создать объект класса Metafile из метафайла Sample.emf.

    1.  // загрузка из файла Sample.emf
    2.  Metafile mf(L«Sample.emf»);

    Кроме загрузки векторных изображений из файла, объект класса Metafile можно создавать с помощью других конструкторов:
    Metafile(HMETAFILE hWmf, WmfPlaceableFileHeader *wmfPlaceableFileHeader, BOOL deleteWmf = FALSE);
    Metafile(HENHMETAFILE hEmf, BOOL deleteEmf = FALSE);
    Metafile(WCHAR *filename, WmfPlaceableFileHeader *wmfPlaceableFileHeader);
    Metafile(IStream *stream);
    Metafile(HDC referenceHdc, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(HDC referenceHdc, RectF &frameRect, MetafileFrameUnit frameUnit = MetafileFrameUnitGdi, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(HDC referenceHdc, Rect &frameRect, MetafileFrameUnit frameUnit = MetafileFrameUnitGdi, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(WCHAR *fileName, HDC referenceHdc, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(WCHAR *fileName, HDC referenceHdc, RectF &frameRect, MetafileFrameUnit frameUnit = MetafileFrameUnitGdi,
    EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(WCHAR *fileName, HDC referenceHdc, Rect &frameRect, MetafileFrameUnit frameUnit = MetafileFrameUnitGdi, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(IStream *stream, HDC referenceHdc, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(IStream *stream, HDC referenceHdc, RectF &frameRect, MetafileFrameUnit frameUnit = MetafileFrameUnitGdi, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Metafile(IStream *stream, HDC referenceHdc, Rect &frameRect, MetafileFrameUnit frameUnit = MetafileFrameUnitGdi, EmfType type = EmfTypeEmfPlusDual, WCHAR *description = NULL);
    Подробное описание этих конструкторов, а также всех методов класса Metafile можно найти в документации Platform SDK.

    Последнее редактирование: 8 янв 2025

  6. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Растровые изображения

    Для работы с растровым изображением в GDI+ используется класс Bitmap, который является потомком класса Image.
    Класс Bitmap имеет следующие конструкторы:
    Bitmap( WCHAR *filename, BOOL useIcm = FALSE);
    Bitmap(INT width, INT height, PixelFormat format = PixelFormat32bppARGB);
    Первый конструктор создает объект класса Bitmap на основе растрового файла. Параметр filename указывает на Unicode-строку, содержащую имя файла, а параметр useIcm указывает, применяется ли цветокоррекция согласно информации об управлении цветом в файле с изображением. Если параметр useIcm имеет значение FALSE, цветокоррекция не применяется.
    Второй конструктор создает объект класса Bitmap на основе параметров width и height, которые определяют, соответственно ширину и высоту растрового изображений. Параметр format задает формат кодирования цвета в новом растровом изображении. Этот параметр должен принимать одно следующих значений:

    • PixelFormat1bppIndexed – индексированные цвета, которые кодируются 1 битом (палитра содержит 21=2 цвета);
    • PixelFormat4bppIndexed – индексированные цвета, которые кодируются 4 битами (палитра содержит 24=16 цветов);
    • PixelFormat8bppIndexed – индексированные цвета, которые кодируются 8 битами (палитра содержит 28=256 цветов);
    • PixelFormat16bppGrayScale – оттенки серого, которые кодируются 16 битами (216=65536 оттенков серого);
    • PixelFormat16bppRGB555 – цвет кодируется 5+5+5+1=16 битами: по 5 бит на красный, зеленый и синий компоненты модели RGB. Оставшийся бит не используется;
    • PixelFormat16bppRGB565 – цвет кодируется 5+5+6=16 битами: по 5 бит на красный и синий, и по 6 бит на зеленый компоненты модели RGB;
    • PixelFormat16bppARGB1555 – цвет кодируется 1+5+5+5=16 битами: по 5 бит на красный, зеленый и синий компоненты модели RGB. Оставшийся бит используется на альфа-фактор;
    • PixelFormat24bppRGB – цвет кодируется 8+8+8=24 битами: по 8 бит на красный, зеленый и синий компоненты модели RGB;
    • PixelFormat32bppARGB – цвет кодируется 8+8+8+8=32 битами: по 8 бит на красный, зеленый и синий компоненты модели RGB. Оставшиеся биты используются на альфа-фактор;
    • PixelFormat32bppRGB – цвет кодируется 8+8+8+8=32 битами: по 8 бит на красный, зеленый и синий компоненты модели RGB. Оставшиеся биты не используются;
    • PixelFormat48bppRGB – цвет кодируется 16+16+16+16=64 битами: по 16 бит на красный, зеленый и синий компоненты модели RGB. Оставшиеся биты не используются;
    • PixelFormat64bppARGB – цвет кодируется 16+16+16+16=64 битами: по 16 бит на красный, зеленый и синий компоненты модели RGB. Оставшиеся биты используются на альфа-фактор.

    В следующем примере показано, как можно создать объект класса Bitmap из файла Sample.png.

    1.  // загрузка из файла Sample.png
    2.  Bitmap bmp(L«Sample.png»);

    Кроме уже рассмотренных конструкторов класс Bitmap имеет еще и следующие конструкторы:
    Bitmap(IStream *stream, BOOL useEmbeddedColorManagement = FALSE);
    Bitmap(INT width, INT height, INT stride, PixelFormat format, BYTE *scan0);
    Bitmap(INT width, INT height, Graphics *target);
    Bitmap(IDirectDrawSurface7 *surface);
    Bitmap(BITMAPINFO *gdiBitmapInfo, VOID *gdiBitmapData);
    Bitmap(HBITMAP hbm, HPALETTE hpal);
    Bitmap(HICON hicon);
    Bitmap(HINSTANCE hInstance, WCHAR *bitmapName);
    Для получения и установки цвета определенного пиксела в растровом изображении класс предоставляет методы GetPixel и SetPixel:
    GetPixel(INT x, INT y, Color *color);
    SetPixel(INT x, INT y, Color &color);
    Метод GetPixel сохраняет текущее значение цвета пикселя в объект класса Color, на который указывает параметр color, а метод SetPixel задает новое значение цвета пикселя. Параметры x и y задают координаты указанного пикселя.

    Класс Image

    Класс Image позволяет работать, как с векторным изображением, так и растровым.
    Класс Image имеет следующие конструкторы:
    Image(WCHAR *filename, BOOL useEmbeddedColorManagement = FALSE);
    Image(IStream *stream, BOOL useEmbeddedColorManagement = FALSE);
    Первый конструктор создает объект класса Image на основе файла (векторного или растрового). Параметр filename указывает на Unicode-строку, содержащую имя файла. Второй конструктор создает объект класса Image на основе интерфейса IStream COM-объекта, на который указывает параметр stream. Параметр useEmbeddedColorManagement указывает, применяется ли цветокоррекция согласно информации об управлении цветом в файле с изображением. Если параметр useEmbeddedColorManagement имеет значение FALSE, цветокоррекция не применяется.
    Рассмотрим некоторые методы класса Image, которые наследуют все потомки этого класса.
    Среди методов класса Image есть методы GetLastStatus и Clone. Метод Clone имеет следующий прототип:
    Image* Clone();
    В случае успеха метод Clone возвращает указатель на объект класса Image, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.
    Определить тип изображения можно с помощью метода GetType класса Image. Этот метод имеет следующий прототип:
    ImageType GetType();
    Метод возвращает одно из следующих значений перечисляемого типа ImageType:

    ImageType hex
    ImageTypeUnknown 0 неизвестный тип изображения
    ImageTypeBitmap 1 растровое изображение
    ImageTypeMetafile 2 векторное изображение

    Для определения формата кодирования цвета в изображении в классе Image есть метод GetPixelFormat(); Метод возвращает одно из значений перечисляемого типа PixelFormat.
    Ширину и высоту изображения можно определить, соответственно, с помощью методов GetWidth и GetHeight класса Image:
    UINT GetWidth();
    UINT GetHeight();
    В классе Image есть два статических метода FromFile и FromStream, которые создают объект класса Image аналогично его конструкторам:
    static Image* FromFile(WCHAR *filename, BOOL useEmbeddedColorManagement = FALSE);
    static Image* FromStream(IStream *stream, BOOL useEmbeddedColorManagement = FALSE);
    В случае успеха методы FromFile и FromStream возвращают указатель на объект класса Image, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.
    Следующий небольшой пример демонстрирует загрузку растрового изображения из файла с помощью метода FromFile класса Image:

    1. // загрузка из файла Sample.png
    2.  Image *image = Image::FromFile(L«Sample.png»);
    3.  { /* файл успешно загружен */

    Метод FromStream класса Image можно, например, использовать для загрузки изображений из ресурсов приложения Windows, как показано в примере из листинга.
    Функция загрузки изображения из ресурсов приложения

    1.  Image* ImageFromResource(HINSTANCE hInstance, LPCTSTR szResName, LPCTSTR szResType)
    2.  { // поиск ресурса указанного типа
    3.  HRSRC hRsrc = FindResource(hInstance, szResName, szResType);
    4.  if (NULL == hRsrc) return NULL;
    5.  HGLOBAL hResource = LoadResource(hInstance, hRsrc);
    6.  if (NULL == hResource) return NULL;
    7. // определяем размера ресурса
    8. DWORD cbImage = SizeofResource(hInstance, hRsrc);
    9.  // выделение памяти для буфера
    10.  HGLOBAL hData = GlobalAlloc(GMEM_FIXED, cbImage);
    11.  { // копируем изображение в буфер
    12.  CopyMemory(GlobalLock(hData), LockResource(hResource), cbImage);
    13.  UnlockResource(hResource);
    14.  FreeResource(hResource); // освобождение ресурса
    15.  { IStream *pStream = NULL;
    16.  HRESULT hr = CreateStreamOnHGlobal(hData, TRUE, &pStream);
    17.  if (SUCCEEDED(hr) && NULL != pStream)
    18.  { Image *image = Image::FromStream(pStream); // загрузка изображения
    19.  GlobalFree(hData); // освобождение памяти

    Класс Image предоставляет очень удобный механизм создания эскизов изображений, которые содержат уменьшенную копию изображения. Поскольку эскизы имеют очень малые размеры, они очень быстро отображаются. Для создания эскизов в классе Image определен метод GetThumbnailImage:
    Image* GetThumbnailImage(UINT thumbWidth, UINT thumbHeight, GetThumbnailImageAbort callback = NULL, VOID *callbackData = NULL);
    Первые два параметра, thumbWidth и thumbHeight, указывают требуемые размеры эскиза: соответственно, ширину и высоту. Параметры callback и callbackData могут использоваться, если нужна возможность прерывания процесса создания эскиза. Эти параметры могут быть установлены в NULL.
    В случае успеха метод GetThumbnailImage возвращает указатель на объект класса Image, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.
    Следующий пример демонстрирует создание эскиза размером 320×240 из файла растрового изображения:

    1.  // загрузка изображения 320×240 из файла Sample.png
    2.  Image *image = Image(L«Sample.png»).GetThumbnailImage(320, 240);
    3.  { /* Изображение успешно загружено */

    Последнее редактирование: 9 янв 2025

  7. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Вывод графики с помощью GDI+

    Все операции графического вывода в GDI+ выполняются с помощью методов класса Graphics, который определен в заголовочном файле gdiplusgraphics.h.
    Класс Graphics имеет следующие конструкторы:
    Graphics(HDC hdc);
    Graphics(HDC hdc, HANDLE hdevice);
    Graphics(HWND hwnd, BOOL icm = FALSE);
    Graphics(Image *image);
    Первый и второй конструкторы создают объект класса Graphics на основе дескриптора контекста устройства, на который указывает параметр hdc. Второй конструктор для создания объекта класса Graphics также использует дескриптор устройства отображения (параметр hdevice). Третий конструктор создает объект класса Graphics на основе дескриптора окна hwnd. Параметр icm определяет, будет ли применяться настройка цвета. Если параметр icm имеет значение FALSE, настройка цвета не применяется. Четвертый конструктор создает объект класса Graphics на основе объекта класса Image, на который указывает параметр image.
    В приведенном далее примере показана функция отображения, в которой на основе контекста устройства отображения создается объект класса Graphics.
    Пример функции отображения

    1.  { // создаем объект класса Graphics для рисования

    Очистка

    Рисование на экране компьютера отличается от рисования на бумаге, так как бумага изначально является белой и все, что нужно сделать – это нарисовать на ней изображение. Однако при рисовании на экране компьютера прежде необходимо удалить старое уже нарисованное изображение, хранящееся в памяти компьютера.
    В классе Graphics есть метод Clear, который очищает область отображения некоторым цветом фона. Метод Clear имеет следующий прототип:
    Clear(Color &color);
    Параметр color – объект класса Color, в котором представлен цвет фона, используемый для очистки области отображения.

    Рисование фигур и линий

    В классе Graphics все методы рисования имеют две версии: методы с префиксом Draw для рисования линий, контуров и т.п. и c префиксом Fill для заливки замкнутых фигур. Методам с префиксом Draw в качестве параметра требуется указатель на объект класса Pen, методам с префиксом Fill передается указатель на объект класса, порожденного от класса Brush.

    Рисование линий

    Для рисования различных линий используется метод DrawLine класса Graphics. Метод имеет следующие прототипы:
    DrawLine(Pen *pen, INT x1, INT y1, INT x2, INT y2);
    DrawLine(Pen *pen, REAL x1, REAL y1, REAL x2, REAL y2);
    DrawLine(Pen *pen, Point &pt1, Point &pt2);
    DrawLine(Pen *pen, PointF &pt1, PointF &pt2);
    Параметр pt1 (pt2), а также параметры x1 (x2) и y1 (y2) определяют координаты первой (второй) точки рисуемой линии.
    В листинге представлен пример, в котором демонстрируется рисование двух линий пером черного цвета.
    Пример рисования линий

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо черного цвета
    5.  Pen blackPen(Color::Black);
    6.  // рисуем линию с координатами (100,100) и (200,80)
    7.  g.DrawLine(&blackPen, 100, 100, 200, 80);
    8.  Point pt1(120, 20); // точка (120,20)
    9.  Point pt2(40, 60); // точка (40,60)
    10.  // рисуем линию с координатами (120,20) и (40,60)
    11.  g.DrawLine(&blackPen, pt1, pt2);

    Для рисования ломаных линий используется метод DrawLines класса Graphics. Этот метод имеет следующие прототипы:
    DrawLines(Pen *pen, Point *points, INT count);
    DrawLines(Pen *pen, PointF *points, INT count);
    Параметр points указывает на массив объектов класса Point (PointF), которые содержат координаты вершин рисуемой ломаной линии, параметр count задает количество элементов в массиве, на который указывает параметр points.
    В следующем примере демонстрируется рисование ломаной линии из четырех точек с помощью пера черного цвета.
    Пример рисования ломаной линии

    1.  { // создаем объект класса Graphics для рисования
    2. // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо черного цвета
    5.  Pen blackPen(Color::Black);
    6.  Point(100, 100), // точка (100,100)
    7.  Point(200, 80), // точка (200,80)
    8.  Point(120, 20), // точка (120,20)
    9.  Point(40, 60) // точка (40,60)
    10.  g.DrawLines(&blackPen, points, 4);

    Рисование прямоугольников

    Для рисования прямоугольников используется метод DrawRectangle класса Graphics, а для закрашивания прямоугольников используется метод FillRectangle этого класса. Методы DrawRectangle и FillRectangle имеет следующие прототипы:
    DrawRectangle(Pen *pen, INT x, INT y, INT width, INT height);
    DrawRectangle(Pen *pen, REAL x, REAL y, REAL width, REAL height);
    DrawRectangle(Pen *pen, Rect &rect);
    DrawRectangle(Pen *pen, RectF &rect);
    FillRectangle(Brush *brush, INT x, INT y, INT width, INT height);
    FillRectangle(Brush *brush, REAL x, REAL y, REAL width, REAL height);
    FillRectangle(Brush *brush, Rect &rect);
    FillRectangle(Brush *brush, RectF &rect);
    Параметр rect, а также параметры x, y, width и height, определяют расположение и размер прямоугольника.
    Как уже было сказано ранее, в классе Graphics методы закрашивания замкнутых фигур отделены от методов рисования контуров таких фигур. Поэтому если необходимо нарисовать закрашенный прямоугольник с контуром, то первым делом необходимо нарисовать закрашенный прямоугольник с помощью метода FillRectangle, а затем контур этого прямоугольника с помощью метода DrawRectangle.
    В листинге представлен пример демонстрирующий рисование двух прямоугольников, изображенных на рисунке.
    Пример рисования прямоугольников

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо зеленого цвета
    5.  Pen pen(Color(0, 128, 0));
    6.  // создаем сплошную кисть
    7.  SolidBrush solidBrush(Color::Yellow); // желтый цвет
    8.  // рисуем закрашенный прямоугольник
    9.  g.FillRectangle(&solidBrush, 100, 70, 120, 50);
    10.  // рисуем контур прямоугольника
    11.  g.DrawRectangle(&pen, 100, 70, 120, 50);
    12.  Rect rect(10, 10, 100, 50);
    13. // рисуем закрашенный прямоугольник
    14.  g.FillRectangle(&solidBrush, rect);
    15.  // рисуем контур прямоугольника
    16.  g.DrawRectangle(&pen, rect);

    Пример нарисованных прямоугольников​

    Для рисования и закрашивания сразу нескольких прямоугольников используются, соответственно, методы DrawRectangles и FillRectangles класса Graphics. Эти методы имеет следующие прототипы:
    DrawRectangles(Pen *pen, Rect *rects, INT count);
    DrawRectangles( Pen *pen, RectF *rects, INT count);
    FillRectangles(Brush *brush, Rect *rects, INT count);
    FillRectangles(Brush *brush, RectF *rects, INT count);
    Параметр rects указывает на массив объектов класса Rect (RectF), которые определяют расположение и размеры прямоугольников, а параметр count задает количество элементов в массиве, на который указывает параметр rects.
    В листинге представлен немного видоизменный пример. В этом примере для рисования сразу двух прямоугольников используются методы FillRectangles и DrawRectangles.
    Пример рисования сразу нескольких прямоугольников

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо зеленого цвета
    5.  Pen pen(Color(0, 128, 0));
    6.  // создаем сплошную кисть
    7.  SolidBrush solidBrush(Color::Yellow); // желтый цвет
    8.  // массив прямоугольников
    9.  Rect rects[2] = { Rect(100, 70, 120, 50), Rect(10, 10, 100, 50) };
    10.  // рисуем закрашенные прямоугольники
    11.  g.FillRectangles(&solidBrush, rects, 2);
    12.  // рисуем контуры прямоугольников
    13.  g.DrawRectangles(&pen, rects, 2);

    Рисование многоугольников
    Для рисования и закрашивания полигонов (многоугольников) используются, соответственно, методы DrawPolygon и FillPolygon класса Graphics. Эти методы имеют следующие прототипы:
    DrawPolygon(Pen *pen, Point *points, INT count);
    DrawPolygon(Pen *pen, PointF *points, INT count);
    FillPolygon(Brush *brush, Point *points, INT count);
    FillPolygon(Brush *brush, PointF *points, INT count);
    FillPolygon(Brush *brush, Point *points, INT count, FillMode fillMode);
    FillPolygon(Brush *brush, PointF *points, INT count, FillMode fillMode);
    Параметр points указывает на массив объектов класса Point (PointF), которые содержат координаты вершин рисуемого полигона, а параметр count задает количество элементов в массиве, на который указывает параметр points. Параметр fillMode определяет, как будет производиться заполнение для внутренней части полигона. Этот параметр должен принимать одно из значений FillMode.
    При заполнении полигонов необходимо определить область, которая должна быть заполнена. По умолчанию используется режим заполнения с чередованием. Для того чтобы определить область заполнения в режиме заполнения с чередованием, строится луч из произвольной точки внутри полигона к некоторой точке, которая явно расположена вне полигона. Если луч пересекает нечетное число ребер полигона, выбранная точка расположена в заполняемой области. Четное число пересечений означает, что точка не находится в области заполнения.
    В режиме заполнения с поворотом, так же строится луч, а затем находятся пересечения этого луча с ребрами полигона. Каждому такому пересечению присваивается +1 или –1, в зависимости от того, как ребро пересекает луч – по часовой (слева направо) или против часовой стрелки (справа налево). Если сумма этих значений будет отлична от нуля, точка считается расположенной внутри области заполнения. Если же сумма равна нулю, точка находится вне области заполнения.
    На рисунке показана пятиконечная звезда, нарисованная с различными режимами заполнения.
    Примеры заполнения полигонов (с указанием вершин)
    В следующем примере демонстрируется рисование закрашенного треугольника с контуром черного цвета.
    Пример рисования треугольника

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо черного цвета
    5.  Pen blackPen(Color::Black);
    6.  // создаем штриховую кисть
    7.  HatchStyleDiagonalBrick, Color::Black, Color::LightGray);
    8.  Point points[3] = { Point(100, 100), // точка (100,100)
    9.  Point(200, 130), // точка (200,130)
    10.  Point(110, 200) // точка (110,200)
    11.  // рисуем закрашенный треугольник
    12.  g.FillPolygon(&hatchBrush, points, 3);
    13.  // рисуем контур треугольника
    14.  g.DrawPolygon(&blackPen, points, 3);

    Рисование эллипсов, окружностей, дуг и секторов

    Для рисования и закрашивания эллипсов используются, соответственно, методы DrawEllipse и FillEllipse класса Graphics. Эти методы имеют следующие прототипы:
    DrawEllipse(Pen *pen, INT x, INT y, INT width, INT height);
    DrawEllipse(Pen *pen, REAL x, REAL y, REAL width, REAL height);
    DrawEllipse(Pen *pen, Rect &rect);
    DrawEllipse(Pen *pen, RectF &rect);
    FillEllipse(Brush *brush, INT x, INT y, INT width, INT height);
    FillEllipse(Brush *brush, REAL x, REAL y, REAL width, REAL height);
    FillEllipse(Brush *brush, Rect &rect);
    FillEllipse(Brush *brush, RectF &rect);
    Параметр rect, а также параметры x, y, width и height, определяют расположение и размер эллипса, как показано на рисунке.

    Расположение и размер эллипса​

    Следующий пример демонстрирует рисование закрашенного эллипса, круга и окружности, изображенных на рисунке.
    Пример рисования эллипса, круга и окружности

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо черного цвета
    5.  Pen blackPen(Color::Black);
    6.  // создаем две сплошные кисти
    7.  SolidBrush solidBrush1(Color::Yellow);
    8.  SolidBrush solidBrush2(Color::Aqua);
    9.  // рисуем закрашенный эллипс
    10.  g.FillEllipse(&solidBrush1, 10, 10, 160, 80);
    11.  g.DrawEllipse(&blackPen, 10, 10, 160, 80);
    12.  Rect rect(180, 50, 70, 70);
    13.  g.FillEllipse(&solidBrush2, rect);
    14.  g.DrawEllipse(&blackPen, rect);

    Как видно из приведенного примера, перечисленные методы класса Graphics для рисования и закрашивания эллипсов также можно использовать, соответственно, для рисования окружности и круга.

    Пример эллипса, круга и окружности​

    Рисование дуги похоже на рисование эллипса. Для рисования дуг использует метод DrawArc класса Graphics. Этот метод имеет следующие прототипы:
    DrawArc(Pen *pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle);
    DrawArc(Pen *pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle);
    DrawArc(Pen *pen, Rect &rect, REAL startAngle, REAL sweepAngle);
    DrawArc(Pen *pen, RectF &rect, REAL startAngle, REAL sweepAngle);
    Параметр rect, а также параметры x, y, width и height, определяют расположение и размер прямоугольника, в который вписывается рисуемая дуга. Параметр startAngle задает угол (в градусах) между осью х и начальной точкой дуги. Параметр sweepAngle задает угол (в градусах) между начальной и конечной точкой дуги.
    На рисунке показано, как рисуется дуга по заданным параметрам.

    Рисование дуги​

    В листинге представлен пример демонстрирующий рисование двух дуг пером красного цвета и толщиной 2.
    Пример рисования дуг

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо красного цвета и толщиной 2
    5.  Pen redPen(Color::Red, 2.f);
    6.  // рисуем дугу от -10 градусов до 130 градусов
    7.  g.DrawArc(&redPen, 100, 70, 120, 50, 10.f, 140.f);
    8.  Rect rect(10, 10, 100, 100);
    9.  // рисуем дугу от 90 градусов до 300 градусов
    10.  g.DrawArc(&redPen, rect, 90.f, 210.f);

    Для того чтобы нарисовать фигуру «сектор» в классе Graphics есть метод DrawPie и есть метод FillPie, который закрашивает эту фигуру.

    Пример рисования секторов​

    Методы DrawPie и FillPie класса Graphics имеют следующие прототипы:
    DrawPie(Pen *pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle);
    DrawPie(Pen *pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle);
    DrawPie(Pen *pen, Rect &rect, REAL startAngle, REAL sweepAngle);
    DrawPie(Pen *pen, RectF &rect, REAL startAngle, REAL sweepAngle);
    FillPie(Brush *brush, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle);
    FillPie(Brush *brush, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle);
    FillPie(Brush *brush, Rect &rect, REAL startAngle, REAL sweepAngle);
    FillPie(Brush *brush, RectF &rect, REAL startAngle, REAL sweepAngle);
    Параметр rect, а также параметры x, y, width и height, определяют расположение и размер прямоугольника, в который вписывается сектор. Параметр startAngle задает угол (в градусах) между осью х и начальной точкой сектора. Параметр sweepAngle задает угол (в градусах) между начальной и конечной точкой сектора.
    В следующем примере продемонстрировано рисование диаграммы, состоящей из четырех секторов.
    Пример рисования секторной диаграммы

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо черного цвета
    5.  Pen blackPen(Color::Black);
    6.  // создаем сплошную кисть
    7.  SolidBrush solidBrush(Color::Red); // красный цвет
    8.  g.FillPie(&solidBrush, 5, 30, 300, 300, 110.f, 30.f);
    9.  // рисуем контур первого сектора
    10.  g.DrawPie(&blackPen, 5, 30, 300, 300, 110.f, 30.f);
    11.  // рисуем еще три сектора…
    12.  Color colors[3] = { Color(255, 192, 0), Color(192, 0, 0), Color(0, 176, 80)};
    13.  float sweepAngle[3] = { 100.f, 115.f, 115.f};
    14.  float angle = 140.f; // начальный угол
    15.  Rect rect(10, 10, 300, 300);
    16.  for (int i = 0; i < 3; ++i) {
    17.  solidBrush.SetColor(colors[I])[/I]; // изменяем цвет кисти
    18.  g.FillPie(&solidBrush, rect, angle, sweepAngle);
    19.  g.DrawPie(&blackPen, rect, angle, sweepAngle);
    20.  angle += sweepAngle; // увеличиваем угол

    Последнее редактирование: 9 янв 2025

  8. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Рисование сплайнов

    В дополнение к рисованию линий и дуг GDI+ поддерживает рисование сплайнов (splines), которые являются очень удобным инструментом для рисования кривых в компьютерной графике.
    В классе Graphics есть несколько методов, которые позволяют рисовать кубические сплайны (cubic splines) и сплайны Безье (splines Bezier). Для рисования кубических сплайнов необходимо использовать методы DrawCurve и DrawClosedCurve. Метод DrawCurve рисует обычный кубический сплайн, а метод DrawClosedCurve – замкнутый кубический сплайн. Эти методы имеют следующие прототипы:
    DrawCurve(Pen *pen, Point *points, INT count);
    DrawCurve(Pen *pen, PointF *points, INT count);
    DrawCurve(Pen *pen, Point *points, INT count, REAL tension);
    DrawCurve(Pen *pen, PointF *points, INT count, REAL tension);
    DrawCurve(Pen *pen, Point *points, INT count, INT offset, INT numberOfSegments, REAL tension = 0.5f);
    DrawCurve(Pen *pen, PointF *points, INT count, INT offset, INT numberOfSegments, REAL tension = 0.5f);
    DrawClosedCurve(Pen *pen, Point *points, INT count);
    DrawClosedCurve(Pen *pen, PointF *points, INT count);
    DrawClosedCurve(Pen *pen, Point *points, INT count, REAL tension);
    DrawClosedCurve(Pen *pen, PointF *points, INT count, REAL tension);
    Параметр points указывает на массив объектов класса Point (PointF), определяющий набор точек, через которые проходит сплайн, а параметр count задает количество элементов в массиве, на который указывает параметр points.
    Параметр tension задает напряжение сплайна. По умолчанию напряжение сплайна равно 0.5.
    Параметр offset указывает индекс (начиная с 0) точки в массиве, с которой начинается рисование сплайна, а параметр numberOfSegments указывает их количество. Важно отметить, что все «невидимые» точки из массива, на который указывает параметр points, все равно будут использованы для расчетов.

    Кубический сплайн, заданный четырьмя точками​

    В классе Graphics есть метод FillClosedCurve для закрашивания замкнутых кубических сплайнов.
    FillClosedCurve(Brush *brush, Point *points, INT count);
    FillClosedCurve(Brush *brush, PointF *points, INT count);
    FillClosedCurve(Brush *brush, Point *points, INT count, FillMode fillMode, REAL tension = 0.5f);
    FillClosedCurve(Brush *brush, PointF *points, INT count, FillMode fillMode, REAL tension = 0.5f);
    Параметры points, count и tension аналогичны одноименным параметрам метода DrawClosedCurve. Параметр fillMode определяет, как будет производиться заполнение области, образуемой замкнутым сплайном. Этот параметр должен принимать одно из значений перечисляемого типа FillMode.
    В листинге показан пример рисования замкнутого кубического сплайна, проходящего через семь точек.
    Пример рисования замкнутого кубического сплайна

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо зеленого цвета
    5.  // создаем сплошную кисть
    6.  SolidBrush solidBrush(Color::Yellow); // желтый цвет
    7.  // массив точек, через кот. Проходит сплайн
    8.  Point points[7] = { Point(50, 50), // точка (50,50)
    9.  Point(100, 25), // точка (100,25)
    10.  Point(200, 5), // точка (200,5)
    11.  Point(250, 50), // точка (250,50)
    12.  Point(300, 100), // точка (300,100)
    13.  Point(350, 200), // точка (350,200)
    14.  Point(250, 250) // точка (250,250)
    15.  // закрашиваем замкнутый сплайн
    16.  g.FillClosedCurve(&solidBrush, points, 7);
    17.  // рисуем замкнутый сплайн
    18.  g.DrawClosedCurve(&pen, points, 7);

    Если нужно нарисовать сплайн Безье следует использовать метод DrawBezier или DrawBeziers. Метод DrawBezier рисует обычный сплайн
    Безье, а метод DrawBeziers – последовательность соединенных сплайнов Безье.
    Метод DrawBezier имеет следующие прототипы:
    DrawBezier(Pen *pen, INT x1, INT y1, INT x2, INT y2, INT x3, INT y3, INT x4, INT y4);
    DrawBezier(Pen *pen, REAL x1, REAL y1, REAL x2, REAL y2, REAL x3, REAL y3, REAL x4, REAL y4);
    DrawBezier(Pen *pen, Point &pt1, Point &pt2, Point &pt3, Point &pt4);
    DrawBezier(Pen *pen, PointF &pt1, PointF &pt2, PointF &pt3, PointF &pt4);
    Параметры pt1, pt2, pt3 и pt4, а также параметры x1, y1, x2, y2, x3, y3, x4 и y4 задают координаты точек, определяющих положение и кривизну сплайна Безье.
    В следующем примере демонстрируется рисование двух различных сплайнов Безье с помощью метода DrawBezier класса Graphics.
    Пример рисования сплайнов Безье

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  Pen pen1(Color::Green); // зеленый цвет
    5.  Pen pen2(Color::Red); // красный цвет
    6.  // рисуем сплайн Безье с начальной точкой (100,100)
    7.  // и конечной точкой (500,100)
    8.  g.DrawBezier(&pen1, 100, 100, 200, 10, 350, 50, 500, 100);
    9.  Point pt1(100, 200); // точка (100,200)
    10.  Point pt2(200, 150); // точка (200,150)
    11.  Point pt3(400, 110); // точка (400,110)
    12.  Point pt4(500, 200); // точка (500,200)
    13.  // рисуем сплайн Безье с начальной точкой (100,200) и конечной точкой (500,200)
    14.  g.DrawBezier(&pen2, pt1, pt2, pt3, pt4);

    Метод DrawBeziers имеет следующие прототипы:
    DrawBeziers(Pen *pen, Point *points, INT count);
    DrawBeziers(Pen *pen, PointF *points, INT count);
    Параметр points указывает на массив объектов класса Point (PointF), определяющий набор контрольных точек сплайнов Безье, а параметр count задает количество элементов в массиве, на который указывает параметр points. При этом точки в массиве должны располагаться так, чтобы последняя точка одного сплайна Безье, являлась начальной точкой следующего сплайна Безье.
    Следующий пример демонстрирует рисование кривой, состоящей сразу из двух сплайнов Безье.
    Пример рисования кривой, состоящей из сплайнов Безье

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо синего цвета
    5.  Point points[7] = { Point(100, 100), // начальная точка 1-го сплайна
    6.  Point(200, 50), Point(400, 10), Point(500, 100), // конечная точка 1-го сплайна
    7.  Point(600, 200), Point(500, 400), Point(800, 350)}; // конечная точка 2-го сплайна
    8.  // рисуем кривую из сплайнов Безье
    9.  g.DrawBeziers(&pen, points, 7);

    Последнее редактирование: 6 янв 2025

  9. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Отображение текста

    Для отображения текста в классе Graphics определен метод DrawString, который имеет следующие прототипы:
    DrawString(WCHAR *string, INT length, Font *font, PointF &origin, Brush *brush);
    DrawString( WCHAR *string, INT length, Font *font, PointF &origin, StringFormat *stringFormat, Brush *brush);
    DrawString(WCHAR *string, INT length, Font *font, RectF &layoutRect, StringFormat *stringFormat, Brush *brush);
    Первый параметр, string, указывает на Unicode-строку, содержащую отображаемый текст, а второй параметр, length, задает длину этой строки. Параметр length может принимать значение -1, если строка завершается нуль-символом.
    Третий параметр, font, указывает на объект класса Font, который представляет шрифт для отображения текста.
    Параметр origin – объект класса PointF, который содержит координаты точки расположения текста, а параметр layoutRect определяет прямоугольник, в котором будет отображаться текст.
    Параметр stringFormat указывает на объект класса StringFormat, который управляет форматированием текста.
    Последний параметр, brush, указывает на объект класса Brush, который представляет кисть для отображения текста.
    В следующем примере показано, как с помощью метода DrawString класса Graphics вывести текст «Привет мир!» в виде одной горизонтальной строки.
    Пример простого вывода текста

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем шрифт Times New Roman
    5.  Font font(L«Times New Roman», 20.f, FontStyleBold);
    6.  // создаем сплошную кисть
    7.  SolidBrush blackBrush(Color::Black); // черный цвет
    8.  // выводим текст, который начинается в точке (10,10)
    9.  g.DrawString(L«Привет мир!», 1, &font, PointF(10.f, 10.f), &blackBrush);

    При необходимости форматированного вывода текста необходимо использовать объект класса StringFormat, который определен в заголовочном файле gdiplusstringformat.h.
    Класс StringFormat имеет следующие конструкторы:
    StringFormat(INT formatFlags = 0, LANGID language = LANG_NEUTRAL);
    StringFormat(StringFormat *format);
    Первый конструктор создает объект класса StringFormat на основе флагов форматирования, которые задает параметр formatFlags, и идентификатора язык, который задается параметром language.
    Параметр formatFlags может принимать одно (или комбинацию) из перечисляемого типа StringFormatFlags, а значение параметра language можно задавать с помощью макроса MAKELANGID, следующим образом:

    1.  LANGID language = MAKELANGID(LANG_RUSSIAN, SUBLANG_RUSSIAN_RUSSIA);

    Второй конструктор класса StringFormat создает копию объекта этого же класса, на который указывает параметр format.
    В листинге представлен пример форматированного вывода текста, результат которого показан на рисунке.
    Пример форматированного вывода текста

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем шрифт Times New Roman
    5.  Font font(L«Times New Roman», 20.f, FontStyleBold);
    6.  // создаем сплошную кисть
    7.  SolidBrush blackBrush(Color::Black); // черный цвет
    8.  // создаем перо красного цвета
    9.  // создаем объект класса StringFormat для форматированного вывода текста
    10.  // ограничивающий прямоугольник
    11.  RectF rect(10.f, 10.f, 300.f, 80.f);
    12.  g.DrawString(L«Съешь ещё этих мягких французских булок, да выпей чаю.», 1, &font, rect, &sf, &blackBrush);
    13.  // рисуем прямоугольник (только для наглядности)
    14.  g.DrawRectangle(&pen, rect);

    Форматированный вывод текста​

    Прежде чем перейти к изучению методов класса StringFormat, следует отметить, что в этом классе (как и во многих других классах GDI+) есть методы GetLastStatus и Clone. Метод Clone имеет следующий прототип:
    StringFormat* Clone();
    В случае успеха метод Clone возвращает указатель на объект класса StringFormat, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.

    Флаги форматирования

    Флаги форматирования можно задавать в качестве одного из параметров конструктора класса StringFormat при создании объекта это класса. Можно также задать флаги форматирования с помощью метода SetFormatFlags:
    SetFormatFlags(INT flags);
    Параметр flags может принимать одно (или комбинацию) из следующих значений перечисляемого типа StringFormatFlags:
    ▪ StringFormatFlagsDirectionRightToLeft – текст будет отображаться справа на лево;
    ▪ StringFormatFlagsDirectionVertical – текст будет отображаться вертикально;
    ▪ StringFormatFlagsNoFitBlackBox – текст будет отображаться без дополнительного пустого пространства между внутренним контуром прямоугольной зоны форматирования и прямоугольником, ограничивающего отображаемый текст;
    ▪ StringFormatFlagsDisplayFormatControl – разрешает отображение управляющих символов, например, таких как метка слева направо (LefttoRight Embedding, LRE);
    ▪ StringFormatFlagsNoFontFallback – запрещается обращение к альтернативным шрифтам при отображении символов, не поддерживаемых в указанном шрифте. Такие символы, как правило, будут отображаться с помощью пустого квадрата;
    ▪ StringFormatFlagsMeasureTrailingSpaces – запрещается исключать пробелы в конце каждой строки при определении размеров ограничивающего прямоугольника;
    ▪ StringFormatFlagsNoWrap – запрещается автоматический перенос текста на новую строку при форматировании в прямоугольнике;
    ▪ StringFormatFlagsLineLimit – при форматировании в прямоугольнике будут отображаться только целые строки;
    ▪ StringFormatFlagsNoClip – разрешается отображать текст, выходящий за пределы прямоугольной зоны форматирования.
    Определить установленные флаги форматирования можно с помощью метода GetFormatFlags класса StringFormat:
    INT GetFormatFlags();
    На рисунке показаны результаты использования некоторых флагов форматирования текста.

    Выравнивание текста

    При отображении текста может потребоваться выровнять этот текст. Чтобы выровнять текст необходимо в метод DrawString класса Graphics передать объект класса StringFormat, в котором задать параметры выравнивания текста с помощью методов SetAlignment и SetLineAlignment. Метод SetAlignment задает выравнивание текста по горизонтали, а метод SetLineAlignment – по вертикали. Эти методы имеют следующие прототипы:
    Status SetAlignment(StringAlignment align);
    Status SetLineAlignment(StringAlignment align);

    Применение флагов форматирования текста

    Параметр align задает выравнивание текста относительно точки расположения текста или относительно границ прямоугольника, в котором будет отображаться текст. Этот параметр должен принимать одно из следующих значений перечисляемого типа StringAlignment:
    ▪ StringAlignmentNear – выравнивание по ближнему краю;
    ▪ StringAlignmentCenter – выравнивание по центру;
    ▪ StringAlignmentFar – выравнивание по дальнему краю.
    На рисунках показаны различные варианты выравнивания текста относительно точки и границ прямоугольника.
    Варианты выравнивания текста относительно точки
    Варианты выравнивания текста относительно границ прямоугольника
    Для горизонтального выравнивания ближним краем будет левый, а дальним краем – правый. Однако, при отображений текста справа на лево ближним краем будет правый, а дальним краем – левый. Для вертикального выравнивания ближним краем будет верхний, а дальним краем – нижний.
    Определить текущее горизонтальное и вертикальное выравнивание можно, соответственно, с помощью методов GetAlignment и GetLineAlignment класса StringFormat. Эти методы имеют следующие прототипы:
    StringAlignment GetAlignment();
    StringAlignment GetLineAlignment();

    Вывод текста с табуляцией

    Для отображаемого текста можно устанавливать позиции табуляции. Для этого в классе StringFormat есть метод SetTabStops. Этот метод имеет следующий прототип:
    SetTabStops(REAL firstTabOffset, INT count, REAL *tabStops);
    Первый параметр, firstTabOffset, задает первое смещение позиции табуляции. Второй параметр, count, определяет количество элементов в массиве табуляции, на который указывает третий параметр – tabStops. Параметр tabStops указывает на массив значений типа float, которые задают смешение позиции табуляции.
    Каждое смещение позиции табуляции, кроме первого, выполняется относительно предыдущей позиции. Первое смещение позиции табуляции выполняется относительно первоначальной позиции смещения. Например, если начальная позиция смещения равна 5 и первое смещение позиции табуляции равно 40, первое смещение позиции табуляции расположено в позиции 45. Если начальная позиция смещения равна нулю, первое смещение позиции табуляции определяется относительно позиции 0, начала строки.
    Следующий пример демонстрирует форматированный вывода текста с табуляцией. Результат показан на рисунке.
    Пример задания позиций табуляции для выводимого текста

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  Font font(L«Arial», 11.f, FontStyleRegular);
    5.  // создаем сплошную кисть
    6.  SolidBrush blackBrush(Color::Black); // черный цвет
    7.  // создаем перо серого цвета
    8.  // создаем объект класса StringFormat для форматированного вывода текста
    9.  // задаем выравнивание по левому краю
    10.  sf.SetAlignment(StringAlignmentNear);
    11.  // задаем выравнивание по верхнему краю
    12.  sf.SetLineAlignment(StringAlignmentNear);
    13.  float tabs[4] = {50.f, 100.f, 100.f, 100.f};
    14.  // устанавливаем позиции табуляции
    15.  sf.SetTabStops(0.0, 4, tabs);
    16.  // ограничивающий прямоугольник
    17.  RectF rect(10.0, 10.0, 350.0, 90.0);
    18.  wchar_t text[] = L«№\tФамилия\tИмя\tОтчество\n\
    19. 1.\tАндреев\tАлександр\tДмитриевич\n\
    20. 2.\tВасильев\tЮрий\tГеннадиевич\n\
    21. 3.\tГромова\tИнна\tВикторовна\n\
    22. 4.\tМартынов\tПавел\tБорисович»;
    23.  g.DrawString(text, 1, &font, rect, &sf, &blackBrush);
    24.  g.DrawRectangle(&pen, rect);

    Форматированный вывод текста с табуляцией​

    Определить количество установленных позиций табуляции можно с помощью метода GetTabStopCount, а получить значения этих позиций можно с помощью метода GetTabStops. Прототипы этих методов записываются следующим образом:
    INT GetTabStopCount();
    GetTabStops(INT count, REAL *firstTabOffset, REAL *tabStops);
    Первый параметр, count, указывает количество элементов в массиве, на который указывает параметр tabStops.
    Второй параметр, firstTabOffset, указывает на переменную типа float, в которую будет записано значение первого смещения позиции табуляции.
    Третий параметр, tabStops, указывает на массив типа float, в который будут сохранены значения установленных позиций табуляции.

    Вывод «горячих» клавиш

    Символ «&» (амперсанд) имеет специальное назначение в тексте, используемом в меню, кнопках и других элементах управления – он означает, что следующий за ним знак должен быть подчеркнут и будет использоваться для быстрого доступа к элементу управления. В классе StringFormat есть метод SetHotkeyPrefix, который определяет, как при отображении интерпретируются амперсанды.
    Метод SetHotkeyPrefix имеет следующий прототип:
    SetHotkeyPrefix(HotkeyPrefix hotkeyPrefix);
    Параметр hotkeyPrefix определяет, как будут интерпретироваться амперсанды. Этот параметр должен принимать одно из следующих значений перечисляемого типа HotkeyPrefix:
    По умолчанию префикс «горячих» клавиш отсутствует. Определить, как интерпретируются амперсанды можно с помощью метода GetHotkeyPrefix класса StringFormat. Этот метод имеет следующий прототип:
    HotkeyPrefix GetHotkeyPrefix();
    В таблице показаны варианты отображения текста «&Файл» с различными режимами интерпретации амперсанда.

    Обрезание текста

    В классе StringFormat есть метод SetTrimming, который определяет, как должны отображаться символы, если текст не полностью помещается в ограничивающий прямоугольник. Метод SetTrimming имеет следующий прототип:
    SetTrimming(StringTrimming trimming);
    Параметр trimming определяет формат обрезания текста. Этот параметр должен принимать одно из следующих значений перечисляемого типа StringTrimming:
    По умолчанию текст обрезается по ближайшему символу. Определить текущий формат обрезания текста можно с помощью метода GetTrimming класса StringFormat. Этот метод имеет следующий формат:
    StringTrimming GetTrimming();
    На рисунке показаны различные варианты обрезания символов, если текст не помещается в ограничивающий прямоугольник.
    Определить ограничивающий прямоугольник для отображения текста с заданным шрифтом можно с помощью метода MeasureString класса Graphics. Этот метод имеет следующие прототипы:
    MeasureString(WCHAR *string, INT length, Font *font, PointF &origin, RectF *boundingBox);
    MeasureString(WCHAR *string, INT length, Font *font, RectF &layoutRect, RectF *boundingBox);
    MeasureString(WCHAR *string, INT length, Font *font, PointF &origin, StringFormat *stringFormat, RectF *boundingBox);
    MeasureString(WCHAR *string, INT length, Font *font, RectF &layoutRect, StringFormat *stringFormat, RectF *boundingBox, INT *codepointsFitted = 0, INT *linesFilled = 0);
    MeasureString(WCHAR *string, INT length, Font *font, RectF &layoutRect, StringFormat *stringFormat, SizeF *size, INT *codepointsFitted = 0, INT *linesFilled = 0);
    Параметры string, length, font, origin, layoutRect и stringFormat аналогичны одноименным параметрам метода DrawString класса Graphics.
    Параметр boundingBox указывает на объект класса RectF, в который будут сохранены расположение и размер ограничивающего прямоугольника.
    Параметр size указывает на объект класса SizeF, в который будет сохранен размер ограничивающего прямоугольника.
    Параметр codepointsFitted указывает на переменную типа INT, в которую записывается количество символов в тексте, размещенном в ограничивающем прямоугольнике.
    Параметр linesFilled указывает на переменную типа INT, в которую записывается количество строк в тексте, размещенном в ограничивающем прямоугольнике.
    Предопределенные форматы
    В классе StringFormat есть два статических метода GenericDefault и GenericTypographic, которые возвращают указатель на предопределенный объект класса StringFormat:
    StringFormat* GenericDefault();
    StringFormat* GenericTypographic();
    Метод GenericDefault возвращает указатель на объект класса StringFormat, который представляет следующими параметрами форматирования:
    ▪ флагов форматирования нет;
    ▪ горизонтальное выравнивание по ближнему краю;
    ▪ вертикальное выравнивание по ближнему краю;
    ▪ позиции табуляции не установлены;
    ▪ префикс «горячих» клавиш отсутствует;
    ▪ текст обрезается по ближайшему символу.
    Метод GenericTypographic возвращает указатель на объект класса StringFormat, который обладает следующими параметрами форматирования:
    ▪ заданы флаги форматирования StringFormatFlagsLineLimit, StringFormatFlagsNoClip и StringFormatFlagsNoFitBlackBox;
    ▪ горизонтальное выравнивание по ближнему краю;
    ▪ вертикальное выравнивание по ближнему краю;
    ▪ позиции табуляции не установлены;
    ▪ префикс «горячих» клавиш отсутствует;
    ▪ текст не обрезается.
    Важно отметить, что не нужно удалять объект, указатель на который возвращают методы метода GenericDefault и GenericTypographic, после того, как необходимость в нем отпадет.
    В следующем примере демонстрируется использование предопределенных объектов класса StringFormat для вывода текста.
    Пример форматированного вывода текста

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  Font font(L«Arial», 14.f, FontStyleRegular);
    5.  // создаем сплошную кисть
    6.  SolidBrush blackBrush(Color::Black); // черный цвет
    7.  // выводим текст, который начинается в точке (10,50)
    8.  g.DrawString(L«Привет мир!», 1, &font, PointF(10.f, 50.f), StringFormat::GenericDefault(), &blackBrush);
    9.  // создаем объект класса StringFormat на основе предопределенного объекта
    10.  StringFormat sf(StringFormat::GenericTypographic());
    11.  // выводим текст, который начинается в точке (10,10)
    12.  g.DrawString(L«Привет мир!», 1, &font, PointF(10.f, 10.f), &sf, &blackBrush);
  10. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Вывод графических изображений

    Для отображения содержимого растрового или векторного изображения в классе Graphics есть метод DrawImage, который имеет огромное количество перегруженных вариантов. Наиболее употребительные варианты имеют следующие прототипы:
    DrawImage(Image *image, INT x, INT y);
    DrawImage(Image *image, REAL x, REAL y);
    DrawImage(Image *image, INT x, INT y, INT width, INT height);
    DrawImage(Image *image, REAL x, REAL y, REAL width, REAL height);
    DrawImage(Image *image, Point &point);
    DrawImage(Image *image, PointF &point);
    DrawImage(Image *image, Rect &rect);
    DrawImage(Image *image, RectF &rect);
    Первый параметр, image, указывает на объект класса Image или класса, производного от класса Image. Этот объект представляет изображение, содержимое которого необходимо отобразить.
    Параметр point, а также параметры x и y, определяют расположение выводимого изображения.
    Параметр rect, а также параметры x, y, width и height, определяют расположение и размер выводимого изображения.
    В следующем примере демонстрируется использование метода DrawImage класса Graphics для вывода изображения.
    Пример вывода изображения

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // загружаем изображение Sample.png
    5.  Image image(L«Sample.png»);
    6.  // вывод загруженного изображения
    7.  g.DrawImage(&image, 10, 10);

    Важно отметить, что чтение изображения из файла может происходить достаточно медленно. Поэтому разумнее всего было бы вынести загрузку выводимых изображений из функции отображения, а не так как это сделано в приведенном примере.

    Пропорциональное масштабирование изображения

    Как показано на рисунке в процессе вывода изображения может возникнуть искажение из-за того, что при масштабировании форматное соотношение прямоугольника, который определяет расположение и размер выводимого изображения, не совпадает с форматным соотношением этого изображения.

    Искажение изображения

    00.png

    Форматное соотношение – это отношение ширины и высоты, которое находится по следующей формуле:

    [math]ratio=\frac{\displaystyle width}{\displaystyle height}[/math](1.2)​

    где [math]ratio[/math] – форматное соотношение, а [math]width[/math] и [math]height[/math] – ширина и высота.
    Для того чтобы при масштабировании изображения не происходило его искажения необходимо найти для него такие ширину и высоту, для которых бы сохранялось их изначальное отношение и которые бы полностью влезали бы в заданный прямоугольник.
    Рассмотрим случай, когда форматное соотношение изображения больше чем форматное соотношение заданного прямоугольника. В этом случае ширина и высота изображения находятся по формуле:

    [math]Image.width=Rectangle.width[/math],
    [math]Image.height=\frac{\displaystyle 1}{\displaystyle ratio}\cdot Rectangle.width[/math] (1.3)​

    где [math]Image.width[/math] и [math]Image.height[/math] – новые ширина и высота изображения; [math]Rectangle.width[/math] – ширина прямоугольника; [math]ratio[/math] – форматное соотношение изображения.
    В другом случае, когда изображение имеет меньшее форматное соотношение, чем у заданного прямоугольника, новые ширина и высота изображения находятся по другой формуле:

    [math]Image.width=ratio\cdot Rectangle.heigth[/math],
    [math]Image.heigth=Rectangle.heigth[/math] (1.4)​

    где [math]Image.width[/math] и [math]Image.heigth[/math] – новые ширина и высота изображения; [math]Rectangle.heigth[/math] – высота прямоугольника; [math]ratio[/math] – форматное соотношение изображения.
    В листинге представлена функция, определяющей ширину и высоту изображения, для которых сохраняется их изначальное отношение, и которые будут полностью влезать в прямоугольник.
    Функция определяющая положение и размер изображения

    1.  MeasureImage(Image *image, RectF &layout, StringAlignment align, RectF *result)
    2.  if (NULL == image || layout.IsEmptyArea() || NULL == result)
    3.  // форматное соотношение изображения
    4.  float fRatio = (float)image->GetWidth() / (float)image->GetHeight();
    5.  if (fRatio > (layout.Width / layout.Height))
    6.  rect.Width = layout.Width;
    7.  rect.Height = layout.Width / fRatio;
    8.  rect.X = layout.GetLeft();
    9.  // выравнивание по вертикали
    10.  case StringAlignmentNear: // по ближнему краю
    11.  rect.Y = layout.GetTop();
    12.  case StringAlignmentCenter: // по центру
    13.  rect.Y = layout.Y + (layout.Heightrect.Height)/2.f;
    14.  case StringAlignmentFar: // по дальнему краю
    15.  rect.Y = layout.GetBottom() rect.Height;
    16.  { rect.Width = fRatio * layout.Height;
    17.  rect.Height = layout.Height;
    18.  rect.Y = layout.GetTop();
    19.  // выравнивание по горизонтали
    20.  case StringAlignmentNear: // по ближнему краю
    21.  rect.X = layout.GetLeft();
    22.  case StringAlignmentCenter: // по центру
    23.          rect.X = layout.X + (layout.Widthrect.Width)/2.f;
    24.  case StringAlignmentFar: // по дальнему краю
    25.        rect.X = layout.GetRight() rect.Width;
    26.  rect.GetBounds(result); // возвращаем результат

    Функция, приведенная в этом примере, определяет также положение изображения в задаваемом прямоугольнике в зависимости от параметров выравнивания, т.к. в результате пропорционального масштабирования может оставаться неиспользованное пространство.
    На рисунке представлены различные варианты выравнивания изображения для двух рассмотренных случаев соотношения изображения и прямоугольника.

    Контуры

    Контур (path) представляет собой последовательность графических примитивов (линий, прямоугольников, кривых, текста и т. п.), которые обрабатываются и отображаются как один объект. Контур можно разделить на отдельные фигуры, которые являются либо незамкнутыми, либо замкнутыми.
    В GDI+ создание контуров выполняется с помощью методов класса GraphicsPath, определенного в заголовочном файле gdipluspath.h.
    Варианты выравнивания изображения относительно границ прямоугольника
    Класс GraphicsPath имеет следующие конструкторы:
    GraphicsPath(FillMode fillMode = FillModeAlternate);
    GraphicsPath(Point *points, BYTE *types, INT count, FillMode fillMode = FillModeAlternate);
    GraphicsPath(PointF *points, BYTE *types, INT count, FillMode fillMode = FillModeAlternate);
    Первый конструктор создает объект класса GraphicsPath на основе режима заполнения, который задает параметр fillMode.
    Второй и третий конструкторы создают объект класса Graphics-Path на основе массива точек, на который указывает параметр points, а параметр count задает количество элементов в этом массиве. Пара-метр types указывает на массив типа INT, элементы которого определяют тип точек, указанных в массиве. Параметр fillMode задает режим заполнения.
    Тип точек определяется одним (или комбинацией) из значений перечисляемого типа PathPointType.
    Для построения контура в классе GraphicsPath есть множество методов схожих по названию с методами класса Graphics, предназначенных для рисования таких же фигур. В таблице перечислены схожие методы класса GraphicsPath и класса Graphics.
    Таблица Сопоставление методов классов Graphics и GraphicsPath

    Метод класса GraphicsPath Аналог в классе Graphics Описание
    AddArc DrawArc Добавляет в контур дугу
    AddBezier DrawBezier Добавляет в контур сплайн Безье
    AddBeziers DrawBeziers Добавляет в контур кривую, состоящую из сплайнов Безье
    AddClosedCurve DrawClosedCurve Добавляет в контур замкнутый кубический сплайн
    AddCurve DrawCurve Добавляет в контур кубический сплайн
    AddEllipse DrawEllipse Добавляет в контур эллипс
    AddLine DrawLine Добавляет в контур линию
    AddLines DrawLines Добавляет в контур ломаную линию
    AddPath DrawPath Добавляет в контур другой контур
    AddPie DrawPie Добавляет в контур сектор
    AddPolygon DrawPolygon Добавляет в контур полигон
    AddRectangle DrawRectangle Добавляет в контур прямоугольник
    AddRectangles DrawRectangles Добавляет в контур несколько прямоугольников
    AddString DrawString Добавляет в контур строку

    Каждый метод класса GraphicsPath, имеет несколько прототипов схожих с аналогичными методами класса Graphics (подробнее см. в документации Platform SDK).
    Следует отметить, что в классе GraphicsPath, как и в других классах GDI+, есть методы GetLastStatus и Clone. Метод Clone имеет следующий прототип:
    GraphicsPath* Clone();
    В случае успеха метод Clone возвращает указатель на объект класса GraphicsPath, который должен быть удален вызовом оператора delete после того как станет не нужен. В случае ошибки – NULL.

    Рисование контуров

    Для рисования контуров используется метод DrawPath класса Graphics, а для закрашивания контуров используется метод FillPath этого класса. Эти методы имеют следующие прототипы:
    DrawPath(Pen *pen, GraphicsPath *path);
    FillPath(Brush *brush, GraphicsPath *path);
    Параметр path указывает на объект класса GraphicsPath, который представляет отображаемый контур.
    В листинге представлен пример демонстрирующий рисование контура, изображенного на рисунке.
    Пример рисования контура

    1.  { // создаем объект класса Graphics для рисования
    2.  // выполняем очистку перед рисованием
    3.  g.Clear(Color::White); // белый цвет фона
    4.  // создаем перо черного цвета
    5.  Pen blackPen(Color::Black);
    6.  // создаем сплошную кисть
    7.  SolidBrush solidBrush(Color::Yellow); // желтый цвет
    8.  Rect rect(70, 70, 100, 100);
    9.  // создаем объект класса GraphicsPath для построения контура
    10.  // добавляем в контур прямоугольник
    11.  // добавляем в контур круг
    12.  // рисуем закрашенный контур
    13.  g.FillPath(&solidBrush, &path);
    14.  g.DrawPath(&blackPen, &path);

    Пример контура​

    Последнее редактирование: 9 янв 2025

  11. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Замкнутые контуры

    Для создания замкнутого контура в классе GraphicsPath есть методы StartFigure, CloseFigure и CloseAllFigures.
    Методы StartFigure, CloseFigure и CloseAllFigures имеют следующие прототипы:
    StartFigure();
    CloseFigure();
    CloseAllFigures();
    Метод StartFigure открывает новую фигуру в контуре, не замыкая при этом текущую фигуру. Все последующие примитивы, добавляемые к контуру, добавляются к этой новой фигуре.
    Метод CloseFigure замыкает текущую фигуру и открывает новую фигуру. Если текущая фигура содержит последовательность соединенных линий, метод CloseFigure замыкает ее путем соединения начальной и конечной точек этих линий.
    Метод CloseAllFigures замыкает все незамкнутые фигуры в контуре и открывает новую фигуру.
    В листинге приведен пример создания замкнутого контура прямоугольника с закругленными углами.

    Прямоугольник с закругленными краями​

    Функция, создающая замкнутый контур

    1.  GraphicsPath* CreateRoundRectangle(Rect &rect, int Radius)
    2.  { // создаем объект класса GraphicsPath для построения контура
    3.  // добавляем в контур линию
    4.  path.AddLine(rect.GetLeft()+Radius, rect.GetTop(), rect.GetRight()Radius, rect.GetTop());
    5.  // добавляем в контур дугу
    6.  path.AddArc(rect.GetRight()Radius, rect.GetTop(), Radius, Radius, 270.f, 90.f);
    7.  // добавляем в контур линию
    8.  path.AddLine(rect.GetRight(), rect.GetTop()+Radius, rect.GetRight(), rect.GetBottom()Radius);
    9.  // добавляем в контур дугу
    10.  path.AddArc(rect.GetRight()Radius, rect.GetBottom()Radius, Radius, Radius, 0.f, 90.f);
    11.  // добавляем в контур линию
    12.  path.AddLine(rect.GetRight()Radius, rect.GetBottom(), rect.GetLeft()+Radius, rect.GetBottom());
    13.  // добавляем в контур дугу
    14.  path.AddArc(rect.GetLeft(), rect.GetBottom() Radius, Radius, Radius, 90.f, 90.f);
    15.  // добавляем в контур линию
    16.  path.AddLine(rect.GetLeft(), rect.GetBottom()Radius, rect.GetLeft(), rect.GetTop()+Radius);
    17.  // добавляем в контур дугу
    18.  path.AddArc(rect.GetLeft(), rect.GetTop(), Radius, Radius, 180.f, 90.f);
    19.  // добавляем закрываем фигуру в контуре
    20.  return path.Clone(); // клонируем объект класса GraphicsPath
    21.  } // CreateRoundRectangle

    Функцию из приведенного примера можно использовать следующим образом:

    1.  Rect rect(30, 30, 200, 100);
    2.  GraphicsPath *path = CreateRoundRectangle(rect, 20);
    3.  { /* контур успешно создан */

    Когда объект класса GraphicsPath, на который указывает переменная path из приведенного примера, более станет не нужен, он должен быть удален с помощью оператора delete.

    Последнее редактирование: 9 янв 2025

  12. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Поддержка полупрозрачности

    В GDI+ можно создавать, как непрозрачные перья и кисти, так и полупрозрачные перья и кисти. При рисовании полупрозрачным пером или кистью выполняется альфа-смешивание, которое представляет собой смешение фонового цвета и цвета пера или кисти. Каждый из трех компонентов (красный, зеленый, синий) фонового цвета смешивается с соответствующим компонентом цвета пера или кисти, согласно следующей формуле:

    [math]Color=SrcColor\cdot\frac{\displaystyle alpha}{\displaystyle 255}+BlndColor\cdot\frac{\displaystyle 255−alpha}{\displaystyle 255}[/math] (1.5)​

    где [math]Color[/math]– отображаем цвет; [math]BlndColor[/math] – фоновый цвет; [math]SrcColor[/math] – цвет пера или кисти, а [math]alpha[/math] – альфа-фактор цвета пера или кисти.
    Для создания непрозрачного пера или кисти следует установить для цвета альфа-фактор равным 255. Чтобы создать полупрозрачное перо или кисть, нужно задать альфа-фактору любое значение из диапазона от 1 до 254.
    В листинге приведен пример альфа-смешивания при рисовании изображения, показанного на рисунке.

    Пример альфа-смешивания​

    Пример рисования полупрозрачными графическими объектами

    1.  { // создаем объект класса Graphics для рисования
    2.  g.SetSmoothingMode(SmoothingModeHighQuality);
    3.  // выполняем очистку перед рисованием
    4.  g.Clear(Color::White); // белый цвет фона
    5.  Rect rect(10, 20, 200, 100);
    6.  // создаем эллиптический контур
    7.  // создаем полупрозрачное перо
    8.  Pen pen1(Color(128, 0, 128, 0), 20.f);
    9.  // создаем непрозрачное перо
    10.  Pen pen2(Color(255, 0, 128, 0), 20.f);
    11.  // создаем штриховую кисть с полупрозрачным фоном
    12.  HatchBrush hatchBrush(HatchStyleCross, Color::Red, Color(100, 255, 0, 0));
    13.  // создаем непрозрачную кисть градиента контура
    14.  PathGradientBrush pthGrBrush(&path);
    15.  // задаем цвет центра контура
    16.  pthGrBrush.SetCenterColor(Color::Aqua);
    17.  // задаем цвет границы контура…
    18.  Color color = Color::Blue;
    19.  pthGrBrush.SetSurroundColors(&color, &n);
    20.  // рисуем непрозрачный контур
    21.  g.FillPath(&pthGrBrush, &path);
    22.  // рисуем полупрозрачный прямоугольник
    23.  g.FillRectangle(&hatchBrush, 30, 10, 50, 120);
    24.  // рисуем полупрозрачную линию
    25.  g.DrawLine(&pen1, 150, 10, 150, 130);
    26.  // рисуем непрозрачную линию
    27.  g.DrawLine(&pen2, 180, 10, 180, 130);

    Настройка графического вывода

    Класс Graphics содержит также методы, которые способны влиять на качество отображаемых объектов.

    Сглаживание линий и текста

    При отображении различных линий, кривых и текста могут появляться контурные неровности. Для устранения контурных неровностей применяется сглаживание (smoothing). Обычно отображение более качественных сглаженных линии, кривых и текста требует больших затрат вычислительных ресурсов, чем менее качественных.
    В классе Graphics есть метод SetSmoothingMode, который задает режим сглаживания линий. Этот метод имеет следующий прототип:
    SetSmoothingMode(SmoothingMode smoothingMode);
    Параметр smoothingMode задает режим сглаживания линий. Этот параметр может принимать одно из следующих значений перечисляемого типа SmoothingMode:
    На рисунке изображен сплайн в двух вариантах без применения и с применением сглаживания линий.
    По умолчанию сглаживание линий не применяется. Определить текущий режим сглаживания линий можно с помощью метода GetSmoothingMode класса Graphics:
    SmoothingMode GetSmoothingMode();
    Режим сглаживания линий никак не влияет на качество отображения текста. Чтобы задать режим сглаживания текста, используется метод SetTextRenderingHint класса Graphics. Этот метод имеет следующий прототип:
    SetTextRenderingHint(TextRenderingHint newMode);
    Параметр newMode задает режим сглаживания текста. Этот параметр может принимать одно из следующих значений перечисляемого типа TextRenderingHint:
    В таблице приведены различные варианты сглаживания текста.
    Определить текущий режим сглаживания текста можно с помощью метода GetTextRenderingHint класса Graphics. Прототип метода: TextRenderingHint GetTextRenderingHint();

    Последнее редактирование: 8 янв 2025

  13. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Качество растровых изображений

    При масштабировании растрового изображения происходит потеря качества этого изображения. В GDI+ реализованы различные алгоритмы интерполяции, позволяющие добиться улучшения качества масштабируемого изображения.
    В классе Graphics определен метод SetInterpolationMode, который позволяет указать, какой алгоритм интерполяции будет использоваться при выводе растровых изображений с изменением его размеров.
    Метод SetInterpolationMode имеет следующий прототип:
    SetInterpolationMode( InterpolationMode interpolationMode);
    Параметр interpolationMode задает режим интерполяции изображения. Этот параметр должен принимать одно из следующих значений перечисляемого типа InterpolationMode:

    Изображение для масштабирования​

    На рисунке представлены различные варианты интерполяции увеличенного в три раза изображения, показанного на рисунке.
    Определить текущий режим интерполяции изображения можно с помощью метода GetInterpolationMode класса Graphics. Этот метод имеет следующий формат:
    InterpolationMode GetInterpolationMode()

    Логические единицы

    Класс Graphics позволяет абстрагироваться от физических характеристик устройства, позволяя указать, в какой логической системе координат будет происходить графический вывод.
    Для установки логической системы координат в классе Graphics имеется метод SetPageUnit. Этот метод имеет следующий прототип:
    SetPageUnit(Unit unit);
    Параметр unit указывает логические единицы устройства отображения. Этот параметр должен принимать одно из следующих перечисляемого типа Unit:

    Unit hex
    UnitWorld 0 мировые (не физические) единицы
    UnitDisplay 1 дисплейные единицы (пиксели)
    UnitPixel 2 пиксели
    UnitPoint 3 1 единица равна 1/72 дюйма
    UnitInch 4 дюймы
    UnitDocument 5 1 единица равна 1/300 дюйма
    UnitMillimeter 6 миллиметры

    Определить, какие используются логические единицы можно с помощью метода GetPageUnit класса Graphics:
    Unit GetPageUnit();
    Кроме того, можно задать коэффициент масштабирования логических единиц. Для этого в классе Graphics существует метод SetPageScale. Этот метод имеет следующий прототип:
    SetPageScale(REAL scale);
    Параметр scale определяет коэффициент масштабирования.
    В следующем небольшом примере продемонстрированно, как задать в качестве логической единицы 1 см.

    1.  // выбираем миллиметры в качестве логических единиц
    2.  g.SetPageUnit(UnitMillimeter);
    3.  // устанавливаем масштабирование логических единиц

    Определить текущий коэффициент масштабирования логических единиц можно с помощью метода GetPageScale класса Graphics:
    REAL GetPageScale();

    Последнее редактирование: 9 янв 2025

  14. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Использование GDI+ в приложениях Win64

    Библиотека GDI+ полностью реализована в DLL-библиотеке GdiPlus.dll, для получения доступа к которой следует подключить к программе библиотеку импорта GdiPlus.lib и заголовочный файл gdiplus.h.
    Библиотека GDI+ прибывает в собственном пространстве имен Gdiplus. Чтобы открыть прямой доступ к функциям и классам, определенным внутри GDI+, необходимо использовать директиву:
    using namespace Gdiplus;

    Инициализация и завершение работы GDI+

    Перед использованием классов и функций GDI+ эту библиотеку инициализируют с помощью функции GdiplusStartup, которая должна быть первой из функций GDI+, вызываемых в программе. Функция GdiplusStartup имеет прототип:
    GdiplusStartup(ULONG_PTR *token, GdiplusStartupInput *input, GdiplusStartupOutput *output);
    Первый параметр, token, указывает на переменную типа ULONG_PTR, в которую сохраняется маркер, необходимый для завершения работы с GDI+.
    Второй параметр, input, указывает на структуру GdiplusStartupInput, поля которой управляют различными аспектами использования библиотеки GDI+.
    Третий параметр, output, указывает на структуру GdiplusStartupOutput. Это поле может быть установлено в NULL.
    После выполнения функция GdiplusStartup возвращает одно из значений перечисляемого типа Status, определенного в заголовочном файле GdiPlusTypes.h. В случае успешного выполнения эта функция возвращается значение Ok.
    Описание структуры GdiplusStartupInput:

    1. struct GdiplusStartupInput
    2. {  UINT32 GdiplusVersion; // версия
    3.     DebugEventProc DebugEventCallback; // функция отладки
    4.     BOOL SuppressBackgroundThread; // флаг, разрешающий // отложенную инициализацию
    5.     BOOL SuppressExternalCodecs; // флаг, разрешающий // использование внешних // кодеков изображений

    Первое поле, GdiplusVersion, задает версию GDI+. Это поле принимает значение 1, которое соответствует версии 1.0.
    Второе поле, DebugEventCallback, указывает на функцию, которая будет вызываться при возникновении ошибки в различных функциях GDI+. Поле может быть установлено в NULL.
    Третье поле, SuppressBackgroundThread, определяет, необходимо ли создавать фоновый поток (например, когда начинаются манипуляции с изображениями) для окончательной инициализации GDI+. При этом инициализируется только часть библиотеки GDI+ (такой механизм отложенной инициализации довольно распространен в библиотеках Microsoft). Если поле SuppressBackgroundThread принимает значение TRUE, то функция GdiplusStartup возвращает (в параметре output) указатель на специальные функции, которые должны быть вызваны в том же потоке, что и функция GdiplusStartup.
    Четвертое поле, SuppressExternalCodecs, определяет, необходимо ли использовать внешние кодеки изображений. Так как GDI+ версии 1.0 не поддерживает внешние кодеки изображений, поэтому значения этого поля игнорируются.
    Конструктор структуры GdiplusStartupInput по умолчанию выполняет инициализацию ее полей, достаточную для большинства программ. По умолчанию поле GdiplusVersion равно 1, поле DebugEventCallback = NULL, поля SuppressBackgroundThread и SuppressExternalCodecs равны FALSE.
    Функция, на которую указывает поле DebugEventCallback, может называться как угодно, но должна имеет следующую сигнатуру:

    1. void WINAPI DebugEventProc(DebugEventLevel level, CHAR *message);

    Первый параметр, level, определяет уровень сообщения отладки и может принимать одно из следующих значений:
    ▪ DebugEventLevelFatal – критическая ошибка;
    ▪ DebugEventLevelWarning – предупреждение.
    Второй параметр, message, указывает на строку, в которой содержится текст сообщения отладки.
    Структура GdiplusStartupOutput имеет следующее описание:

    1. struct GdiplusStartupOutput
    2. { NotificationHookProc NotificationHook;
    3.    NotificationUnhookProc NotificationUnhook;

    Поля этой структуры, NotificationHook и NotificationUnhook, указывают на функции, которые нужно вызвать, соответственно, до и после цикла обработки оконных сообщений в приложении Win64.
    Функция, на которую указывает поле NotificationHook, имеет следующую сигнатуру:
    WINAPI NotificationHookProc(ULONG_PTR *token);
    Параметр token указывает на переменную типа ULONG_PTR, в которую будет сохранен маркер, необходимый для вызова функции, на которую указывает поле NotificationUnhook.
    Функция, на которую указывает поле NotificationUnhook, имеет следующую сигнатуру:
    void WINAPI NotificationUnhookProc(ULONG_PTR token);
    Когда больше нет необходимости в использовании функций и классов GDI+, следует вызвать функцию GdiplusShutdown:
    void GdiplusShutdown(ULONG_PTR token);
    В качестве параметра необходимо передать маркер, который вернула функция GdiplusStartup через параметр token.
    Следующий пример демонстрирует фрагмент программного кода инициализации и завершения работы с GDI+.
    Пример инициализации и завершения работы с GDI+

    1.  GdiplusStartupInput gdiplusStartupInput;
    2.  GdiplusStartupOutput gdiplusStartupOutput;
    3.  // указываем функцию отладки
    4.  gdiplusStartupInput.DebugEventCallback = GdiplusDebugProc;
    5.  // разрешаем отложенную инициализацию
    6.  gdiplusStartupInput.SuppressBackgroundThread = TRUE;
    7.  Status stRet = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, &gdiplusStartupOutput);
    8.  gdiplusStartupOutput.NotificationHook(&token);
    9.  /* цикл обработки оконных сообщений */
    10.  gdiplusStartupOutput.NotificationUnhook(token);
    11.  GdiplusShutdown(gdiplusToken); // завершение работы GDI+

    В примере используется отложенная инициализация GDI+ при дальнейшей отладке программы используется функция обратного вызова GdiplusDebugProc, которая может быть такой:

    1.  void WINAPI GdiplusDebugProc(DebugEventLevel level, CHAR *message)
    2.  case DebugEventLevelFatal:
    3.  MessageBoxA(NULL, message, «Критическая ошибка», MB_OK | MB_ICONERROR | MB_TASKMODAL);
    4.  case DebugEventLevelWarning:
    5.  MessageBoxA(NULL, message, «Предупреждение», MB_OK | MB_ICONWARNING | MB_TASKMODAL);

    В большинстве программ инициализация GDI+ выполняется проще. Следующий пример демонстрирует фрагмент программного кода более простой инициализации и завершения работы GDI+:
    Пример простой инициализации и завершения работы с GDI+

    1.  GdiplusStartupInput gdiplusStartupInput;
    2.  Status stRet = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    3.  { /* цикл обработки оконных сообщений */
    4.  GdiplusShutdown(gdiplusToken); // завершение работы GDI+

    Последнее редактирование: 7 янв 2025

  15. Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.930

    Вместо эпилога

    Статья «Введение в GDI+» написана вчерне. Впереди перевод на masm64, добавление иллюстраций, удаление ошибок

    Последнее редактирование: 8 янв 2025


    alex_dz, E.D. и Research нравится это.

GDI+ is an enhanced version of the Windows Graphics Device Interface (GDI). GDI+ was introduced with Windows XP and later versions and provides more advanced graphics capabilities. It’s built upon the foundation of GDI, offering improved performance and a richer set of graphical functions for developers.

What is GDI+?

If you have ever asked, “What is GDI+?” it’s an API designed to simplify the creation and manipulation of graphical content. GDI+ offers improved 2D graphics rendering over GDI, and better support for gradient fills, alpha blending and anti-aliasing. This results in smoother and more visually appealing graphics. Additionally, GDI+ enhances text rendering by supporting advanced typography features like kerning, ligatures, and complex script processing.

GDI+ is particularly useful for applications that perform complex image-processing tasks. It supports image scaling, cropping, rotation, and format conversion, meaning you can easily manipulate images within your application without relying on external libraries. This means you can draw sophisticated paths and shapes and create complex designs and graphics.

Another advantage of GDI+ is its compatibility with existing GDI-based applications. While GDI+ offers more advanced features, it maintains backward compatibility. This gives it a smoother transition and integration with older systems and makes GDI+ a practical choice for modernizing legacy applications.

Components of GDI+

You should understand its key components to use GDI+ for graphics rendering effectively and provide a flexible and powerful graphical subsystem.

Graphics classes

GDI+ provides a set of graphics classes that form the core of its functionality. These classes handle various graphical tasks, such as drawing shapes, rendering text, and managing images. The Graphics class, for example, is central to GDI+ and provides methods for drawing lines, curves, shapes, and text. There are other classes such as the Pen class to draw lines a specific width and style and the Font class to define font type, size, and style attributes.

Drawing surfaces

Drawing surfaces in GDI+ refer to the areas where graphics are rendered. These surfaces can be anything from a window or a control to an off-screen bitmap. The Graphics class works with these surfaces to perform drawing operations.

Drawing surfaces lets you render graphics directly to the screen or create complex images in memory before displaying them. This flexibility allows for more efficient and effective graphics rendering in your applications.

Image handling

GDI+ excels in image handling, providing advanced capabilities for working with images. The Image and Bitmap classes are fundamental as they allow you to load, manipulate, and save images in various formats.

GDI+ supports operations such as scaling, rotating, cropping, and converting image formats which make it easier to manage and display images within your applications. Features like transparency and alpha blending are also supported and enable the creation of more visually appealing graphics.

How to use GDI+ for graphics rendering

Here are some steps to follow to use GDI+ to render graphics for your applications:

Step 1: Set up your development environment

  • Include the necessary headers and libraries.
  • In a C++ project, this typically means including the Gdiplus.h header and linking against the Gdiplus.lib library.

Step 2: Initialize GDI+

  • Create a GdiplusStartupInput structure.
  • Call the GdiplusStartup function to initialize GDI+.

Step 3: Create graphics objects

  • To draw on a window or control, create a Graphics object associated with the device context of the drawing surface.
  • This allows rendering operations directly on the specified surface.

Step 4: Draw shapes

  • Create a Pen object to define the color and style of the outline.
  • Use the DrawLine method of the Graphics class to draw a line on the surface.
  • Similarly, use the DrawRectangle and DrawEllipse methods to render rectangles and ellipses.

Step 5: Render text

  • Create a Font object that specifies the font family, size, and style.
  • Use the DrawString method of the Graphics class to draw text on the surface with the specified font and brush.

Is GDI+ still usable?

Despite the emergence of newer graphical frameworks, GDI+ remains a viable option for many developers. Microsoft continues to support it and it’s included in the Windows operating system. If you are wondering, “Is GDI+ still usable?” the answer is yes, particularly for certain types of applications and scenarios.

GDI+ is still in use because of its compatibility with older systems and applications. Many legacy applications were built using GDI+ and maintaining compatibility is important for businesses that rely on these applications. GDI+ allows you to update or enhance existing software without completely rewriting it.

Additionally, it is well-suited for applications that require detailed 2D graphics rendering, advanced text handling, and image processing.

It is important to remember that while GDI+ is still usable, it may not be the best choice for all new developments. Newer graphical interfaces like Direct2D and DirectWrite provide more modern features, better performance, and enhanced security, which might be a better choice for many of your projects.

Benefits of Using GDI+

Using GDI+ offers several benefits that make it a valuable tool for developers working on Windows applications. These benefits include:

  • Versatility in graphics rendering: GDI+ provides a versatile platform for rendering 2D graphics. It allows you to draw lines, shapes, text, and images with ease while advanced features let you create smooth and visually appealing graphics.
  • Simplified image processing: GDI+ supports various image formats and provides tools to scale, crop, and convert images, which simplifies the process of manipulating images within your application.
  • Integration with Windows applications: GDI+ integrates seamlessly with Windows applications and allows you to enhance graphical capabilities without significant code changes. Its compatibility with the Win32 API ensures that you can use GDI+ with other Windows technologies.

Practical applications of GDI+

GDI+ is widely used in various practical applications, showcasing its flexibility and capabilities in different domains. Here are some key areas where GDI+ proves to be particularly useful:

User interface design

GDI+ is an excellent choice for designing user interfaces. Its ability to render high-quality graphics and text makes it ideal for creating visually appealing and intuitive interfaces.

You can use GDI+ to draw custom controls, design intricate menus, and enhance the overall look and feel of your application. These advanced imaging capabilities let you integrate detailed images and icons, further enriching the user experience.

Game development

While not typically associated with high-end gaming, GDI+ can be effectively used in casual game development. Its straightforward API allows you to handle basic graphics rendering tasks such as drawing sprites, handling animations, and managing game states.

It’s also suitable for developing simple 2D games or prototypes, where ease of use and quick development are more important than utilizing the latest graphical technologies.

Data visualization

GDI+ excels in creating detailed and interactive data visualizations. Whether you need to generate charts, graphs, or custom visual representations of data, GDI+ provides the tools necessary to produce clear and informative graphics. Its capabilities in handling shapes, colors, and text allow you to create dynamic and responsive visualizations that help users interpret complex data sets.

In the right settings, GDI+ offers a rich feature set with advanced capabilities to produce clear and informative graphics that enhance the user experience and improve data interpretation. This makes it an invaluable tool for many applications including business intelligence, scientific research, and educational software.

Материал из РУВИКИ — свободной энциклопедии

У этого термина существуют и другие значения, см. GDI (значения).

GDI (Graphics Device Interface, Graphical Device Interface) — один из трёх основных компонентов или «подсистем», вместе с ядром и Windows API, составляющих пользовательский интерфейс (оконный менеджер GDI) Microsoft Windows.

GDI — это интерфейс Windows для представления графических объектов и передачи их на устройства отображения, такие, как мониторы и принтеры.

GDI отвечает за отрисовку линий и кривых, отображение шрифтов и обработку палитры. Он не отвечает за отрисовку окон, меню и т. п., эта задача закреплена за пользовательской подсистемой, располагающейся в user32.dll и основывающейся на GDI. GDI выполняет те же функции, что и QuickDraw в Mac OS.

Одно из преимуществ использования GDI вместо прямого доступа к оборудованию — это унификация работы с различными устройствами. Используя GDI, можно одними и теми же функциями рисовать на разных устройствах, таких, как экран или принтер, получая на них практически одинаковые изображения. Эта возможность лежит в центре многих WYSIWYG-приложений для Windows.

Простые игры, которые не требуют быстрой графики, могут использовать GDI. Однако GDI не обеспечивает качественной анимации, поскольку в нём нет возможности синхронизации с кадровым буфером. Также в GDI нет растеризации для отрисовки 3D-графики. Современные игры используют DirectX или OpenGL, что даёт программистам доступ к большему количеству аппаратных возможностей.

Для определения атрибутов текста и изображения, которые выводятся на экран или принтер, используется программный объект под названием «контекст устройства» (Device Context, DC). DC, как и большинство объектов GDI, инкапсулирует подробности реализации и данные в себе и к ним нельзя получить прямой доступ.

Для любого рисования нужен объект HDC (Handle DC). При выводе на принтер HDC получается вызовом CreateDC, и на нём вызываются специальные функции для перехода на новую страницу печатаемого документа. При выводе на экран также можно использовать CreateDC, но это приведёт к рисованию поверх всех окон вне их границ, потому обычно для рисования на экране используются вызовы GetDC и BeginPaint, принадлежащие уже не GDI, а USER, и возвращающие контекст, ссылающийся на регион отсечения окна.

Функциональность:

  • вывод одними и теми же вызовами на экран, принтер, «экран в памяти» (доступный приложению по указателю и созданный им bitmap в памяти, также возможно выделение bitmapов в памяти видеокарты — CreateCompatibleBitmap — и рисование на них, такие битовые карты не доступны по указателю, но дальнейшая перерисовка с них на физический экран происходит очень быстро без нагрузки процессора и шины, и особенно быстро в случае Remote Desktop).
  • вывод в метафайл — запоминание последовательности команд рисования в файле, который можно «проиграть» заново, векторный графический файл .wmf есть именно этот метафайл с небольшим дополнительным заголовком в начале.
  • вывод текста различными шрифтами, в том числе TrueType и OpenType, а также шрифтами, вшитыми в принтер (при изображении документа на экране используется ближайший похожий программно реализованный шрифт). Буквы всегда заливаются одним цветом («текущий цвет»), промежутки между ними либо остаются прозрачными, либо же заливаются другим цветом («текущий цвет фона»). Не поддерживается расположение букв по кривой.
  • богатый набор операций с битовыми картами (битмапами), включая масштабирование, автоматическое преобразование из типичных форматов в текущий формат экрана без усилий со стороны программиста (StretchDIBits), рисование на битмапах нескольких типичных форматов, находящихся в памяти, и огромное количество логических операций комбинирования цветов 2 битмапов — уже имеющегося на устройстве назначения и вновь рисуемого.
  • богатый набор операций векторной графики (примерно тот же, что в PostScript, но используется другой вид кривых). Проводимая линия имеет атрибуты — толщину, рисунок пунктира и цвет (собраны вместе в т. н. объекте PEN) и способ сглаживания углов многоугольников. Заливка может быть одноцветной, одной из штриховок на выбор или же битмапом 8 на 8 (эти атрибуты собраны в «объекте BRUSH»). В Windows NT также появились кривые Безье.
  • все цвета в вызовах — всегда в RGB, независимо от системы цветов текущего устройства. Исключение — отдельные пикселы внутри битмапов, которые могут быть и в виде, определённом устройством.
  • поддержка регионов отсечения и всех основных логических операций над ними. Координаты в них — 16-битные целые (что ограничивало размер экрана Windows, даже довольно поздних версий, до 32K пикселов).
  • поддержка матрицы поворотов/растяжений — World Transform, не поддерживается для регионов отсечения, только для векторной графики.

В Windows 9x и более ранних реализована в 16-битной GDI.DLL, которая, в свою очередь, подгружает выполненный в виде DLL драйвер видеокарты. Драйвер видеокарты первоначально и был обязан реализовать вообще всё рисование, в том числе рисование через битмапы в памяти в формате экрана. Позже появилась DIBENG.DLL, в которой было реализовано рисование на битмапах типичных форматов, драйвер был обязан пропускать в неё все вызовы, кроме тех, для которых он задействовал аппаратный ускоритель видеокарты.

Драйвер принтера подгружался таким же образом и имел тот же интерфейс «сверху», но «снизу» он вместо рисования в памяти/на аппаратуре генерировал последовательности команд принтера и отсылал их в объект Job. Эти команды, как правило, были либо двоичные и не читаемые человеком, либо PostScript.

В Windows NT GDI была полностью переписана с нуля заново, причём на C++ (по слухам, у Microsoft тогда не было компилятора этого языка и они использовали cfront). API для приложений не изменился (кроме добавления кривых Безье), для драйверов — обёртки на языке Си вокруг реализованных на C++ внутренностей (вроде BRUSHOBJ_pvGetRbrush).

Сама GDI была размещена сначала в WINSRV.DLL в процессе CSRSS.EXE, начиная с NT4 — в win32k.sys. Драйверы загружались туда же. DIBENG.DLL была переписана заново и перенесена туда же, как совокупность вызовов EngXxx — EngTextOut и другие. Логика взаимодействия драйвера-GDI-DIBENG осталась примерно та же.

GDI32.DLL в режиме пользователя реализована как набор специальных системных вызовов, ведущих в win32k.sys (до NT4 — как обёртки вокруг вызова CsrClientCallServer, посылавшего сообщение в CSRSS.EXE).

В Windows Vista появилась модель драйверов WDDM, в которой была отменена возможность использования аппаратуры двухмерной графики. При использовании WDDM все GDI-приложения (то есть все обычные системные части Windows UI — заголовки и рамки окон, рабочий стол, панель задач и другое) используют GDI-драйвер cdd.dll (Canonical Display Driver)[1], который рисует на некоторых битмапах в памяти, своих для каждого окна (содержимое окна стало запоминаться в памяти, до того Windows никогда так не делала и всегда перерисовывала окна заново, кроме неких специальных окон с флагом CS_SAVEBITS). Изображения из cdd.dll извлекаются процессом dwm.exe (Desktop Window Manager), который является Direct3D-приложением и отрисовывает «картинки окон» на физическом экране через Direct3D.

Сам же WDDM-драйвер поддерживает только DirectDraw и Direct3D и не имеет отношения ни к GDI, ни к win32k.sys, сопрягаясь с модулем dxgkrnl.sys в ядре.

Крайне сильно критикуется подсистема печати Windows, особенно в случае сравнения её с CUPS.

Причины: бинарный формат потока задания печати (в CUPS это PostScript) и реализация обработки этого потока в виде нескольких DLL внутри одного процесса SPOOLSV.EXE (CUPS вместо этого использует обычный конвейер из нескольких процессов вроде pstoraster | rastertoepson | parallel, который можно при желании запустить из обычного UNIX shell). Таким образом, CUPS поддерживает разработку фильтров заданий печати (например, для платных принтеров в отелях) даже на скриптовых языках вроде Perl.

Однако тут речь скорее о компонентах, лежащих ниже GDI.

Однако CUPS имеет серьёзные проблемы с поддержкой WinPrinterов вроде всех дешёвых лазерных принтеров Hewlett-Packard. Так как они не поддерживают распространённый формат PCL, для них надо ставить огромные, сложные в настройках и построении пакеты, такие, как HP OfficeJet (порт «hpoj» во FreeBSD). При этом CUPS прекрасно поддерживает струйные принтеры, дорогие модели лазерных принтеров Hewlett-Packard и принтеры PostScript.

Нижние уровни технологии X11, используемой в UNIX-подобных ОС, таких, как Linux.

При этом X11 беднее возможностями, чем GDI (например, есть проблемы с реализацией независимых от устройства цветов), и для получения полного аналога GDI необходимо добавить ещё ряд библиотек, таких, как SDL.

компонент Windows
Microsoft Windows GDI+
Тип компонента программное обеспечение и компонент Microsoft Windows[d]
Включён в Windows XP
Windows Server 2003
Windows Vista Starter
Заменил Microsoft Windows GDI
Был заменён Диспетчер окон рабочего стола

С выходом Windows XP появился потомок подсистемы, GDI+, основанной на C++[2]. Подсистема GDI+ доступна как «плоский» набор из 600 функций, реализованных в gdiplus.dll. Эти функции «обёрнуты» в 40 классов C++. Microsoft не планирует оказывать поддержку для кода, который обращается к плоскому набору напрямую, а не через классы и методы C++. .NET Framework предлагает набор альтернативных C++ обёрточных классов, входящих в пространство имён System.Drawing..

GDI+ является улучшенной средой для 2D-графики, в которую добавлены такие возможности, как сглаживание линий (antialiasing), использование координат с плавающей точкой, градиентная заливка, возможность работы изнутри с такими графическими форматами, как JPEG и PNG, куда лучшая реализация регионов отсечения с возможностью использовать в них координаты с плавающей точкой (а не 16-битные целые) и применения к ним World Transform, преобразования двумерных матриц и т. п. GDI+ использует ARGB-цвета. Эти возможности используются в пользовательском интерфейсе Windows XP, а их присутствие в базовом графическом слое облегчает использование систем векторной графики, таких, как Flash или SVG.

Динамические библиотеки GDI+ могут распространяться вместе с приложениями для использования в предыдущих версиях Windows.

GDI+ схож с подсистемой Quartz 2D у Apple и библиотеками с открытым кодом libart и Cairo.

GDI+ есть не более чем набор обёрток над обычной GDI. В Windows 7 появился новый API Direct2D, который есть примерно то же, но реализован «сверху донизу» вплоть до драйвера видеокарты (точнее, использует некие возможности Direct3D в этом драйвере), и может использовать аппаратное ускорение — то есть видеопроцессор трёхмерной графики для рисования некоторых двухмерных объектов (antialiasing и т. д.)

Уязвимости[править | править код]

14 сентября 2004 года была обнаружена уязвимость в GDI+ и других графических API, связанная с ошибкой в коде библиотеки JPEG. Эта ошибка позволяла выполнить произвольный код на любой системе Windows. Патч для исправления уязвимости был выпущен 12 октября 2004 года[3].

  1. Comparing Direct2D and GDI — DirectX Developer Blog — Site Home — MSDN Blogs. Дата обращения: 24 марта 2014. Архивировано из оригинала 8 апреля 2014 года.
  2. GDI+ Flat API (англ.) (недоступная ссылка — история). MSDN Library. Microsoft. Дата обращения: 31 октября 2009. Архивировано 3 марта 2012 года.
  3. MS04-028: Buffer overrun in JPEG processing (GDI+) could allow code execution (англ.). Microsoft Support. Microsoft. Дата обращения: 6 февраля 2005. Архивировано из оригинала 6 февраля 2005 года.
  • Microsoft’s GDI+ page
  • Bob Powell’s GDI+ FAQ list (недоступная ссылка)
  • MSDN article on GDI overview
  • Microsoft Security Bulletin MS04-028 (недоступная ссылка)
  • F-Secure: Critical vulnerability in MS Windows may escalate the virus threat

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Night shift на windows
  • Easy transfer windows 10 что это
  • Как поставить windows через rufus
  • Утилиты для диагностики сети windows
  • Настройка конфигурации системы windows 10