Помощь - Поиск - Пользователи - Календарь
Полная версия: Рисование сложных элементов
Форум «Всё о Паскале» > Delphi, Assembler и другие языки. > Delphi
Atreides
Добрый день! Прилетела задача по рисованию вот такой конструкции см.рисунок. Вопрос в чем это лучше сделать. Пробовал TChart, но не получается рисовать замкнутые линии, выдает ломанные. Через TCanvas, но можно ли делать штриховку и пунктирные линии?
IUnknown
Цитата
но можно ли делать штриховку и пунктирные линии?
Почему нет?

procedure TForm1.Button3Click(Sender: TObject);
var myBrush : HBRUSH;
begin
with Self.Canvas do
begin
Pen.Style := psDashDot;
MoveTo(0, 0);
LineTo(ClientWidth, ClientHeight);
Pen.Style := psDashDotDot;
MoveTo(ClientWidth, 0);
LineTo(0, ClientHeight);
end;

// Стандартные FillRect от Canvas глючат - инвертируют цвет, поэтому WinAPI
myBrush := CreateHatchBrush(HS_FDIAGONAL, RGB(0,0,0));
FillRect(Self.Canvas.Handle, Rect(10, 10, 50, 50), myBrush);
DeleteObject(myBrush);
end;

Atreides
А можно задать наклон диагональной заливки в другую сторону?
IUnknown
HS_BDIAGONAL ?
Гость
Есть необходимость нарисовать треугольник. LineTo и MoveTo yне дают закрасить, поэтому сделал через
Код
  Canvas.Polygon([Point(50, 50), Point(300, 300), Point(100, 200)]);
, а как его закрасить штриховкой?
IUnknown
Canvas.Polygon использует текущую кисть для заливки:

      Pen.Style := psClear;
Brush.Style := bsBDiagonal;
Brush.Color := clRed;
Polygon([Point(50, 50), Point(300, 300), Point(100, 200)]);
Atreides
Столкнулся с такой ситуацией - у меня переменные типа int, а для полигона нужны Point, как обойти ситуацию?
Код
  Canvas.Pen.Style := psClear;
  Canvas.Brush.Style := bsBDiagonal;
  Canvas.Brush.Color := clRed;
  Canvas.Polygon([Point(StartX + S_is, StartY - P_is),
  Point(StartX + S_is, StartY - P_is - (Delta_S div 2)),
  Point(StartX + S_p, StartY - P_is - Delta_S),
  Point(StartX + S_p, StartY - P_is)]);
Atreides
Начал рисовать сетку на осях, но почему на пересечение с осью, сетка прокрашивается белым, это причина кривизны моих руки или в чем?
шрихи по оси Х
Код
  x:=S_is;
  i := 0;
  while i < 7 do
  begin
    Canvas.Pen.Color := RGB(0, 0, 0);
    Canvas.Pen.Width := 1;
    Canvas.MoveTo(StartX + S_is+x, StartY - 10);
    Canvas.LineTo(StartX + S_is+x, StartY + 10);
    x := x + S_is;
      inc(i);
    end;


сама ось X
Код
  // ось Х
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX, StartY);
  Canvas.LineTo(StartX + S_k + S_k + S_k, StartY);
  // подпись оси X
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_k + S_k div 4, StartY - P_is div 2,
    'Остаток до конца срока');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_k + S_k div 4, StartY - P_is div 4,
    'службы по паспорту');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_k + S_k, StartY + P_is div 5, 'S');
Atreides
Кидаю, что у меня вышло, может кому сгодится. Местами не самые красивые методы программирования, но зато работает ))

Код
procedure Grapht;
const
  NUM_SHAPES = 200;
  StartX = 80; // начальные координаты по X
  StartY = 600; // начальные координаты по Y
  zoom = 4; // масштаб
  verty = 10;
  year = 12;
var
  i, ShapeLeft, ShapeTop: Integer;
  LF: TLogFont;
  FNew, FOld: HFont;
  myBrush: HBRUSH;
  x, z, year_x: Integer;
  p1, p2, p3, p4: Tpoint;

begin

  // пропорция умножение пиксилей на 5 у.е.
  P_is := P_is * zoom;
  S_is := S_is * zoom;
  S_p := S_p * zoom;
  Delta_S := Delta_S * zoom;
  S_k := S_k * zoom;
  P_k := P_k * zoom;
  DeltaDate := DeltaDate * zoom;

  Canvas.Pen.Style := psSolid;

  // фон
  Canvas.Brush.Color := RGB(255, 255, 255);
  ShapeLeft := 10; // (ClientWidth);   начальная координата слева
  ShapeTop := 120; // (ClientHeight);  начальная координата сверху
  Canvas.Rectangle(ShapeLeft, ShapeTop, ShapeLeft + 930, ShapeTop + 600);

  // деления по оси Х
  x := 0;
  i := 1;
  z := 12;
  year_x := year * zoom;
  while i < 8 do
  begin
    Canvas.Pen.Color := RGB(0, 0, 0);
    Canvas.Pen.Width := 1;
    Canvas.MoveTo(StartX + x, StartY - 10);
    Canvas.LineTo(StartX + x, StartY + 10);
    Canvas.Font.Size := 10; // от 10 до 16
    Canvas.TextOut(StartX + S_is + x, StartY + 12, IntToStr(z));
    x := x + year_x;
    inc(i);
    z := z + year;
  end;

  // деления по оси Y
  x := 0;
  i := 0;
  z := 0;
  year_x := year * zoom;
  while i < 8 do
  begin
    Canvas.Pen.Color := RGB(0, 0, 0);
    Canvas.Pen.Width := 1;
    Canvas.MoveTo(StartX - 10, StartY - x);
    Canvas.LineTo(StartX + 10, StartY - x);
    Canvas.Font.Size := 10; // от 10 до 16
    Canvas.TextOut(StartX - 20, StartY - x, IntToStr(z));
    x := x + year_x;
    inc(i);
    z := z + year;
  end;

  // ось Х
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX, StartY);
  Canvas.LineTo(StartX + S_k * 3, StartY);
  // подпись оси X
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_k + S_k div 4, StartY - P_is div 2,
    'Остаток до конца срока');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_k + S_k div 4, StartY - P_is div 4,
    'службы по паспорту');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_k + S_k, StartY + P_is div 5, 'S');

  // ИСК
  myBrush := CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 0));
  FillRect(self.Canvas.Handle, Rect(StartX, StartY, StartX + S_is,
    StartY - P_is), myBrush);
  DeleteObject(myBrush);
  // текст ИКС
  Canvas.Font.Size := 10; // от 10 до 16
  Canvas.TextOut(StartX + S_is div 4, StartY - P_is div 2, 'ИСК');

  // ось Y
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX, StartY);
  Canvas.LineTo(StartX, StartY - P_k - P_k - P_k div 4);
  // подпись оси Y
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_is div 4, StartY - P_k - P_k - P_is,
    'Остаток до конца полуторного срока службы от даты постройки');
  Canvas.Font.Size := 11; // от 10 до 16

  // P_is
  Canvas.Font.Size := 10; // от 10 до 16
  Canvas.TextOut(StartX - (S_p - S_is) - 10, StartY - P_is, 'Pис');

  // S_is
  Canvas.Font.Size := 10; // от 10 до 16
  Canvas.TextOut(StartX + S_is, StartY + P_is div 5 + 10, 'Sис');

  // S_p
  Canvas.Font.Size := 10; // от 10 до 16
  Canvas.TextOut(StartX + S_p, StartY + P_is div 5 + 10, 'Sп');

  // ДР на 110
  p1.x := StartX + S_is;
  p1.Y := StartY;
  p2.x := StartX + S_is;
  p2.Y := StartY - P_is - (Delta_S div 2);
  p3.x := StartX + S_p;
  p3.Y := StartY - P_is - Delta_S;
  p4.x := StartX + S_p;
  p4.Y := StartY;
  // Canvas.Pen.Style := psClear;
  Canvas.Brush.Style := bsFDiagonal;
  Canvas.Brush.Color := clRed;
  Canvas.Polygon([p1, p2, p3, p4]);

  // Линия S_k
  Canvas.Pen.Color := RGB(102, 204, 102);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX + S_k, StartY);
  Canvas.LineTo(StartX + S_k, StartY - P_k);
  Canvas.Font.Size := 10; // от 10 до 16
  Canvas.TextOut(StartX + S_k, StartY + P_is div 5 + 10, 'Sk');

  // Линия P_k
  Canvas.Pen.Color := RGB(102, 204, 102);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX, StartY - P_k);
  Canvas.LineTo(StartX + S_k, StartY - P_k);
  Canvas.Font.Size := 10; // от 10 до 16
  Canvas.TextOut(StartX - (S_p - S_is) - 10, StartY - P_k, 'Pk');

  // Линия ДР_нижняя
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX + S_p, StartY - P_is);
  Canvas.LineTo(StartX + S_k, StartY - P_is);

  // ДР на 110 бок_правый
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX + S_p, StartY);
  Canvas.LineTo(StartX + S_p, StartY - P_is - Delta_S);

  // ДР на 110 бок_левый
  Canvas.Pen.Style := psSolid;
  Canvas.Pen.Color := RGB(255, 255, 51);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX + S_is, StartY - P_is);
  Canvas.LineTo(StartX + S_is, StartY - P_is - (Delta_S div 2));

  // ДР на 110 крышка_диагональ
  Canvas.Pen.Style := psSolid;
  Canvas.Pen.Color := RGB(255, 255, 51);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX + S_is, StartY - P_is - (Delta_S div 2));
  Canvas.LineTo(StartX + S_p, StartY - P_is - Delta_S);

  // ДР на 110 крышка_низ
  Canvas.Pen.Color := RGB(255, 255, 51);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX + S_is, StartY - P_is);
  Canvas.LineTo(StartX + S_p, StartY - P_is);

  // ИСК крышка
  Canvas.Pen.Color := RGB(255, 102, 51);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX, StartY - P_is);
  Canvas.LineTo(StartX + S_is, StartY - P_is);

  // ИСК бок_правый
  Canvas.Pen.Color := RGB(102, 0, 153);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX + S_is, StartY);
  Canvas.LineTo(StartX + S_is, StartY - P_is);

  // ДРП бок_правый
  Canvas.Pen.Color := RGB(255, 255, 51);
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(StartX + S_p, StartY - P_is - Delta_S);
  Canvas.LineTo(StartX + S_p, StartY - P_is - Delta_S - P_k);

  // диагональная пунктиром
  Canvas.Pen.Width := 1;
  Canvas.Pen.Style := psDashDot;
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.MoveTo(StartX, StartY);
  Canvas.LineTo(StartX + S_k, StartY - P_k);

  // текст ДРП
  Canvas.Font.Size := 16; // от 10 до 16
  Canvas.TextOut(StartX + S_p div 5, StartY - P_is -
    ((P_k - P_is) - P_is div 2), 'ДРП');

  // текст ДР
  Canvas.Font.Size := 16; // от 10 до 16
  Canvas.TextOut(StartX + S_p + ((S_k - S_p) div 2),
    StartY - P_is - ((P_k - P_is) div 2), 'ДР');

  // текст ДР на 110 нижний под 90 градусов
  // Сохраняем хендл шрифта канвы
  FOld := Canvas.Font.Handle;
  // обнуляем поля структуры параметров нового шрифта
  FillChar(LF, SizeOf(LF), 0);
  // назначаем параметры нового шрифта
  LF.lfHeight := 14; // размер
  LF.lfWeight := fw_Normal;
  LF.lfEscapement := 900; // угол поворота в десятых долях градуса
  StrPCopy(LF.lfFaceName, 'Times New Roman');
  // создаем шрифт на основе заданных параметров
  FNew := CreateFontIndirect(LF);
  // назначаем его для канвы
  Canvas.Font.Handle := FNew;
  // выводим текст
  Canvas.TextOut(StartX + S_is + ((S_p - S_is) div 4), StartY - P_is div 4,
    'ДР на 110');
  // убиваем шрифт, если больше не нужен
  DeleteObject(FNew);
  // назначаем первоначальный шрифт для канвы
  Canvas.Font.Handle := FOld;

  // ДР и КР по 707 распоряжению
  Canvas.Font.Size := 16; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_p, StartY - P_is - ((P_k - P_is) div 2),
    'ДР и КР');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_p, StartY - P_is - ((P_k - P_is) div 2 - 30),
    'по 707 распоряжению');


  // текст делта S
   FOld := Canvas.Font.Handle;
   FillChar(LF, SizeOf(LF), 0);
  LF.lfHeight := 14; // размер
  LF.lfWeight := fw_Normal;
  LF.lfEscapement := 0; // угол поворота в десятых долях градуса
  StrPCopy(LF.lfFaceName, 'Symbol');
  FNew := CreateFontIndirect(LF);
  // назначаем его для канвы
  Canvas.Font.Handle := FNew;
  // выводим текст
  Canvas.TextOut(StartX + S_p + S_is div 5, StartY - P_is - delta_s div 2-10,
    #68);
  DeleteObject(FNew);
  Canvas.Font.Handle := FOld;
  FOld := Canvas.Font.Handle;
  FillChar(LF, SizeOf(LF), 0);
  LF.lfHeight := 14; // размер
  LF.lfWeight := fw_Normal;
  LF.lfEscapement := 0; // угол поворота в десятых долях градуса
  StrPCopy(LF.lfFaceName, 'Times New Roman');
  // создаем шрифт на основе заданных параметров
  FNew := CreateFontIndirect(LF);
  // назначаем его для канвы
  Canvas.Font.Handle := FNew;
  // выводим текст
  Canvas.TextOut(StartX + S_p + S_is div 5+10, StartY - P_is - delta_s div 2-10,
    'S');
  DeleteObject(FNew);
  Canvas.Font.Handle := FOld;



  // ДРП или КРП по 707
  Canvas.Font.Size := 16; // от 10 до 16
  Canvas.TextOut(StartX + S_p div 4, // ((S_p - StartX) div 2 - 15),
    StartY - P_k - 150, 'ДРП');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_p div 4, // ((S_p - StartX) div 2 - 10),
    StartY - P_k - 120, 'или');
  Canvas.Font.Size := 16; // от 10 до 16
  Canvas.TextOut(StartX + S_p div 4, // ((S_p - StartX) div 2 - 15),
    StartY - P_k - 90, 'КРП');
  Canvas.Font.Size := 11; // от 10 до 16
  Canvas.TextOut(StartX + S_p div 4, // ((S_p - StartX) div 2 - 17),
    StartY - P_k - 60, 'по 707');

  // подпись схемы
  Canvas.Font.Size := 14; // от 10 до 16
  Canvas.TextOut(StartX + S_k + S_p + S_k, StartY - P_k - P_k - P_is + P_is,
    'Схема определения вида ремонта');

  // пунктиры ДР на 110 верхний
  Canvas.Pen.Style := psDot;
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX + S_p, StartY - P_is - Delta_S);
  Canvas.LineTo(StartX - 10, StartY - P_is - Delta_S);

  // пунктиры ДР на 110 нижний
  Canvas.Pen.Style := psDot;
  Canvas.Pen.Color := RGB(0, 0, 0);
  Canvas.Pen.Width := 1;
  Canvas.MoveTo(StartX + S_is, StartY - P_is - (Delta_S div 2));
  Canvas.LineTo(StartX, StartY - P_is - (Delta_S div 2));

  // треугольник на оси X
  p1.x := StartX + S_k * 3;
  p1.Y := StartY + 5;
  p3.x := StartX + S_k * 3 + 10;
  p3.Y := StartY;
  p2.x := StartX + S_k * 3;
  p2.Y := StartY - 5;
  Canvas.Pen.Style := psSolid;
  Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := clBlack;
  Canvas.Polygon([p1, p2, p3]);

  // треугольник на оси Y
  p1.x := StartX - 5;
  p1.Y := StartY - P_k - P_k - P_k div 4;
  p3.x := StartX;
  p3.Y := StartY - P_k - P_k - P_k div 4 - 10;
  p2.x := StartX + 5;
  p2.Y := StartY - P_k - P_k - P_k div 4;
  Canvas.Pen.Style := psSolid;
  Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := clBlack;
  Canvas.Polygon([p1, p2, p3]);

end;
Atreides
Один вопрос остался неразрешенным мной. Как заставить рисовать канву при отображении формы. Вешал на событие онКриейт, пошаговом режимом вижу, что захожу в процедуру, но на экране ничего не наблюдаю.
Atreides
Вопрос с канвой устранил. Возник вопрос с печатью. Пробовал через TPrinter, но чет уж слишком мелко выдает, буквально в десяток пикселей умещается картинка. В сторону чего стоит посмотреть? Исходники прикрепил файлом.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.