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


Автор: suxxor 18.1.2012, 00:23
Нужно нарисовать градиент как на картинке из .NET на C++ (WINAPI)

Оригинал:
Код

void CCtrlTraffic::OnPaint()
{
    CPaintDC dc(this); // device context for painting

    int iMax = GetMaxSpeed();
    CRect rect;
    GetClientRect(&rect);

    Graphics graphics(dc);

    //Draw background
    LinearGradientBrush lineargradientbrush(
        Point(rect.left, rect.top), 
        Point(rect.right, rect.bottom),
        Color(255, 65, 120, 165),
        Color(255, 0, 0, 0));

    Pen PenDownload(Color(150, 65, 95, 120));
    Pen PenUpload(Color(255, 135, 135, 135)); //230, 155, 55));
    Pen PenWhite(Color(150, 255, 255, 255)); 


    SolidBrush BrushDownload(Color(150, 65, 95, 120));
    SolidBrush BrushUpload(Color(150, 135, 135, 135)); // 185, 125, 55));
    SolidBrush BrushWhite(Color(150, 255, 255, 255));
    
    Gdiplus::Font fFont(L"Segoe UI", 10);

    PointF pointfDown(0.0f, rect.Height()/2 - 10);
    PointF pointfUp(rect.Width()/2 , rect.Height()/2 - 10);
    //DrawBack ground
    graphics.FillRectangle(&lineargradientbrush, rect.left, rect.top, rect.right, rect.bottom);

    graphics.DrawLine(&PenWhite, rect.left, rect.Height()/2 - 10, (int)rect.right, (int)rect.Height()/2 - 10 );
    graphics.DrawLine(&PenWhite, rect.left, rect.Height()/2 + 10, (int)rect.right, (int)rect.Height()/2 + 10 );
    graphics.DrawLine(&PenWhite, rect.Width()/2, rect.Height()/2 - 10, (int)rect.Width()/2, (int)rect.Height()/2 + 10 );

    CString sDonwload;
    sDonwload.Format(L"Down: %.2f kb/s", m_fDownloadSpeed);

    CString sUpload;
    sUpload.Format(L"Up: %.2f kb/s", m_fUploadSpeed );


    graphics.DrawString(sDonwload, sDonwload.GetLength(), &fFont, pointfDown, &BrushWhite);
    graphics.DrawString(sUpload, sUpload.GetLength(), &fFont, pointfUp, &BrushWhite);

    int iSize = m_vDownloads.size();
    int iNumberOfBars = rect.Width() / BAR_SIZE;

    std::vector<int>::iterator iItrDownload;
    std::vector<int>::iterator iItrUpload;

    iItrDownload = m_vDownloads.begin();
    iItrUpload = m_vUploads.begin(); 

    while(iItrUpload!= m_vUploads.end() && iItrDownload!= m_vDownloads.end())
    {

        int iHightUpload = (*iItrUpload)*(rect.Height()/2 - 10) / iMax;
        int iHightDownload = (*iItrDownload)*(rect.Height()/2 - 10) / iMax;
        if (iHightDownload > iHightUpload)
        {
            graphics.FillRectangle(&BrushDownload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2-11) - iHightDownload, BAR_SIZE, iHightDownload);        
            graphics.DrawRectangle(&PenDownload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2-11) - iHightDownload + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightDownload - BAR_FRAME_SIZE*2);

            graphics.FillRectangle(&BrushUpload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2+11) , BAR_SIZE, iHightUpload);
            graphics.DrawRectangle(&PenUpload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2+11) + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightUpload - BAR_FRAME_SIZE*2);            
        }
        else
        {
            graphics.FillRectangle(&BrushUpload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2+11), BAR_SIZE, iHightUpload);
            graphics.DrawRectangle(&PenUpload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2+11) + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightUpload - BAR_FRAME_SIZE*2);            

            graphics.FillRectangle(&BrushDownload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2-11) - iHightDownload, BAR_SIZE, iHightDownload);        
            graphics.DrawRectangle(&PenDownload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2-11) - iHightDownload + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightDownload - BAR_FRAME_SIZE*2);
        }

        iItrDownload++;
        iItrUpload++;
        iSize--;
    }
}


Результат:
user posted image

http://www.codeproject.com/KB/IP/3G_Modem_Internet_Dialer.aspx

Автор: GremlinProg 18.1.2012, 08:17
на C++ (WINAPI) для этого есть GradientFill
https://www.google.com/search?q=using+GradientFill

Автор: suxxor 18.1.2012, 11:15
GremlinProg, как с помощью этой ф-и сделать как на картинке?

Автор: GremlinProg 18.1.2012, 11:23
как сделать сам градиент на все окно, или разукрасить градиентом график?

Добавлено через 3 минуты и 36 секунд
если первое, то по ссылке есть примеры
если второе, то существует несколько способов, например: отрисовать сначала график в путь, выбрать его в HDC ( SelectClipPath ), после чего, отрисовать серый градиент на фоне синего градиента

Добавлено через 13 минут
по моему, тут даже серого градиента нет, это просто 2 кисти: upload и download,
тогда и путей не надо, просто отрисовка графика на фоне градиента

Автор: suxxor 18.1.2012, 11:48
Мне нужен только градиент:

Кажется оно:
Код

    //Draw background
    LinearGradientBrush lineargradientbrush(
        Point(rect.left, rect.top), 
        Point(rect.right, rect.bottom),
        Color(255, 65, 120, 165),
        Color(255, 0, 0, 0));


как это с GradientFill сделать?

Автор: GremlinProg 18.1.2012, 12:41
Цитата(suxxor @  18.1.2012,  13:48 Найти цитируемый пост)
Мне нужен только градиент

ну, по первой же ссылке как раз нужный код:
Код

type
  TRIVERTEX = packed record
    X, Y : DWORD;
    Red, Green, Blue, Alpha : Word;
  end;

function GradientFill(DC : hDC; pVertex : Pointer; dwNumVertex : DWORD;
  pMesh : Pointer; dwNumMesh, dwMode: DWORD) : DWord; stdcall;
  external 'msimg32.dll';

The following example shows a horizontal rectangle call.

procedure TForm1.Button1Click(Sender: TObject);
var
 vert : array[0..1] of TRIVERTEX;
 gRect   : GRADIENT_RECT;
begin
  vert [0] .x      := 0;
  vert [0] .y      := 0;
  vert [0] .Red    := $0000;
  vert [0] .Green  := $0000;
  vert [0] .Blue   := $0000;
  vert [0] .Alpha  := $0000;

  vert [1] .x      := 100;
  vert [1] .y      := 32;
  vert [1] .Red    := $0000;
  vert [1] .Green  := $0000;
  vert [1] .Blue   := $ff00;
  vert [1] .Alpha  := $0000;

  gRect.UpperLeft  := 0;
  gRect.LowerRight := 1;
  GradientFill(Form1.Canvas.Handle, @vert,2,@gRect,1,GRADIENT_FILL_RECT_H);
end;

vert [0] .x, vert [0] .y - координата левого-верхнего угла прямоугольника
vert [1] .x, vert [1] .y - координата правого-нижнего угла прямоугольника
стоит только отметить, что цветовые компоненты здесь 16-битные, т.е. чтобы перевести 8-битные к 16-битным, требуется масштабирование:
Код

clr_x16 = WORD( ::MulDiv( clr_x8, 0xffff, 0xff ) );

Автор: Dem_max 18.1.2012, 16:08
Ты же сам код функции привел, в чем проблема то ?

Автор: suxxor 18.1.2012, 17:50
Dem_max, там .NET <censure>

Короче написал, если что исправьте:
Код

TRIVERTEX vert[2] = {0};
GRADIENT_RECT gRect = {0};
vert [0].x      = rc.left;
vert [0].y      = rc.top;
vert [0].Red    = WORD(MulDiv(65, 0xffff, 0xff));
vert [0].Green  = WORD(MulDiv(120, 0xffff, 0xff));
vert [0].Blue   = WORD(MulDiv(165, 0xffff, 0xff));
vert [0].Alpha  = WORD(MulDiv(255, 0xffff, 0xff));
vert [1].x      = rc.right;
vert [1].y      = rc.bottom; 
vert [1].Red    = WORD(MulDiv(0, 0xffff, 0xff));
vert [1].Green  = WORD(MulDiv(0, 0xffff, 0xff));
vert [1].Blue   = WORD(MulDiv(0, 0xffff, 0xff));
vert [1].Alpha  = WORD(MulDiv(255, 0xffff, 0xff));
gRect.UpperLeft  = 0;
gRect.LowerRight = 1;

GradientFill(hDC, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_H);

Автор: Dem_max 19.1.2012, 04:00
Вот твоя функция на С++ для рисования того что тебе нада. Взял с первого поста.

Код

void CCtrlTraffic::OnPaint(HDC dc)
{

    int iMax = GetMaxSpeed();
    RECT rect;
    
   GetClientRect(&rect);

    Graphics graphics(dc);

    //Draw background
    LinearGradientBrush lineargradientbrush(
        Point(rect.left, rect.top), 
        Point(rect.right, rect.bottom),
        Color(255, 65, 120, 165),
        Color(255, 0, 0, 0));

    Pen PenDownload(Color(150, 65, 95, 120));
    Pen PenUpload(Color(255, 135, 135, 135)); //230, 155, 55));
    Pen PenWhite(Color(150, 255, 255, 255)); 


    SolidBrush BrushDownload(Color(150, 65, 95, 120));
    SolidBrush BrushUpload(Color(150, 135, 135, 135)); // 185, 125, 55));
    SolidBrush BrushWhite(Color(150, 255, 255, 255));
    
    Gdiplus::Font fFont(L"Segoe UI", 10);

    PointF pointfDown(0.0f, rect.Height()/2 - 10);
    PointF pointfUp(rect.Width()/2 , rect.Height()/2 - 10);
    //DrawBack ground
    graphics.FillRectangle(&lineargradientbrush, rect.left, rect.top, rect.right, rect.bottom);

    graphics.DrawLine(&PenWhite, rect.left, rect.Height()/2 - 10, (int)rect.right, (int)rect.Height()/2 - 10 );
    graphics.DrawLine(&PenWhite, rect.left, rect.Height()/2 + 10, (int)rect.right, (int)rect.Height()/2 + 10 );
    graphics.DrawLine(&PenWhite, rect.Width()/2, rect.Height()/2 - 10, (int)rect.Width()/2, (int)rect.Height()/2 + 10 );

    TCHAR  sDonwload[200], sUpload[200];
    wsprintf(sDonwload, _T("Up: %i kb/s"),  (int)m_fUploadSpeed);  
    wsprintf(sUpload, _T("Up: %i kb/s"),  (int)m_fUploadSpeed); 

    graphics.DrawString(sDonwload, sDonwload.GetLength(), &fFont, pointfDown, &BrushWhite);
    graphics.DrawString(sUpload, sUpload.GetLength(), &fFont, pointfUp, &BrushWhite);

    int iSize = m_vDownloads.size();
    int iNumberOfBars = rect.Width() / BAR_SIZE;

    std::vector<int>::iterator iItrDownload;
    std::vector<int>::iterator iItrUpload;

    iItrDownload = m_vDownloads.begin();
    iItrUpload = m_vUploads.begin(); 

    while(iItrUpload!= m_vUploads.end() && iItrDownload!= m_vDownloads.end())
    {

        int iHightUpload = (*iItrUpload)*(rect.Height()/2 - 10) / iMax;
        int iHightDownload = (*iItrDownload)*(rect.Height()/2 - 10) / iMax;
        if (iHightDownload > iHightUpload)
        {
            graphics.FillRectangle(&BrushDownload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2-11) - iHightDownload, BAR_SIZE, iHightDownload);        
            graphics.DrawRectangle(&PenDownload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2-11) - iHightDownload + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightDownload - BAR_FRAME_SIZE*2);

            graphics.FillRectangle(&BrushUpload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2+11) , BAR_SIZE, iHightUpload);
            graphics.DrawRectangle(&PenUpload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2+11) + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightUpload - BAR_FRAME_SIZE*2);            
        }
        else
        {
            graphics.FillRectangle(&BrushUpload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2+11), BAR_SIZE, iHightUpload);
            graphics.DrawRectangle(&PenUpload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2+11) + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightUpload - BAR_FRAME_SIZE*2);            

            graphics.FillRectangle(&BrushDownload, rect.right - BAR_SIZE *(iSize) , (rect.Height()/2-11) - iHightDownload, BAR_SIZE, iHightDownload);        
            graphics.DrawRectangle(&PenDownload, rect.right - BAR_SIZE*(iSize) + BAR_FRAME_SIZE, (rect.Height()/2-11) - iHightDownload + BAR_FRAME_SIZE * 2 , BAR_SIZE - BAR_FRAME_SIZE*2, iHightDownload - BAR_FRAME_SIZE*2);
        }

        iItrDownload++;
        iItrUpload++;
        iSize--;
    }
}

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