Программирование на Паскале. Выпуск 12


Работа с мышью. 4

Извините, уважаемые подписчики, в последней (второй) программе предыдущего выпуска 11 (Мышь.3) я по невнимательности, программе допущено несколько ошибок. Из-за этого она работать не может. Помещу исправленный файл и на сайте 16 сентября в 17:00.

Сейчас опишу, что было плохого

В том варианте программы есть (были) три погрешности:
  1. Процедура - обработчик прерывания мыши особая, она не должна быть описана как прерывание (на это указывала бы добавка interrupt в заголовке процедуры). Это должна быть "обычная" процедура с добавлением в заголовке FAR, чтобы компилятор Паскаля сформировал полный адрес
  2. В старой версии я "опрашивал" поля переменной r типа Registers, а это не то же самое, что регистры процессора. Тут пришлось переходить на ассемблер. Только там есть доступ к регистрам процессора. На самом деле это не очень сложно. Посмотрите комментарии. Я сделал их поподробнее.
  3. В принципе, я все равно планировал склонять Вас, уважаемые подписчики, к использованию ассемблера, но чуть позже
  4. Далее, в подпрограмме ChangeView не было завершено описание типизированной константы
  5. И последнее, не была вызвана функция отображения указателя мыши на экране   r.ax:=1; intr($33, r);
  6. И самое последнее, обращаю внимание что на сайте www.yourpascal.com создан новый раздел "Скорая помощь". Пишите - поможем.

Текст исправленной программы внизу. Выделены изменения:
program mouse_02c;
uses DOS, CRT;

procedure FillScreen;
var f: File of char; c: Char;
begin
  Assign(f, 'mou_02c.pas'); {$I-} Reset(f); {$I+}
  if IOResult <> 0 then Exit;
  ClrScr;
  While NOT EOF(f) and (WhereY < 25) do begin
    Read(f, c); Write(c)
  end;
  Close(f);
end;

var
  r: Registers;
  v: Integer;
  L_Pressed, R_Pressed: Boolean;
  Flag: Boolean;

procedure MouInt; far;
{Исправили INTERRUPT на FAR}
begin
  if Flag then Exit;
  Flag:=True;
  L_Pressed:=False;
  R_Pressed:=False;
  {Присвоили начальные, а теперь хотим - не хотим, а надо
   переходить на ассемблер. Но это не сложно}
  asm
  {Ассемблерная вставка начинается с ключевого слова ASM
   и заканчивается "обычным" END}
    TEST bx, 1
  {Проверяем (тестируем = TEST) первый бит регистра BX.
   В ассемблере нет команд перехода по условию.
   Команда TEST просто устанавливает флаг нуля у процессора}
    JZ @1
  {JZ это сокращение от Jump if Zerou. 
   Это означает "Переход на метку, если установлен флаг нуля"
   Вот и пишем, если "первый бит = 0, то переходм на метку @1"}
    MOV L_Pressed, 1
  {Сюда попадаем, если "не ноль".
   Записываем (перемещаем = MOVE) в переменную L_Pressed единицу.
   Паскаль поймет это как значение "ИСТИНА" = TRUE}    
   @1:
  {Теперь аналогично обрабатываем второй бит регистра BX процессора}
    TEST bx, 2
    JZ @2
    MOV R_Pressed, 1
   @2:
  end;
  {Вот и закончился код на языке ассемблера}
end;

function ChangeView(ViewNo: Integer): Integer;
const
   Current: Integer = -1;  
   {По недосмотру в опубликованном варианте не было
        присвоения начального значения}
begin
 ChangeView:=Current;
 if ViewNo = Current then Exit;
 r.ax:=$0a;
 case ViewNo of
  1: with r do begin bx:=0; cx:=$00ff; dx:=$4e00 end;
  2: with r do begin bx:=0; cx:=$0;    dh:=$1f; dl:=ord('+') end;
  3: with r do begin bx:=1; cx:=7; dx:=8 end;
 else Exit;
 end;
 intr($33, r);
end;

BEGIN
  r.ax:=0;
  intr($33, r);
  if r.ax <> $FFFF then
   begin
     WriteLn('Мышь не обнаружена'); Halt(1)
   end;
  FillScreen;
  r.ax:=1; intr($33, r); {Мышь нужно показать}

  {Установка обработчика}
  r.ax:=$0c;
  r.cx:=2 + 4 + 8;
  {Список событий:
    - нажата и отпущена левая кнопка;
    - нажата правая}
  r.es:=Seg(MouInt);
  r.dx:=Ofs(MouInt);
  intr($33, r);

  Write('Мышь обнаружена с ',r.bx,' кнопками');
  v:=1;
  repeat
    if Flag then
    begin
      Flag:=False;
      if L_Pressed then
      case v of
        1: v:=2;
        2: v:=3;
        ELSE v:=1 end; {Этого конца "end" тоже не хватало}
      ChangeView(v)
    end;
  until R_Pressed;

 {Удаление обработчика. Так положено}
  r.ax:=$0c;
  r.cx:=0;
  r.es:=Seg(MouInt);
  r.dx:=Ofs(MouInt);
  intr($33, r);
END.

Свои вопросы и предложения присылайте Борису

Мы приглашаем Вас и Ваших друзей к сотрудничеству. Напишите, какая проблема Вас лично интересует - и мы постараемся помочь Вам. Поделитесь со всеми, если Вам удастся найти красивое решение. Присылайте свои программы, и если они хороши, то опубликуем их с обязательным указанием Вашего авторства.

По всем вопросам можно писать либо на наш форум www.yourpascal.com. Здесь создан новый раздел "Скорая помощь" для решения Ваших проблем или в Гостевую книгу нашего сайта на www.turbopascal.tk, либо прямо мне, автору этого выпуска, © Сурину Борису: surin_bp@mail.ru, ICQ: 320096696.

Постараюсь ответить на все вопросы и учесть все разумные предложения

Рассылка поддерживается сайтом www.turbopascal.tk. При перепечатке ссылка на сайт обязательна

Hosted by uCoz