Как использовать Graph и CRT в FreePascal for Windows

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Как использовать Graph и CRT в FreePascal for Windows

Сообщение D_I_M_A » 17.11.2007 13:55:24

Проблема такая: пишу несложную программу на ФриПаскале:

Код: Выделить всё
{Строит график ф-ции, заданной непосредсвенно в теле программы}
Program GraphBuilder;
Uses Graph,CRT;
Const
  myDriver=d8bit; {драйвер}
  myMod=m640x480;  {мод}
  GraphColor=Green;  {цвет графика ф-ции}
  GraphWidth=NormWidth; {толщина линии графика ф-ции}
  tabX=0.05;  {шаг изменения аргумента за одину интерацию цика}
  startArg=-100;  {с какого начального значения аргумента вычислять ф-цию}
  toArg=100;  {до какого конечного значения аргумента вычислять ф-цию}
{коды клавиатуры}
  In_x='6'; {растягивание графика по оси абсцисс}
  Out_x='4'; {сжимание графика по оси абсцисс}
  In_y='8'; {растягивание графика по оси ординат}
  Out_y='2'; {сжимание графика по оси ординат}
  In_all='+'; {пропорциональное увеличение графика}
  Out_all='-'; {пропорциональное уменьшение графика}
  Add_x='d'; {сдвиг по оси абсцисс влево}
  Subs_x='a'; {сдвиг по оси абсцисс вправо}
  Add_y='w'; {сдвиг по оси ординат вверх}
  Subs_y='s'; {сдвиг по оси ординат вниз}
  reset_to_starts=' '; {сбросить увеличения/сжимания}
  Esc=#27; {клавиша Escape, выход}
{операции с графиком}
  startDeltaX=1; startDeltaY=1; {начальные предустановки}
  DeltaMultiply=2; {во сколько раз увеличивать график за один приём}
  DeltaDivide=2; {во сколько раз уменьшать график за один приём}
  SdvigI=10; {на сколько пикселей сдвинется график за один приём}
  startSdvigX=0; {изначально график сдвинут по оси абсцисс на ...}
  startSdvigY=0; {изначально график сдвинут по оси ординат на ...}
{ошибки и критические ситуации}
  In_err=64; {нельзя увеличивать более чем в ...}
  Out_err=1/64; {нельзя уменьшать более чем в ...}
  SdvigX_control=250; {нельзя сдвигать график по оси X более чем на ... пикселей}
  SdvigY_control=250; {нельзя сдвигать график по оси Y более чем на ... пикселей}
Var
  Fx,Arg:Real; {знач. ф-ции и аргумент}
  x,y:Integer; {координаты для построения графика}
  offsetX:Integer; {смещение для координаты X для изображения на экране}
  grDriver,grMod:Integer;  {переменные драйвер и мод}
  KbdKey:Char;  {код клавиши с клавиатуры}
  deltaX,deltaY:Real; {для растягивания/сжимания по осям}
  sdvigX,sdvigY:Integer; {текущий сдвиг по оси абсцисс и ординат}
{===========================}
Procedure BuildOxOy; {строих оси координат}
Const
  DefColor=White; {цвет стрелок}
  LineWidth=ThickWidth; {толщина оси}
  StrelkaX=5; {параметры наконечника стрелки}
  StrelkaY=20;
Begin
  SetLineStyle(SolidLn,0,LineWidth);
  SetColor(DefColor);
  Line(Round(GetMaxX/2),0,Round(GetMaxX/2),GetMaxY);
  Line(0,Round(GetMaxY/2),GetMaxX,Round(GetMaxY/2));
  Line(Round(GetMaxX/2),0,Round(GetMaxX/2)-StrelkaX,StrelkaY);
  Line(Round(GetMaxX/2),0,Round(GetMaxX/2)+StrelkaX,StrelkaY);
  Line(GetMaxX,Round(GetMaxY/2),GetMaxX-StrelkaY,Round(GetMaxY/2)-StrelkaX);
  Line(GetMaxX,Round(GetMaxY/2),GetMaxX-StrelkaY,Round(GetMaxY/2)+StrelkaX);
End;
{===========================}
Procedure BG_Field; {строит клетки на фоне}
Const
  BackGr=Black; {фон}
  LineColor=LightGray; {цвет линий}
  LineStyle=DottedLn; {стиль линий - точечный}
  Bg_Cell=50; {сторона клетки}
Var
  i,j:Word;
Begin
  SetFillStyle(1,BackGr);
  Bar(0,0,GetMaxX,GetMaxY);
  SetColor(LineColor);
  SetLineStyle(LineStyle,0,NormWidth);
  for i:=0 to ((GetMaxX div 2) div Bg_Cell) do begin
    Line ( ( (GetMaxX div 2) - i*Bg_Cell ) ,0,
          ( GetMaxX div 2 ) - i*Bg_Cell, GetMaxY);
    Line ( ( (GetMaxX div 2) + i*Bg_Cell ) ,0,
          ( GetMaxX div 2 ) + i*Bg_Cell, GetMaxY);
    Line ( 0, ( ( GetMaxY div 2 ) - i*Bg_Cell ),
            GetMaxX, ( (GetMaxY div 2) - i*Bg_Cell ));
    Line ( 0, ( ( GetMaxY div 2 ) + i*Bg_Cell ),
            GetMaxX, ( (GetMaxY div 2) + i*Bg_Cell ));
  end;
End;
{===========================}
Procedure Err_Sound; {звук, свидетельствующий об ошибке}
Const
  Q=100; {частота}
  del=100; {время задержки}
Begin
  Sound(Q); Delay(del); NoSound;
End;
{===========================}
Begin
  grDriver:=myDriver; grMod:=myMod; {устанавливаем драйвер, мод}
  InitGraph(grDriver,grMod,''); {инициализация графики}
  if GraphResult<>grOk then Write('Graphis Error'); {гр. ошибка}
  deltaX:=startDeltaX; deltaY:=startDeltaY; {начальная установка растягивания графика}
  Repeat
    Bg_Field; {клетки на фоне}
    BuildOxOy; {оси}
    SetLineStyle(SolidLn,0,GraphWidth); {тип линий графика}
    SetColor(GraphColor); {цвет графика}
    arg:=startArg;
    offsetX:=Round(GetMaxX/2); {смещение графика для изображения на экране}
    MoveTo(Round(startArg+offsetX)+Round(SdvigI*sdvigX),
      (GetMaxY div 2)-Round(Sin(Arg)/Cos(Arg))-Round(SdvigI*sdvigY)); {устанавливаем в начало графика}
    Repeat
      arg:=arg+tabX; {увеличиваем аргумент}
      if arg=0 then continue;
      Fx:=Sin(Arg)/Cos(Arg); {расчёт ф-ции}
      x:=Round(arg*deltaX);
      y:=Round(Fx*deltaY); {координаты}
      LineTo(Round(x+offsetX)+SdvigI*sdvigX,
             Round(GetMaxY/2-y)-SdvigI*sdvigY); {построение по линиям}
    Until arg>=ToArg;
    KbdKey:=ReadKey; {читаем символ с клавиатуры}
    Case KbdKey of {обработка клавиатурных команд}
      In_x: deltaX:=deltaX*deltaMultiply;
      Out_x: deltaX:=deltaX/deltaDivide;
      In_y: deltaY:=deltaY*deltaMultiply;
      Out_y: deltaY:=deltaY/deltaDivide;
      In_all: begin deltaX:=deltaX*deltaMultiply; deltaY:=deltaY*deltaMultiply; end;
      Out_all: begin deltaX:=deltaX/deltaDivide; deltaY:=deltaY/deltaDivide; end;
      Add_x: Inc(SdvigX);
      Subs_x: Dec(SdvigX);
      Add_y: Inc(SdvigY);
      Subs_y: Dec(SdvigY);
      reset_to_starts: begin deltaX:=startDeltaX; deltaY:=startDeltaY; SdvigX:=startSdvigX; SdvigY:=startSdvigY; end;
    End;
    if deltaX>In_err then begin deltaX:=In_err; Err_Sound; end; {обработка ошибок}
    if deltaY>In_err then begin deltaY:=In_err; Err_Sound; end;
    if deltaX<Out_err then begin deltaX:=Out_err; Err_Sound; end;
    if deltaY<Out_err then begin deltaY:=Out_err; Err_Sound; end;
    if SdvigX>SdvigX_control then begin SdvigX:=SdvigX_control; Err_Sound; end;
    if SdvigX<-SdvigX_control then begin SdvigX:=-SdvigX_control; Err_Sound; end;
    if SdvigY>SdvigY_control then begin SdvigY:=SdvigY_control; Err_Sound; end;
    if SdvigY<-SdvigY_control then begin SdvigY:=-SdvigY_control; Err_Sound; end;
    ClearDevice;
  Until KbdKey=Esc; {Esc для выхода}
  CloseGraph;
End.


Программа изначально писалась на TurboPascal, потом я её перекомпилировал на FreePascal for DOS, вроде всё работало, потом решил ещё на FPC Win32 перекомпилировать, только вот в чём проблема:
При создании окна с графикой остаётся консольное окошко и ф-ция ReadKey из модуля CRT работает некорректно с этим графическим окном, точнее вообще не работает, т.е. для того, чтобы "послать" программе какое-то клавиатурное сообщение (к примеру, сдвинуть график по осям) приходится переключаться в консольное окно и жать клавиши туда, это очень не удобно. Пробовал использовать модуль Keyboard, но там тоже самое, Help! :(
D_I_M_A
новенький
 
Сообщения: 27
Зарегистрирован: 21.08.2007 12:42:20

Сообщение D_I_M_A » 17.11.2007 13:58:57

ОС - WinXPSP2
Free Pascal 2.2.0 i386 Win32
D_I_M_A
новенький
 
Сообщения: 27
Зарегистрирован: 21.08.2007 12:42:20

Сообщение halyavin » 17.11.2007 18:16:24

Без WinAPI/LCL этого сделать нельзя. Так что изучайте WinAPI и пишите нормальное windows-приложение. По адресу http://shade.msu.ru/~msu-se/demo.dpr я выложил приложение-шаблон, которое поможет вам начать программировать на winapi (на его основе я писал свой школьный проект в 11 классе не имея опыта windows-программирования до этого).
halyavin
новенький
 
Сообщения: 25
Зарегистрирован: 23.10.2007 16:35:55

Сообщение Максим » 17.11.2007 22:50:15

D_I_M_A
По-моему, для решения этой проблемы существует модуль Wincrt ?
Аватара пользователя
Максим
энтузиаст
 
Сообщения: 598
Зарегистрирован: 27.07.2007 01:51:43
Откуда: Москва

Сообщение nagash » 19.11.2007 09:16:35

может и существует)
но я не нашел ни строки документации по wincrt
nagash
новенький
 
Сообщения: 50
Зарегистрирован: 21.05.2007 08:27:05

Сообщение Dic » 20.11.2007 13:35:40

Я когда решал подобную проблему воспользовался
WINcrt и WINGraph.
Только в связке все это работает. Но немного там режимы не совместимы. и с русскими фонтами в графике напряг. Зато если посмотреть константы в WINGRAPHе То там есть и полноэкранный режим.
Тоесть прийдется немного попариться.
При этом программу пишем с {$APPTYPE GUI}
Библиотеки используем WINcrt и WINGRAPH.
И тогда почти полное счастье! Одно окно, в графическом режиме, в котором работает и мыша и клавиатура (WRITELN и READLN естественно не работают)
Dic
новенький
 
Сообщения: 28
Зарегистрирован: 28.08.2007 11:16:42
Откуда: Красноярск

Сообщение D_I_M_A » 21.11.2007 16:15:09

halyavin писал(а):Без WinAPI/LCL этого сделать нельзя. Так что изучайте WinAPI и пишите нормальное windows-приложение. По адресу http://shade.msu.ru/~msu-se/demo.dpr я выложил приложение-шаблон, которое поможет вам начать программировать на winapi (на его основе я писал свой школьный проект в 11 классе не имея опыта windows-программирования до этого).


Знаете что... Мне блин 14 лет и я в 9-ом классе, так что тут не надо...
D_I_M_A
новенький
 
Сообщения: 27
Зарегистрирован: 21.08.2007 12:42:20

Сообщение Vic3Dexe » 21.11.2007 16:49:11

D_I_M_A писал(а):Знаете что... Мне блин 14 лет и я в 9-ом классе, так что тут не надо...

Ну так может стоит учиться, а не "не надо"?

Чтоб не было страшным оффтопом, имхо, halyavin прав. Досовские модули graph/crt, да и вообще досовская структура приложения под вынь - это моветон...
Vic3Dexe
незнакомец
 
Сообщения: 4
Зарегистрирован: 20.11.2007 03:24:39
Откуда: Киев

Сообщение v-t-l » 21.11.2007 23:40:55

Ставь лазарус. У любого контрола есть свойство Canvas. Его методами и рисуй.
То есть, лепишь на форму панельку и кнопку. Щелкаешь два раза по кнопке и пишешь почти то же самое, что хотел. Что-то вроде, Panel1.Canvas.... (лазаруса под рукой нету, негде посмотреть точнее).
v-t-l
энтузиаст
 
Сообщения: 740
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Сообщение Dic » 22.11.2007 06:00:33

Ну не путайте человека! Lazarus отличная оболочка, но для начального обучения программированию она не подходит!
Да и экзамен по программированию в ВУЗах на традиционном паскале сдается. И интернет олимпиады в основном на нем родимом.
Так что все правильно, сначала надо нормально программировать научиться а уж потом использовать оболочки, где все что и так понятно автоматически формируется :-)
А иначе программистом хорошим очень трудно стать, половина останется на уровне шаманства. Тут просто проблема, что в основном FPS под UNIX "заточен" а с виндами немного напряг.
А через годик можно и на LAZARUS переходить да и то только тогда, когда все там понятно будет. Так что пожелаем от всей души человеку удачи, он сейчас в начале большого пути! Ну а чем можем нужно помочь :-)
Dic
новенький
 
Сообщения: 28
Зарегистрирован: 28.08.2007 11:16:42
Откуда: Красноярск

Сообщение D_I_M_A » 23.11.2007 12:22:28

Спасибо огромное вам, потом раздерусь со всем по порядку, пока надо с этим разобраться
D_I_M_A
новенький
 
Сообщения: 27
Зарегистрирован: 21.08.2007 12:42:20


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9

Рейтинг@Mail.ru