PowerShell Cookbook

Search

Categories

 

On this page

Archive

Blogroll

Disclaimer
I work for Microsoft.

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 222
This Year: 0
This Month: 0
This Week: 0
Comments: 536

Sign In

 Wednesday, November 16, 2005
Thursday, November 17, 2005 5:08:26 AM (Pacific Standard Time, UTC-08:00) ( )

As your scripts become more complex, it’s possible that you will have to interact with the user in a manner more complex than write- and read-host.  For example, you might decide to implement a text-based menu system, or even a game of Aliens.

To support this low-level access to the console buffer, hosts (for example, ours,) extend the MshHostRawUserInterface class.  This class provides most of the common operations required by a console-mode raw user interface, including window management, blitting, scrolling, and colour control.

The following script demonstrates some of the ways in which you can work with Monad’s Raw UI.  It illustrates:

  • Getting the coordinates of the viewport in relation to the window buffer
  • Getting the current cursor location
  • Obtaining direct access to the console’s buffer contents
  • Scrolling the buffer’s contents
  • Directly writing to the console’s buffer
  • Working within the constraints of the console’s current width and height
 
## scroll-buffer.msh
## Demonstrate some of the features of the MshHostRawUserInterface class
## Simply get a big screen full of junk, and run it.  ^C exits.

function main
{
    ## Get the current coordinates of the view-port within the
    ## screen buffer.
    $currentCoordinatesX = $host.UI.RawUI.WindowPosition.X
    $currentCoordinatesY = $host.UI.RawUI.WindowPosition.Y
    $currentCursorY = $host.UI.RawUI.CursorPosition.Y - 1
    
    ## Initialize a random number generator
    $random = new-object Random

    ## Initialize the scrolling rectangles
    . initializeVerticalScrollRectangles
    . initializeHorizontalScrollRectangle
    
    ## Continuously scroll the rectangles until the user breaks out
    $counter = 0
    while($true
    {
        ## We let each of the vertical scrolling rectangles scroll twice,
        ## and then pick new dimensions and locations
        if($counter -eq ((2 * $rectHeight) + 2)) 
        {
            . initializeVerticalScrollRectangles
            $counter = 0
        }

        $counter++

        ## Sleep a bit so that it looks animated
        start-sleep -m 50

        ## Store the top line of the vertical scrolling rectangle,
        ## scroll the rectangle up,
        ## and fill the emptied space with the old top line.
        $oldBufferLine = $host.UI.RawUI.GetBufferContents(`
            $verticalScrollTopLineRectangle)
        $host.UI.RawUI.ScrollBufferContents(`
            $verticalScrollRectangle,`
            $verticalScrollTargetCoordinates,`
            $verticalScrollRectangle,`
            $cellType)
        $host.UI.RawUI.SetBufferContents(`
            $verticalScrollBottomCoordinates, $oldBufferLine)

        ## Store the left cell of the horizontally scrolling line,
        ## scroll the line left,
        ## and fill the emptied space at the right with the old left cell.
        $oldCell = $host.UI.RawUI.GetBufferContents(`
            $horizontalScrollRectangle)[0,0]
        $host.UI.RawUI.ScrollBufferContents(`
            $horizontalScrollRectangle,`
            $horizontalScrollTargetCoordinates,`
            $horizontalScrollRectangle,`
            $oldCell)
    }
}

function initializeVerticalScrollRectangles
{
    $cellType = new-object System.Management.Automation.Host.BufferCell `
        ".","White","Black","Complete"

    ## Pick constrained random widths and heights
    $rectWidth = [int] ($random.NextDouble() * 38) + 2
    $rectHeight = [int] ($random.NextDouble() * 28) + 2

    ## Decide where we want to position the rectangles
    $xMax = $host.UI.RawUI.WindowSize.Width - $rectWidth
    $yMax = $host.UI.RawUI.WindowSize.Height - $rectHeight - 4
    $xOffset = [int] ($random.NextDouble() * $xMax)
    $yOffset = [int] ($random.NextDouble() * $yMax)

    ## Pick the rectangle that indicates the large vertical scrolling
    ## rectangle region
    $verticalScrollRectangle = `
        new-object System.Management.Automation.Host.Rectangle `
        ($currentCoordinatesX + $xOffset),`
        ($currentCoordinatesY + $yOffset),`
        ($currentCoordinatesX + $xOffset + $rectWidth),`
        ($currentCoordinatesY + $yOffset + $rectHeight)

    ## The rectangle that indicates the top line of the large vertical
    ## scrolling rectangle region
    $verticalScrollTopLineRectangle = `
        new-object System.Management.Automation.Host.Rectangle `
        ($currentCoordinatesX + $xOffset),`
        ($currentCoordinatesY + $yOffset),`
        ($currentCoordinatesX + $xOffset + $rectWidth),`
        ($currentCoordinatesY + $yOffset)

    ## The target of the scroll of the large vertical scrolling region.
    ## This is simply one line up
    $verticalScrollTargetCoordinates = `
        new-object System.Management.Automation.Host.Coordinates `
        ($currentCoordinatesX + $xOffset),`
        ($currentCoordinatesY + $yOffset - 1)

    ## The bottom of the large vertical scrolling region.  This will be
    ## used to fill later with the contents from the top
    $verticalScrollBottomCoordinates = `
        new-object System.Management.Automation.Host.Coordinates `
        ($currentCoordinatesX + $xOffset),`
        ($currentCoordinatesY + $yOffset + $rectHeight)
}

function initializeHorizontalScrollRectangle
{
    $horizontalScrollRectangle = `
        new-object System.Management.Automation.Host.Rectangle `
        0,$currentCursorY,$host.UI.RawUI.WindowSize.Width,$currentCursorY

    $horizontalScrollTargetCoordinates = `
        new-object System.Management.Automation.Host.Coordinates `
        -1,$currentCursorY
}

. main


 

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]

Comments [3] | | # 
Thursday, November 17, 2005 8:54:07 AM (Pacific Standard Time, UTC-08:00)
If you past the script from this page you have to take care that you have no spaces after the ` sign (continue on next line), if there is a space behind it it will not work, and you get alot of errors in the script.

I did solve this by do a search replace in notepad "` " -> "`"

b.t.w. in this case it does not matter but, but if you want a real random number you need to feed the Random a Feed (starting number)

I also posted a nice (I think Example on my blog using the random and the RawUI (remember old data)

http://mow001.blogspot.com/2005/10/thow-dices-in-msh.html

gr /\/\o\/\/
Thursday, November 17, 2005 6:47:42 PM (Pacific Standard Time, UTC-08:00)
Thanks for pointing that out about the back ticks.

Regarding the Random number -- the default constructor initializes the Random class with a time-dependent default seed value. Because of that, it basically does the same thing that you do in your script. I was going to point that out when I first read your roll dices script, but I didn't want to nit pick on your awesome work :)
Tuesday, November 22, 2005 3:09:23 PM (Pacific Standard Time, UTC-08:00)
thx, for pointing this out.
it's not realy clear in the SDK (only if you choose the constuctor help, the sample scipt is misleading), so I missed this, and as I was used to feeding my rnd a time since the great Atari 800 ;-), i did not look much further,I just carried on,
b.t.w. feel free to nit pick ;-) as it's a learning traject.

sorry about Miss Picking on you ;-)

gr /\/\o\/\/
Name
E-mail
Home page

Comment (Some html is allowed: b, blockquote@cite, em, i, strike, strong, sub, super, u)  

Enter the code shown (prevents robots):