powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Рисование полупрозрачных полигонов (Win32 API)
2 сообщений из 2, страница 1 из 1
Рисование полупрозрачных полигонов (Win32 API)
    #36934361
kaktambaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
Мне требуется нарисовать средствами Win32API лепестковую диаграмму (radar в англоязычных источниках). Серии этой диаграммы отображаются в виде полигонов (polygons) с непрозрачной заливкой. В отдельных случаях возникает ситуация, когда одна серия полностью затмевает другую. Одним из решений этой проблемы видится рисование полупрозрачных полигонов, чтобы серии, лежащие внизу и затмеваемые находящимися выше, были видны пользователю.
Уважаемые коллеги, посоветуйте, как правильно отобразить такие полигоны или как-то иначе решить описанную проблему.

С уважением, Канат Кактамбаев
...
Рейтинг: 0 / 0
Рисование полупрозрачных полигонов (Win32 API)
    #36938622
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 kaktambaev:

Если очень хочется рисовать полу-прозрачные многоугольники с помощью GDI, то можно так:
(обработки ошибок нет, чтобы понятнее)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
#include <assert.h>
#include <limits.h> // для INT_MIN, INT_MAX

void PaintTranslucentPolygon(HDC hDC, const POINT pVerts[], int NumVerts, COLORREF FillColor, int Opacity)
{
  const unsigned int TransparentColor = 0xFF00FF; // magenta (ядовито-розовый цвет)

  assert(NumVerts >=  3 );
  assert(FillColor != RGB( 255 ,  0 ,  255 )); // не magenta
  assert(( 0  <= Opacity) && (Opacity <=  255 ));

  // считаем границы многоугольника
  int MinX = INT_MAX;
  int MaxX = INT_MIN;
  int MinY = INT_MAX;
  int MaxY = INT_MIN;
  for (int i =  0 ; i < NumVerts; i++)
  {
    int x = pVerts[i].x;
    if (x < MinX) MinX = x;
    if (x > MaxX) MaxX = x;
    int y = pVerts[i].y;
    if (y < MinY) MinY = y;
    if (y > MaxY) MaxY = y;
  }
  // слегка раздвигаем границы (чтобы избежать нежелательного отсечения)
  MinX--;
  MaxX++;
  MinY--;
  MaxY++;

  // создаём временный буфер для вне-экранного рисования
  int BufWidth = MaxX - MinX +  1 ;
  int BufHeight = MaxY - MinY +  1 ;
  BITMAPINFO bi;
  bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bi.bmiHeader.biWidth = BufWidth;
  bi.bmiHeader.biHeight = BufHeight;
  bi.bmiHeader.biPlanes =  1 ;
  bi.bmiHeader.biBitCount =  32 ;
  bi.bmiHeader.biCompression = BI_RGB;
  bi.bmiHeader.biSizeImage =  0 ;
  bi.bmiHeader.biXPelsPerMeter =  0 ;
  bi.bmiHeader.biYPelsPerMeter =  0 ;
  bi.bmiHeader.biClrUsed =  0 ;
  bi.bmiHeader.biClrImportant =  0 ;
  void* pBufPixels;
  HBITMAP hBuf = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &pBufPixels, NULL,  0 );

  // заполняем буфер прозрачным цветом
  int NumPixels = BufHeight * BufWidth;
  unsigned int* pPix = static_cast<unsigned int*>(pBufPixels);
  for (int i =  0 ; i < NumPixels; i++)
  {
    *pPix++ = TransparentColor;
  }

  // рисуем многоугольник в буфер
  HDC hBufDC = CreateCompatibleDC(NULL);
  SelectObject(hBufDC, hBuf);
  SelectObject(hBufDC, GetStockObject(DC_BRUSH));
  SetDCBrushColor(hBufDC, FillColor);
  SelectObject(hBufDC, GetStockObject(NULL_PEN)); // контур не рисовать
  SetWindowOrgEx(hBufDC, MinX, MinY, NULL);
  Polygon(hBufDC, pVerts, NumVerts);
  SetWindowOrgEx(hBufDC,  0 ,  0 , NULL);

  // приводим содержимое буфера к формату с premultiplied alpha
  pPix = static_cast<unsigned int*>(pBufPixels);
  for (int i =  0 ; i < NumPixels; i++)
  {
    unsigned int c = *pPix;
    if (c == TransparentColor)
    {
      *pPix =  0 ;
    }
    else
    {
      c |= 0xFF000000; // сделать alpha = 255
      *pPix = c;
    }
    pPix++;
  }

  // рисуем содержимое буфера в указанный DC, со смешиванием (blending) цветов
  BLENDFUNCTION bf;
  bf.BlendOp = AC_SRC_OVER;
  bf.BlendFlags =  0 ;
  bf.SourceConstantAlpha = Opacity;
  bf.AlphaFormat = AC_SRC_ALPHA;
  AlphaBlend(hDC, MinX, MinY, BufWidth, BufHeight, hBufDC,  0 ,  0 , BufWidth, BufHeight, bf);

  // освобождаем временные GDI-объекты
  DeleteDC(hBufDC);
  DeleteObject(hBuf);
}
Пример использования:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
case WM_PAINT:
{
  PAINTSTRUCT PaintStruct;
  HDC hDC = BeginPaint(hwnd, &PaintStruct);

  // рисуем шашечки
  int CellSize =  8 ;
  int MinRow = PaintStruct.rcPaint.top / CellSize;
  int MaxRow = PaintStruct.rcPaint.bottom / CellSize;
  int MinCol = PaintStruct.rcPaint.left / CellSize;
  int MaxCol = PaintStruct.rcPaint.right / CellSize;
  HBRUSH hGrayBrush = static_cast<HBRUSH>(GetStockObject(LTGRAY_BRUSH));
  HBRUSH hWhiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
  for (int Row = MinRow; Row <= MaxRow; Row++)
  {
    for (int Col = MinCol; Col <= MaxCol; Col++)
    {
      RECT Cell;
      Cell.left = Col * CellSize;
      Cell.right = (Col +  1 ) * CellSize;
      Cell.top = Row * CellSize;
      Cell.bottom = (Row +  1 ) * CellSize;
      FillRect(hDC, &Cell, (Row & 0x1) == (Col & 0x1) ? hGrayBrush : hWhiteBrush);
    }
  }

  // рисуем прямоугольники
  for (int Rect =  1 ; Rect <=  10 ; Rect++)
  {
    double CenterX = Rect *  30 ;
    double CenterY =  50 ;
    double Width =  20 ;
    double Height =  80 ;
    double Rot =  20 ; // угол в градусах

    double hw =  0 . 5  * Width;
    double hh =  0 . 5  * Height;
    const double Pi =  3 . 1415926535897932384626433832795 ;
    double cr = cos((Pi /  180 ) * Rot);
    double sr = sin((Pi /  180 ) * Rot);
    POINT Verts[ 4 ];
    Verts[ 0 ].x = (int)(CenterX + cr * hw - sr * hh);
    Verts[ 0 ].y = (int)(CenterY + sr * hw + cr * hh);
    Verts[ 1 ].x = (int)(CenterX - cr * hw - sr * hh);
    Verts[ 1 ].y = (int)(CenterY - sr * hw + cr * hh);
    Verts[ 2 ].x = (int)(CenterX - cr * hw + sr * hh);
    Verts[ 2 ].y = (int)(CenterY - sr * hw - cr * hh);
    Verts[ 3 ].x = (int)(CenterX + cr * hw + sr * hh);
    Verts[ 3 ].y = (int)(CenterY + sr * hw - cr * hh);
    int Opacity = Rect *  255  /  10 ;
    PaintTranslucentPolygon(hDC, Verts,  4 , RGB( 0 ,  255 ,  0 ), Opacity);
  }

  EndPaint(hwnd, &PaintStruct);
  break;
}
Результат -- см. приложенный screenshot (снял в Windows 2000).

Но, GDI -- очень старый API, родом из 80-ых. Так что если хочется много рисовать с градиентами, anti-aliasing-ом и альфа-смешиванием, то я бы взял что-нибудь поновее: Cairo ( пример использования ) или GDI+ (не использовал).
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Рисование полупрозрачных полигонов (Win32 API)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]