Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > GDI+ Нарисовать тень по пути


Автор: artsb 15.12.2011, 18:28
Всем привет!

Нарисовал скруглённый прямоугольник и тень вокруг него. Но, что-то мне не нравится эта тень smile
user posted image
Во-первых, какой-то косяк слева вверху: нет куска тени.
Во-вторых, она не равномерная: слева - бледная; сверху - слишком тёмная (как-будто два раза нарисована); справа и снизу - то что нужно.

Делаю так:
Код

       Gdiplus::Graphics gGraphics(this->Canvas->Handle);
       Gdiplus::GraphicsPath gpPath, gpPath2;
       Gdiplus::Color clrBlack(0, 0, 0),
                   clrInnerGlow(90, 255, 255, 255),
                   clrBackground(127, 40, 40, 40);
       Gdiplus::Pen pnPen(clrBlack , 1);
       Gdiplus::SolidBrush brshBackground(clrBackground);
     
       Gdiplus::Color clrColors[] = {
          Gdiplus::Color(0,   0, 0, 0),
          Gdiplus::Color(255, 0, 0, 0),
          Gdiplus::Color(255, 0, 0, 0)};
     
       float fPos[] = {0.0f, 0.1f, 1.0f};
     
       float X = 50.f, Y = 30.f;
       float radius = 9.5f, height = 200.f, width = 300.f;
       float _X = X - 8.f, _Y = Y - 8.f;
       float _radius = radius + 1.f, _height = height + 16.f, _width = width + 16.f;
     
       gpPath2.AddLine(_X + _radius, _Y, _X + _width - (_radius * 2.f), _Y);
       gpPath2.AddArc(_X + _width - (_radius * 2.f), _Y, _radius * 2.f, _radius * 2.f, 270.f, 90.f);
       gpPath2.AddLine(_X + _width, _Y + _radius, _X + _width, _Y + _height - (_radius * 2.f));
       gpPath2.AddArc(_X + _width - (_radius * 2.f), _Y + _height - (_radius * 2.f), _radius * 2.f, _radius * 2.f, 0.f, 90.f);
       gpPath2.AddLine(_X + _width - (_radius * 2.f), _Y + _height, _X + _radius, _Y + _height);
       gpPath2.AddArc(_X, _Y + _height - (_radius * 2.f), _radius * 2.f, _radius * 2.f, 90.f, 90.f);
       gpPath2.AddLine(_X, _Y + _height - (_radius * 2.f), _X, _Y + _radius);
       gpPath2.AddArc(_X, _Y, _radius * 2.f, _radius * 2.f, 180.f, 90.f);
       gpPath2.CloseFigure();
     
       gpPath.AddLine(X + radius, Y, X + width - (radius * 2.f), Y);
       gpPath.AddArc(X + width - (radius * 2.f), Y, radius * 2.f, radius * 2.f, 270.f, 90.f);
       gpPath.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2.f));
       gpPath.AddArc(X + width - (radius * 2.f), Y + height - (radius * 2.f), radius * 2.f, radius * 2.f, 0.f, 90.f);
       gpPath.AddLine(X + width - (radius * 2.f), Y + height, X + radius, Y + height);
       gpPath.AddArc(X, Y + height - (radius * 2.f), radius * 2.f, radius * 2.f, 90.f, 90.f);
       gpPath.AddLine(X, Y + height - (radius * 2.f), X, Y + radius);
       gpPath.AddArc(X, Y, radius * 2.f, radius * 2.f, 180.f, 90.f);
       gpPath.CloseFigure();
     
       gpPath2.AddPath(&gpPath, TRUE);
     
    // gGraphics.DrawPath(&pnPen, &gpPath2);
     
       gGraphics.FillPath(&brshBackground, &gpPath);
       gGraphics.DrawPath(&pnPen, &gpPath);
     
       Gdiplus::PathGradientBrush pgbGradientBrush(&gpPath2);
       pgbGradientBrush.SetWrapMode(Gdiplus::WrapModeClamp);
       pgbGradientBrush.SetInterpolationColors(clrColors, fPos, 3);
     
       gGraphics.FillPath(&pgbGradientBrush, &gpPath2);
     
       gpPath.Reset();
     
       X++;
       Y++;
       radius -= 1.5f;
       height -= 2.f;
       width -= 2.f;
     
       gpPath.AddLine(X + radius, Y, X + width - (radius * 2.f), Y);
       gpPath.AddArc(X + width - (radius * 2.f), Y, radius * 2.f, radius * 2.f, 270.f, 90.f);
       gpPath.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2.f));
       gpPath.AddArc(X + width - (radius * 2.f), Y + height - (radius * 2.f), radius * 2.f, radius * 2.f, 0.f, 90.f);
       gpPath.AddLine(X + width - (radius * 2.f), Y + height, X + radius, Y + height);
       gpPath.AddArc(X, Y + height - (radius * 2.f), radius * 2.f, radius * 2.f, 90.f, 90.f);
       gpPath.AddLine(X, Y + height - (radius * 2.f), X, Y + radius);
       gpPath.AddArc(X, Y, radius * 2.f, radius * 2.f, 180.f, 90.f);
       gpPath.CloseFigure();
     
       pnPen.SetColor(clrInnerGlow);
       gGraphics.DrawPath(&pnPen, &gpPath);

ИМХО, что-то не чисто с объединением путей. До этого ещё хуже всё отрисовывалось. Хотя если раскомментировать закомментированную строку, то линии рисуются правильно. А вот с заливкой этих путей кистью, что-то не так.

ЗЫ Может, кстати, подскажете другой способ нарисовать такую тень.
ЗЗЫ Ещё я не совсем разобрался с Interpolation Colors у PathGradientBrush (код тупо содрал из MSDN'а smile). Объясните если не сложно.

Спасибо!

Автор: Dem_max 16.12.2011, 11:33
нормальная тень

Автор: artsb 18.12.2011, 15:34
Цитата(Dem_max @  16.12.2011,  11:33 Найти цитируемый пост)
нормальная тень 

"нормально" - меня не устраивает smile
а вот так действительно лучше:
user posted image

Автор: Dem_max 19.12.2011, 08:34
выложи код, что то у тебя с радиусом тени не то, радиус тени явно не пропорционален радиусу кона.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)