e-mail    Debatní kniha    Mapa stránek    Hlavní  
 perličky 
 

Print Screen verze 3.0

Zbyšek Hlinka

Program na stažení obsahu textové obrazovky do textového souboru
V Programátorských perličkách Bajtu 5/91 vyšla druhá verze mého programu na ukládání textových obrazovek do souboru. Využívala přesměrování přerušení klávesy na proceduru, která zajišťovala kopírování textových obrazovek do souboru na disku. Program pracoval v základní paměti (640 KB) a pro její úsporu ukládal obrazovky v interruptové proceduře přímo do souboru. To však mělo neblahé následky na správnou funkci programu, který byl náchylný k blokování počítače. Zápis na disk v interruptové proceduře je totiž nekorektní a vyčleněním nějaké rozumně veliké vyrovnávací paměti (např. 80 x 25 x počet obrazovek) se zase ubíral prostor pro spouštění větších programů.

Hladké řešení problému nedostatku základní paměti přinesl až Borland Pascal 7.0, který umožňuje ladit a provozovat programy v chráněném režimu. Zde již není problém nadefinovat dostatečně velkou paměť (v oblasti XMS, je-li jí dostatek) pro ukládání obrazovek a při ukončení programu tuto paměť přepsat do souboru na disk. Tím se lze vyhnout závažným nekorektnostem a přitom nám zůstane sdostatek paměti v dolních 640 KB pro spouštění i paměťově náročných programů.

Jako vhodná se ukázala i změna přerušení z 05 (PrintScreen) na přerušení 09 (klávesnice) - to nám dovoluje nadefinovat aktivaci ukládání na jakoukoli klávesu. Např. (viz uvedený výpis) chcete-li stahovat z obrazovky nějaký text, který se roluje klávesou , je vhodné aktivovat ukládání obrazovky právě na tuto klávesu, což nám na jedno stisknutí zajistí uložení obrazovky a zároveň i její rolování.

Program lze použít např. pro vytváření dokumentace vlastních programů.
Základní princip tkví ve využití objektu TMemoryStream, který umí využít paměť XMS pro ukládání dat. S objektem se přitom pracuje stejně jako s proudy, které ukládají data na disk (TDosStream). Tato vlastnost umožňuje v konečné fázi jednoduše poslat proud Memory do proudu Disk. Při vlastním přerušení však zapisujeme do paměti, nikoli na disk.

Při inicializaci objektu TMemoryStream je nutno definovat v metodě Init celkovou velikost potřebné paměti (zde 1000000 bajtů; záleží na velikosti vaší RAM, počítejte přibližně s možností využití paměti nad 2 MB) a velikost jednotlivých paměťových bloků (zde 8000 bajtů) - blíže viz dokumentaci v souboru manual.tv. Procedura PrtScr obsluhuje vlastní přerušení klávesnice a volání procedury PScreen, která pak provede uložení obrazovky. Po ukončení programu příkazem EXIT se přepíše obsah proudu Memory na disk do předem definovaného souboru.

Program je nutno odladit v režimu Compile/Target/Protected mode}. Program může dělat nedobrotu při volání programů *.bat. To lze obejít tak, že vypustíte smyčku volání programů a v proceduře Exec nahradíte parametr '/C'+Command jménem žádaného programu (.exe nebo .com) a v souboru .bat nahradíte volání původního programu voláním tohoto. Pokud se program nebude chovat řádně, pohrajte si s hodnotami v Options/Compiler. S programem je nutno mít na disku i soubory DPMI16BI.OVL a RTM.EXE.

{$M 8192}

uses Dos,Objects,Crt;
const
  RowStart=0;  {První a poslední řádka}
  RowEnd=24;   {Aktuální pocet řádků zmenšený o 1
                je uložen na adrese Mem[Seg0400:84]}
  ColStart=1;  {První a poslední sloupec}
  ColEnd=80;   {Aktuální šířka řádky je uložena na adrese
                Memw[Seg0400:4A]}

var
  P:pointer;
  R:registers;
  Dir:DirStr;
  ScreenAdr:word; {Adresa začátku obrazovkové paměti}
  Inter:byte;     {Adresa přesměrovaného vektoru přerušení}
  Command:string[127];
  Memory:TMemoryStream;{Proud v paměti pro ukládání obraz.}
  Disk:TDosStream; {Proud na disku (soubor), do kterého se
                    uloží obsah obrazovek z proudu Memory}
  EL:word;        {End of Line}
  Pos:longint;

function Ex(s:string):boolean;
var
  i:byte;
begin
  for i:=1 to 4 do s[i]:=UpCase(s[i]);
  s[0]:=#4;
  if s='EXIT' then Ex:=true else Ex:=false;
end;

procedure PScreen;
var
  Buff:array [1..160] of char;  {Skutečná velikost paměti,
                        kterou potřebuje 80-znakový řádek}
  i,j:integer;
begin
  for i:=RowStart to RowEnd do
  begin
    Move(Mem[ScreenAdr:2*80*i],Buff,160);
    for j:=ColStart to ColEnd
           do Memory.Write(Buff[2*j-1],1);
    Memory.Write(EL,2);
  end;
  Sound(880); Delay(10); Nosound;
end;

procedure PrtScr; interrupt;
begin
  Intr(Inter,R);
  if Port[$60]=81 then
  if Memw[Seg0040:Memw[Seg0040:$1A]]=$5100 then PScreen;
                {PgDn na numerické klávesnici}
{ Lze použít i řídících kláves, např.
  if (Memw[Seg0400:17] and $030E)=$030E then PScreen;
  = Ctrl-Shift-Alt}
end;

begin
  if ParamCount<>1 then
  begin
    WriteLn('Jako parametr musi byt uvedeno
 jmeno souboru,');
    WriteLn('do ktereho chces obrazovky zapisovat.');
    Halt(0);
  end;
  if LastMode=7 then ScreenAdr:=SegB000
     else ScreenAdr:=SegB800;
  Inter:=$90;
  GetIntVec($9,P);
  SetIntVec(Inter,P);
  SetIntVec($9,@PrtScr);
  WriteLn('Instalovan program Print Screen,
 obrazovky se zapisi do souboru');
  WriteLn(ParamStr(1),'.  Ukonceni prikazem EXIT.');
  WriteLn('Verze 3.0         HLINKA-SOFT   (c) 1993,
 tel: (02) 795 29 56');

  EL:=$0A0D;
  Memory.Init(1000000,8000); {Zde je max. velikost souboru
         1000000 bajtů, tedy 1000000/80 řádek -- lze měnit}
  repeat
    GetDir(0,Dir);
    Write('<PS> ',Dir,'>');
    ReadLn(Command);
    if not Ex(Command) then
    begin
      SwapVectors;
      Exec(GetEnv('COMSPEC'),'/C '+Command);
      SwapVectors;
      if DosError <> 0
         then WriteLn('Nelze spustit COMMAND.COM');
      WriteLn;
    end;
  until Ex(Command);
  SetIntVec($9,P);
  Disk.Init(ParamStr(1),stCreate);
  Pos:=Memory.GetPos;
  Memory.Seek(0);
  if Pos>0 then Disk.CopyFrom(Memory,Pos);
  Memory.Done;
  Disk.Done;
end.

Popis důležitých částí: Procedura PrtScr testuje, zda byla stisknuta klíčová klávesa; pokud ano, volá proceduru PScreen. (Pozor, tato procedura se volá při každém stisku klávesy dvakrát -- jednou při stisku a podruhé při puštění klávesy, přičemž pokaždé se vracejí jiné hodnoty.) Port[$60]} vrací číslo klávesy, Memw[Seg0040:Memw[Seg0040:$1A]] kód klávesy. Hodnoty, které potřebujeme, nám může zjistit následující prográmek:

uses Dos;
var r:registers;

function Hex(c:byte):string;
const H:array[0..15] of char='0123456789ABCDEF';
var S:string[2];
begin
  S[0]:=#2;
  S[1]:=H[c div 16];
  S[2]:=H[c mod 16];
  Hex:=S;
end;

begin
  repeat
    r.ah:=$10; {Pro klávesnici 83/84 znaků r.ah:=$00!}
    Intr($16,r);
    WriteLn('Kod klavesy: $',Hex(r.ah),Hex(r.al),
      '   Cislo klavesy: ',Port[$60]);
  until r.al=27;    {ESC}
end.

Volání PScreen lze zajistit i stiskem řídících kláves. Blíže např. v [1] na str. 179.

Procedura PScreen ukládá obsah obrazovky o velikosti (ColStart,RowStart) x (ColEnd,RowEnd), přičemž rozměry standardní obrazovky uvažujeme jako (1,0) x (80,24). Tuto proceduru lze dále zušlechťovat, můžete přidat oddělovací čáru mezi jednotlivými obrazovkami, upravovat některé znaky atp.

Literatura:
[1] BIOS IBM PC -- příručka programátora, Vítězslav Boukal, Grada 1992




Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC