Почему путь RoundRect с градиентной заливкой не дает правильные углы на правой стороне? - PullRequest
0 голосов
/ 20 июня 2019

Я придумал процедуру создания прямоугольника с закругленными углами, заполненного градиентом (кнопка), однако, если я опущу код, который пишет контур, нижний правый угол выглядит квадратным, а верхний правый тоже не совсем правильным.,Это почему?

примечание: кнопка рисования владельца была создана 23x23.

//-------------------------------------------------------------------------
// Purpose: Draw a rounded rectangle for owner-draw button
//
// Input:   dis        - [i] owner-draw information structure
//          undermouse - [i] flag if button is under mouse
//
// Output:  na
//
// Notes:   This creates a standard grey type rounded rectangle for owner
//          drawn buttons.
//
//          This routine does not currently use undermouse to change 
//          gradient
//
void DrawRoundedButtonRectangle(const DRAWITEMSTRUCT& dis, BOOL undermouse)
{
  UNREFERENCED_PARAMETER(undermouse);

  // save DC before we modify it.
  SaveDC(dis.hDC);

  // create a path for the round rectangle (right/bottom is RECT format of +1)
  BeginPath(dis.hDC);
  RoundRect(dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom, 6, 6);
  EndPath(dis.hDC);

  // save DC before changing clipping region
  SaveDC(dis.hDC);
  // set clipping region to be the path
  SelectClipPath(dis.hDC, RGN_COPY);

  TRIVERTEX vertices[2];

  // setup the starting location and color (light grey)
  vertices[0].x = dis.rcItem.left;
  vertices[0].y = dis.rcItem.top;
  vertices[0].Red = MAKEWORDHL(211, 0);
  vertices[0].Green = MAKEWORDHL(211, 0);
  vertices[0].Blue = MAKEWORDHL(211, 0);
  vertices[0].Alpha = 0xffff;

  // setup the ending location and color (grey)
  vertices[1].x = dis.rcItem.right;   // should this be -1 ?
  vertices[1].y = dis.rcItem.bottom;  // should this be -1 ?
  vertices[1].Red = MAKEWORDHL(150, 0);
  vertices[1].Green = MAKEWORDHL(150, 0);
  vertices[1].Blue = MAKEWORDHL(150, 0);
  vertices[1].Alpha = 0xffff;

  // setup index to use for left to right
  GRADIENT_RECT r[1];
  r[0].UpperLeft = 0;
  r[0].LowerRight = 1;

  // fill the DC with a vertical gradient 
  GradientFill(dis.hDC, vertices, _countof(vertices), r, _countof(r), GRADIENT_FILL_RECT_V);

  // go back to original clipping area
  RestoreDC(dis.hDC, -1);
  // change the path to be the outline border
  if (WidenPath(dis.hDC)) {
    // set clipping region to be the path
    SelectClipPath(dis.hDC, RGN_COPY);
    // create a gradient on the outline
    GradientFill(dis.hDC, vertices, _countof(vertices), r, _countof(r), GRADIENT_FILL_RECT_V);
  }
  // put back the DC as we received it
  RestoreDC(dis.hDC, -1);
}

Красный цвет на фотографиях показывает фон.

Good Button

Bad Button

Плохая кнопка генерируется при удалении секции WidenPath.

1 Ответ

0 голосов
/ 20 июня 2019

Согласно вашему описанию, я думаю, вы можете говорить об этой ситуации.

    BeginPath(dis.hDC);
//  RoundRect(dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, dis.rcItem.bottom, 6, 6);
    EndPath(dis.hDC);

1

Позвольте мне сначала проанализировать причину, по которой я получил эту форму.

Когда вы перерисовываете кнопку, если длина и ширина перерисованной кнопки меньше, чем у самой кнопки, будет происходить только часть перерисовки.

case WM_CREATE:
{
    //Button width:230  Button height:230 
    button = CreateRoundRectButton(hWnd, 500, 200, 230, 230, 30, 30, BTN_ID);
    return 0;
}
break;
case WM_DRAWITEM:
{

    DRAWITEMSTRUCT dis;
    dis.CtlType = ODT_BUTTON;
    dis.CtlID = BTN_ID;
    dis.hDC = GetDC(button);
    dis.rcItem.left = 0;
    dis.rcItem.top = 0;
    dis.rcItem.right = 200;  //Width of redrawing
    dis.rcItem.bottom = 200; //Height of redrawing
    DrawRoundedButtonRectangle(dis, TRUE);
}

Чтобы увидеть эффект более четко, я увеличу ширину и высоту.

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

// fill the DC with a vertical gradient 
    GradientFill(dis.hDC, vertices, _countof(vertices), r, _countof(r), GRADIENT_FILL_RECT_V);

Если я изменю координаты XY перерисовки.

2

На самом деле, когда вы отключаете RoundRect, единственное, что работает, это GradientFill.

Обновлен:

Площадь перерисовки основана на rcItem. Когда вы рисуете путь, учитывается только внутренняя область, а контур - нет, поэтому WidenPath затем идет по контуру, и это дает истинную перенаправленную область rect.

...