A $host változó szolgáltatásaihoz hasonló dolgokat érünk el a [console] osztály (System.Console ) statikus metódusain keresztül is. Nézzük a tagjellemzőit:
[12] PS C:\> [console] | Get-Member -Static
TypeName: System.Console
Name MemberType Definition
---- ---------- ----------
CancelKeyPress Event System.ConsoleCancelEventHandler CancelKeyP...
Beep Method static System.Void Beep(), static System.Vo...
Clear Method static System.Void Clear()
Equals Method static bool Equals(System.Object objA, Syst...
MoveBufferArea Method static System.Void MoveBufferArea(int sourc...
OpenStandardError Method static System.IO.Stream OpenStandardError()...
OpenStandardInput Method static System.IO.Stream OpenStandardInput()...
OpenStandardOutput Method static System.IO.Stream OpenStandardOutput(...
Read Method static int Read()
ReadKey Method static System.ConsoleKeyInfo ReadKey(), sta...
ReadLine Method static string ReadLine()
ReferenceEquals Method static bool ReferenceEquals(System.Object o...
ResetColor Method static System.Void ResetColor()
SetBufferSize Method static System.Void SetBufferSize(int width,...
SetCursorPosition Method static System.Void SetCursorPosition(int le...
SetError Method static System.Void SetError(System.IO.TextW...
SetIn Method static System.Void SetIn(System.IO.TextRead...
SetOut Method static System.Void SetOut(System.IO.TextWri...
SetWindowPosition Method static System.Void SetWindowPosition(int le...
SetWindowSize Method static System.Void SetWindowSize(int width,...
Write Method static System.Void Write(string format, Sys...
WriteLine Method static System.Void WriteLine(), static Syst...
BackgroundColor Property static System.ConsoleColor BackgroundColor ...
BufferHeight Property static System.Int32 BufferHeight {get;set;}
BufferWidth Property static System.Int32 BufferWidth {get;set;}
CapsLock Property static System.Boolean CapsLock {get;}
CursorLeft Property static System.Int32 CursorLeft {get;set;}
CursorSize Property static System.Int32 CursorSize {get;set;}
CursorTop Property static System.Int32 CursorTop {get;set;}
CursorVisible Property static System.Boolean CursorVisible {get;set;}
Error Property static System.IO.TextWriter Error {get;}
ForegroundColor Property static System.ConsoleColor ForegroundColor ...
In Property static System.IO.TextReader In {get;}
InputEncoding Property static System.Text.Encoding InputEncoding {...
KeyAvailable Property static System.Boolean KeyAvailable {get;}
LargestWindowHeight Property static System.Int32 LargestWindowHeight {get;}
LargestWindowWidth Property static System.Int32 LargestWindowWidth {get;}
NumberLock Property static System.Boolean NumberLock {get;}
Out Property static System.IO.TextWriter Out {get;}
OutputEncoding Property static System.Text.Encoding OutputEncoding ...
Title Property static System.String Title {get;set;}
TreatControlCAsInput Property static System.Boolean TreatControlCAsInput ...
WindowHeight Property static System.Int32 WindowHeight {get;set;}
WindowLeft Property static System.Int32 WindowLeft {get;set;}
WindowTop Property static System.Int32 WindowTop {get;set;}
WindowWidth Property static System.Int32 WindowWidth {get;set;}
Ezzel készíthetünk a régi ZX Spectrum és Commodore világába visszavezető, képernyő-pozícióba kiíró WriteTo-Pos függvényt:
function WriteTo-Pos ([string] $str, [int] $x = 0, [int] $y = 0,
[string] $bgc = [console]::BackgroundColor,
[string] $fgc = [Console]::ForegroundColor)
{
if($x -ge 0 -and $y -ge 0 -and $x -le [Console]::WindowWidth -and
$y -le [Console]::WindowHeight)
{
$saveY = [console]::CursorTop
$offY = [console]::WindowTop
[console]::setcursorposition($x,$offY+$y)
Write-Host -Object $str -BackgroundColor $bgc `
-ForegroundColor $fgc -NoNewline
[console]::setcursorposition(0,$saveY)
}
}
A paraméterei: a kiírandó karakter (lehet szöveg is), a koordináta x és y része, valamint a háttérszín és a betű színe. Itt a fő okosság, hogy a konzol ablak a koordinátákat nem a látható részhez, hanem a teljes képernyő pufferhez számolja, így ha én a látható képernyő megfelelő pozíciójába akarok írni, akkor a „eltolást” figyelembe kell venni, amit a [console]::WinodwsTop statikus tulajdonság ad meg.
És ezzel akár körrajzoló függvényt is tudunk készíteni:
function Draw-Circle ($x, $y, $r)
{
$step = [int] ([Math]::Atan(1/$r)*30)
$px = (Get-WmiObject -Class Win32_VideoController
).currenthorizontalresolution
$py = (Get-WmiObject -Class Win32_VideoController
).currentverticalresolution
$cx = [Console]::LargestWindowWidth
$cy = [Console]::LargestWindowHeight
$deform = $py/$cy/$px*$cx
for($i =0; $i -lt 360; $i+=$step)
{
$oy = [int] ($y + $r*[math]::sin($i/180*[math]::pi))
$ox = [int] ($x + $r*[math]::cos($i/180*[math]::pi)*$deform)
switch($i)
{
{$i -gt 337} {$c = "|"; break}
{$i -gt 292} {$c = "\"; break}
{$i -gt 247} {$c = "-"; break}
{$i -gt 202} {$c = "/"; break}
{$i -gt 157} {$c = "|"; break}
{$i -gt 112} {$c = "\"; break}
{$i -gt 67} {$c = "-"; break}
{$i -gt 22} {$c = "/"; break}
default {$c = "|"}
}
WriteTo-Pos $c $ox $oy
}
}
A függvény definíciója nem sok magyarázatot igényel. Az $x, $y a kör közepének koordinátái, az $r a sugara, a $step a kör kirajzolásának a „felbontása” fokokban, melyet a sugár nagyságához igazítok. Kis körnél a két egymás melletti körívpont kirajzolásához nagyobbat lehet fordulni, nagyobb körnél kisebbet lehet csak fordulni, különben „lukacsos” lesz a körív. A karakterek nem négyzet alakúak, a WMI video vezérlő adataiból meg lehet a monitor vízszintes és függőleges felbontását határozni, valamint ezt összevetve a karakterszámban kifejezett maximális PowerShell ablakmérettel, ebből kijön a konzol fontjainak téglalap formájának aránya, amit a $deform változóban tárolok. Plusz még a fok függvényében más és más karaktert rak ki a képernyőre, amelyek jobban szimulálják a körívet.
Ezzel ilyen szépségeket lehet rajzolni:
138 . ábra Körrajzolás a konzolra
Sőt! Ezzel az osztállyal megoldható a várakozás nélküli billentyűzetfigyelés is:
function getkeysilent
{
if([console]::KeyAvailable){
while([console]::KeyAvailable){$key = [console]::readkey().Key}}
else{$key = "nokey"}
$key
}
A KeyAvailable statikus tulajdonság akkor válik igazzá, ha van leütött billentyűzet. Ennek vizsgálatával csak akkor olvasom be a ReadKey metódussal a billentyűt, ha már tudom, hogy le volt nyomva, így nem várakozik. Viszont ilyenkor elképzelhető, hogy a billentyűzet pufferbe több leütés is feltorlódott, így egészen addig kell olvasni, amíg a KeyAvailable jelez megnyomást. Visszatérési értékként a puffer utolsó billentyűzetlenyomását adom vissza.
A konzol tartalmát is be lehet olvasni, erre írtam egy célfüggvényt, mellyel egyszerűbb lesz egy karaktert beolvasni az x-y koordinátáról:
function getpos ($x, $y)
{
if($x -ge 0 -and $y -ge 0 -and $x -le [Console]::WindowWidth -and
$y -le [Console]::WindowHeight) {
$y += [console]::WindowTop
$r = New-Object System.Management.Automation.Host.Rectangle $x,$y,$x,$y
$host.UI.RawUI.GetBufferContents($r)[0,0].character
}
}
Ehhez nem a [console] osztály jó nekünk, hanem a $host automatikus változó, mely egy téglalap típusú osztályt vár paraméterként.