Miniwindows in MUSHclient - Drawing shapes
Written by Nick Gammon - July 2008. Updated September 2010.
On this page:
- Pen parameters
- Brush parameters
- Rectangle coordinates
- WindowArc
- WindowBezier
- WindowCircleOp
- WindowGradient
- WindowLine
- WindowPolygon
- WindowRectOp
- WindowSetPixel
See also:
- Introduction
- Creating miniwindows
- Drawing text
- Drawing images
- Hotspots
- Helpful graphics functions
- Blending images
Examples on this page
Most of the examples on this page are drawn in a 100 x 100 pixel window, with a grid drawn every 20 pixels to make it clearer the effect of the example code. The code for producing the grid is described in Creating miniwindows.
Pen parameters
Many functions below use a "pen". This is something used to draw lines. To save explaining the pen parameters for every function they are listed here:
- PenColour - the RGB colour for this pen (a number). You can use ColourNameToRGB to convert a colour name (like "red" or "green") into a colour number.
- PenStyle - what style of pen to use:
Value Purpose Lua symbol 0 Solid (an unbroken pen) miniwin.pen_solid 1 Dash: ------- miniwin.pen_dash 2 Dot: ....... miniwin.pen_dot 3 Dashdot: _._._._ miniwin.pen_dash_dot 4 Dashdotdot: _.._.._ miniwin.pen_dash_dot_dot 5 5 - Null (no pen) miniwin.pen_null 6 Insideframe - a solid pen, drawn inside the shape miniwin.pen_inside_frame You can also add in one of the following to control how the ends of line are drawn (version 4.59 onwards):
Value Purpose Lua symbol 0 Round ends (the default) miniwin.pen_endcap_round 0x100 (256) Square ends miniwin.pen_endcap_square 0x200 (512) Flat ends miniwin.pen_endcap_flat You can also add in one of the following to control how lines join (version 4.59 onwards):
Value Purpose Lua symbol 0 Round joins (the default) miniwin.pen_join_round 0x1000 (4096) Bevel joins miniwin.pen_join_bevel 0x2000 (8192) Miter joins miniwin.pen_join_miter Lua note: Instead of numbers you can use the above "symbolic constants" in Lua (version 4.52 onwards).
- PenWidth - the width of the pen in pixels. For styles 1 to 4 only a width of 1 is valid.
For a particular shape, specify style 5 (miniwin.pen_null) if you only want to fill the shape, and not stroke it as well.
Brush parameters
Many functions below use a "brush". This is something used to fill the interior of a shape. To save explaining the brush parameters for every function they are listed here:
- BrushColour - the RGB colour for this brush. You can use ColourNameToRGB to convert a colour name (like "red" or "green") into a colour number.
- BrushStyle - what style of brush to use:
Value Purpose Lua symbol 0 Solid (filled with a solid colour) miniwin.brush_solid 1 Null (not filled) miniwin.brush_null 2 Hatch: horizontal miniwin.brush_hatch_horizontal 3 Hatch: vertical miniwin.brush_hatch_vertical 4 Hatch: forwards diagonal miniwin.brush_hatch_forwards_diagonal 5 Hatch: backwards diagonal miniwin.brush_hatch_backwards_diagonal 6 Hatch: cross miniwin.brush_hatch_cross 7 Hatch: diagonal cross miniwin.brush_hatch_cross_diagonal 8 Fine pattern miniwin.brush_fine_pattern 9 Medium pattern miniwin.brush_medium_pattern 10 Coarse pattern miniwin.brush_coarse_pattern 11 Waves - horizontal miniwin.brush_waves_horizontal 12 Waves - vertical miniwin.brush_waves_vertical Lua note: Instead of numbers you can use the above "symbolic constants" in Lua (version 4.52 onwards).
These screenshots illustrate the effects of the various brush styles (style 1 - no brush - is not shown).
For the various patterns, the PenColour is used as the "foreground" colour of the pattern, and the BrushColour is used as the "background" colour of the pattern.
Rectangle coordinates
In many functions described below you specify the rectangle in which the shapes is to appear (including ellipses, circles, etc.). As a shorthand you can specify a negative number, or zero, for the bottom or right side. This is taken to be offset from the bottom or right edge of the containing miniwindow. For example:
- Rectangle: 0,0,0,0 - the whole miniwindow
- Rectangle: 2,2,-2,-2 - a rectangle offset by 2 from each edge
- Rectangle: 20,40,0,0 - a rectangle starting 20 from the left, 40 from the top, and continuing the the right and bottom edges.
Straight lines
WindowLine function prototype:
long WindowLine(BSTR Name, long x1, long y1, long x2, long y2, long PenColour, long PenStyle, long PenWidth);
This draws a line from x1,y1 to x2,y2 with the designated pen.
- Name - the name of an existing miniwindow. Names are case-sensitive.
- x1, y2 - the starting point for the line
- x2, y2 - the ending point for the line (negative or zero is taken literally for x2 and y2, not as an offset from the right-hand or bottom edges).
- PenColour, PenStyle, PenWidth - the pen colour, style, and width as described at the top of this page.
Example of drawing a line
WindowLine (win, 20, 20, 80, 80, ColourNameToRGB ("blue"), miniwin.pen_solid, 2)

Arcs
WindowArc function prototype:
long WindowArc(BSTR Name, long Left, long Top, long Right, long Bottom, long x1, long y1, long x2, long y2, long PenColour, long PenStyle, long PenWidth);
This draws an arc from x1,y1 to x2,y2 inside the box (Left,Top,Right,Bottom) with the designated pen.
- Name - the name of an existing miniwindow. Names are case-sensitive.
- Left, Top, Right, Bottom - describes the rectangle into which the arc must fit.
- x1, y2 - the starting point for the arc - this point does not have to lie exactly on the arc.
- x2, y2 - the ending point for the arc - this point does not have to lie exactly on the arc.
- PenColour, PenStyle, PenWidth - the pen colour, style, and width as described at the top of this page.
Example of drawing an arc
WindowArc (win, 20, 20, 80, 80, 30, 30, 120, 50, ColourNameToRGB ("green"), miniwin.pen_solid, 4)

The example above shows the enclosing rectangle, in blue, and the starting and ending points, in red, to illustrate how the arc works. They are not drawn as part of the arc, but shown to illustrate the idea.
Polygons
WindowPolygon function prototype:
long WindowPolygon(BSTR Name, BSTR Points, long PenColour, long PenStyle, long PenWidth, long BrushColour, long BrushStyle, BOOL Close, BOOL Winding);
This draws a polygon (series of straight lines) connecting the specified points, with the designated pen and filled with the designated brush.
- Name - the name of an existing miniwindow. Names are case-sensitive.
- Points - a string consisting of pairs of numbers, one for each point, in the format x1,y1,x2,y2 ...
For example: "20,50,180,50" would specify two points, one at 20,50 and one at 180,50.
You must have at least 2 points (the start and end), which is 4 numbers. The number of numbers in the string must be even (divisible by two), as it takes a pair of numbers to specify one point.
- PenColour, PenStyle, PenWidth - the pen colour, style, and width as described at the top of this page.
- BrushColour, Brushstyle - the brush colour and style as described at the top of this page.
- Close - if true, the polygon is closed by connecting the last point to the first one, if necessary
- Winding - if true the polygon is filled using the "winding" algorithm, if false it is filled using the "alternate" algorithm. When the polygon-filling mode is "alternate", the system fills the area between odd-numbered and even-numbered polygon sides on each scan line. That is, the system fills the area between the first and second side, between the third and fourth side, and so on. This mode is the default. When the polygon-filling mode is "winding", the system uses the direction in which a figure was drawn to determine whether to fill an area. Each line segment in a polygon is drawn in either a clockwise or a counterclockwise direction. Whenever an imaginary line drawn from an enclosed area to the outside of a figure passes through a clockwise line segment, a count is incremented. When the line passes through a counterclockwise line segment, the count is decremented. The area is filled if the count is nonzero when the line reaches the outside of the figure.
Example of drawing a polygon
WindowPolygon (win, "20,50,180,50,180,20,230,70,180,120,180,90,20,90",
ColourNameToRGB("cyan"), miniwin.pen_solid, 3, -- pen (solid, width 3)
ColourNameToRGB("yellow"), miniwin.brush_solid, -- brush (solid)
true, -- fill
false) -- alternate fill

Rectangles
WindowRectOp function prototype:
long WindowRectOp(BSTR Name, short Action, long Left, long Top, long Right, long Bottom, long Colour1, long Colour2);
This draws a rectangle in various styles, controlled by the Action parameter. You can also use WindowCircleOp with an action of 2 (miniwin.circle_rectangle) to draw rectangles with a pen and brush.
- Name - the name of an existing miniwindow. Names are case-sensitive.
- Action - what sort of rectangle to draw, as follows:
Value Purpose Lua symbol 1 Frame by a single pixel wide line in Colour1 miniwin.rect_frame 2 Fill the entire rectangle by Colour1 miniwin.rect_fill 3 InvertRect - the colour on the miniwindow inside that rectangle is inverted miniwin.rect_invert 4 Draw a "3D-style" rectangle in two colours, a single pixel wide (Colour1 is top and left edge colour, Colour2 is bottom and right edge colour) miniwin.rect_3d_rect 5 Draw Edge (draws a 3d-style edge with optional fill) miniwin.rect_draw_edge 6 Flood Fill Border (fills to border specified by Colour1) - the filling commences at the pixel designated by Left, Top and continues until it runs out of pixels that colour. miniwin.rect_flood_fill_border 7 Flood Fill Surface (fills while on surface specified by Colour1) - the filling commences at the pixel designated by Left, Top and continues until it is on pixels that colour. miniwin.rect_flood_fill_surface - Left, Top, Right, Bottom - describes the rectangle to be drawn.
- Colour1 - the colour to draw the rectangle in (or fill it). For Action 5 (miniwin.rect_draw_edge), this must be one of:
Value Purpose Lua symbol 5 Raised miniwin.rect_edge_raised 6 Etched miniwin.rect_edge_etched 9 Bump miniwin.rect_edge_bump 10 Sunken miniwin.rect_edge_sunken - Colour2 - the colour used by Action 4 (miniwin.rect_3d_rect) for the bottom and right edge. For Action 5 (miniwin.rect_draw_edge), this is:
Value Purpose Lua symbol 3 Top left miniwin.rect_edge_at_top_left 6 Top right miniwin.rect_edge_at_top_right 9 Bottom left miniwin.rect_edge_at_bottom_left 12 Bottom right miniwin.rect_edge_at_bottom_right 15 Rect miniwin.rect_edge_at_all Diagonal lines:
Value Purpose Lua symbol 19 Diagonal - end top left miniwin.rect_diagonal_end_top_left 22 Diagonal - end top right miniwin.rect_diagonal_end_top_right 25 Diagonal - end bottom left miniwin.rect_diagonal_end_bottom_left 28 Diagonal - end bottom right miniwin.rect_diagonal_end_bottom_right For Action 5 (miniwin.rect_draw_edge) you can also add in the following values to modify the behaviour of the drawn rectangle:
Value Purpose Lua symbol 0x0800 (2048) Fill in the middle miniwin.rect_option_fill_middle 0x1000 (4096) For softer buttons miniwin.rect_option_softer_buttons 0x4000 (16384) For flat rather than 3D borders miniwin.rect_option_flat_borders 0x8000 (32768) For monochrome borders miniwin.rect_option_monochrom_borders
Examples of drawing rectangles
Resulting image is to the left of the corresponding code.
| |
There are more things you can try with rectangles, such as "bump" and "sunken" styles. Ellipses, Filled Rectangles, Round Rectangles, Chords, PiesWindowCircleOp function prototype:
long WindowCircleOp(BSTR Name, short Action, long Left, long Top, long Right, long Bottom, long PenColour, long PenStyle, long PenWidth, long BrushColour, long BrushStyle, long Extra1, long Extra2, long Extra3, long Extra4);
This draws an ellipse, rectangle, round rectangle, chord or pie, controlled by the Action parameter. Unlike WindowRectOp, described above, the rectangles drawn here can be filled with a brush, thus allowing you to have patterned interiors if desired. If you just want to draw a plain rectangle, however, WindowRectOp may be easier to use.
Examples of drawing ellipses and other shapesResulting image is to the left of the corresponding code.
The example above shows the enclosing rectangle, in blue, and the starting and ending points, in red, to illustrate how the chord works. They are not drawn as part of the chord, but shown to illustrate the idea.
The example above shows the enclosing rectangle, in blue, and the starting and ending points, in red, to illustrate how the pie works. They are not drawn as part of the pie, but shown to illustrate the idea. Bézier curvesWindowBezier function prototype:
long WindowBezier(BSTR Name, BSTR Points, long PenColour, long PenStyle, long PenWidth);
Draws one or more Bézier splines. This function draws cubic Bézier splines by using the endpoints and control points specified by the Points parameter. The first spline is drawn from the first point to the fourth point by using the second and third points as control points. Each subsequent spline in the sequence needs exactly three more points: the end point of the previous spline is used as the starting point, the next two points in the sequence are control points, and the third is the end point.
Example of drawing a Bézier curve
The example above shows the control points, in red, to illustrate how the Bézier curve works. They are not drawn as part of the curve, but shown to illustrate the idea. GradientsWindowGradient function prototype:
long WindowGradient(BSTR Name, long Left, long Top, long Right, long Bottom, long StartColour, long EndColour, short Mode);
Draws a gradient - that is a rectangle that gradually changes from the start colour to the end colour.
Examples of drawing a gradient
Setting pixelsWindowSetPixel function prototype:
long WindowSetPixel(BSTR Name, long x, long y, long Colour);
Sets a single pixel in the miniwindow.
Warning - although setting individual pixels is reasonably fast, if you need to set a lot (for example, to draw a line or a box), it would be much faster to use the appropriate dedicated function (such as WindowLine). This is because to draw boxes and lines, especially large ones, or filled ones, would take many, many calls to WindowSetPixel to achieve the same result. Example of setting pixels
You can also use WindowGetPixel to get the RGB colour code at a particular pixel location. Other pages about miniwindows
|


