Using Picture Windows

Contributed by dohcan
Picture windows are a great way to add originality to your script or to create new functionality. Suppose you need a progress bar? You can use a picture window and /drawrect commands to create your own. Suppose you want to list information in a way not possible with dialogs or standard windows? You can use /drawtext to place text in exactly the right spot, even with different fonts and colors. In this example, we will make a small "file process" script. It will scroll files from a chosen directory, gather information about them, and show a progress bar. This example will make use of /drawrect, /drawtext, and /drawscroll. Please remember there are many more /draw* commands, such /drawline and /drawdot. Check the helpfile for the complete list.

(source code for this example will provided in full at the bottom of this document)
Where Do We Start?
A picture window is sort of a like a painter's canvas. You can use it to draw lines, write text, places dots, just about anything you want. Each /draw* command takes certain parameters, like X,Y coordinates, the width and height of what you're drawing, the font, the color, etc. You can use this to precisely place the objects you want to display.

As mentioned before, in this example, we are going to make a "file process" script. This would be helpful of you were creating an mp3 serve script and generating a list of your files. Since these operations can take quite a while if you have a lot of files to analyze, it would be nice to show some sort of progress, instead of just letting mIRC "freeze up" while it is working.
Creating The Window
The first thing we need to do is create our picture window. This is accomplished by using the -p parameter in the /window command. So any window created like this:

/window -p @WindowName

..will be a picture window. You are not allowed to use any of the standard /*line commands that are available with normal custom @windows, but are required to use the /draw* commands. For our example, we will be creating a window that is 350 pixels wide and 180 pixels tall. The alias we will be using to call this procedure will be "/fileprocess", and use the syntax:

/fileprocess <directory> <file extension>

eg "/fileprocess c:\ *.mp3" would search all of c:\ for mp3 files.

To create our picture window, we do:
window -fp @FP 50 50 350 185
The -f parameter tells the window command to use the width and height parameters for the inside of the window (or client area) and not count the border or titlebar. This will make using the /draw* commands easier, as we will not have to take into account the size of titlebar and borders, since they can vary from system to system depending on the fonts used. We are placing the window at location X = 50, Y = 50.

Since we are dealing with files in this example, we will also create a secondary hidden window called @FP.Hidden. The identifier used to find files, $findfile(), can take a custom window as a parameter, and fill it with the matches found. This will allow us to store the results and avoid making repeated calls to $findfile(), thus greatly increasing the speed of the file processor. The syntax we will use for that is simply:
window -hl @FP.Hidden
We used the -h (hidden) parameter, so the X, Y, W, H parameters are not needed.
Finding the Files
Since we passed the directory and the file extension to look for when we called the alias, we use these as parameters in our $findfile() call. We can then store the result in a variable, so we know how much to loop when outputting the progress.
var %found = $findfile($1, $2, 0, @FP.Hidden)
Notice the 4th parameter. That will fill our hidden file list window with the matching files, a separate file on each line. Now the fun part begins.
Using the Picture Window
Now that we have our two windows, @FP, the output window, and @FP.Hidden, the hidden file list window, we can loop through each line and display the output. To do this, we will use a while loop:
var %i = 1
That will set our loop control variable to one. If you do not understand how loops work, you might want to take a look at our loops tutorial, then come back to this one.
var %file, %size
These are just temporary variables pertaining to the files. Their use will become apparent once we get to them in the while loop.
titlebar @FP Processing %found files...
Simply changes the titlebar to show the number of files found.
drawrect -fn @FP 1 1 0 0 350 185
Our first /draw* command, probably one of the most common ones, /drawrect. We'll start with the most obvious parameters first. The "@FP" parameter tells it to draw in the @FP window, which is our main output window. The "0 0 350 185" tells it to start at X = 0, Y = 0 and draw a rectangle that is 350 pixels wide and 185 pixels tall. In this example, that covers the entire window. The "1 1" is the color and the size of the lines of the rectangle. Finally, the "-fn" means "fill the rectangle" and "do not update immediately." The -f parameters tells it to fill the inside area. The -n parameter tells it to hold off updating until we tell it to. This is because we are going to be doing several operations, and updating after each operation (ie, not using the -n parameter) would cause a great deal of flicker.

So now we have a window that is filled entirely with black. We enter the while loop:
while (%i <= %found) {
While the loop control variable is less than or equal to the number of files found...
%file = $line(@FP.Hidden, %i)
%size = $round($calc($file(%file).size / 1024), 1) $+ kb
Those two lines simply get information about the current file, %file containing the file itself and %size containing its file size (converted to kilobytes).
drawscroll -n @FP 0 -15 0 10 350 150
Another /draw* command, this time /drawscroll. This one may seem a little tricky, but in actuality, it's very similar to the /drawrect command. We know that the "-n" means "do not update immediately" and the "@FP" means work in the @FP custom window. The "0 -15" parameters govern how far in either direction the section is scrolled. The "0 10 350 150" tell it what "section" to grab. In this example, we grab a rectangle that starts at X = 0, Y = 10, and is 350 pixels wide and 150 pixels tall. We don't want to grab the whole thing, as we need to leave room for our scroll bar at the bottom. Back to the "0 -15". These are the amounts to scroll in either direction. The first number, 0, means scroll 0 pixels in the X direction. In other words, to not scroll. The second number, -15, means scroll -15 pixels in the Y direction. Specifying this as a negative makes the scrolling go backwards, or upwards, however you want to look at it.

In this example, we are scrolling files upward. Each file is display on its own line, which is 15 pixels tall. So each time we encounter a new file, we scroll up 15 pixels to make room for the new file.
drawrect -fn @FP 1 1 0 145 350 15
When we scroll, the area where the "section" was still remains, so we must cover up that area. We will use a simple /drawrect call that covers the area with a black filled rectangle. The parameters are exactly the same as the first /drawrect we did, except for the Y and the H parameters. We only want to cover up a small portion, the portion that was scrolled with the /drawscroll command. We draw a rectangle that starts at X = 0, Y = 145 and is 350 pixels wide and 15 pixels tall. This exactly fills the area we uncovered when we scrolled.

So now we have a blank 15 pixel line that is ready to accept a new file.
drawtext -n @FP 0 "MS Sans Serif" -8 10 145 %i $+ . %file %size
In this line, we see some familiar parameters, such as the "-n" and "@FP", but we also see some new ones. The "0" by itself is simply the color of the text we are going to draw. We want white text, so we use 0. The next parameter is "MS Sans Serif". This is the font we want to use when drawing the text. Notice the quotations around it in the font name in the /drawtext call, this is because the font has spaces in its name. The next parameter is "-8". Using a negative number will make the font size match up to the font size in the font dialog. Next we have "10 145", which means put the upper left corner of the text at X = 10, Y = 145. These are the placement parameters. With these, you can move the text where ever you want. The last parameter is "%i $+ . %file %size", the text part we are drawing. In this example, this will result in something like: "1. c:\windows\file.ext 25kb"
Drawing the Progress Bar
The final part in our example is the progress bar. Since there are no progress bars available in mIRC (without the use of external DLLs), we can create one. And it's not hard. Two /drawrect calls. That's it.

The first call we will use will be the one to draw the actual "progress" so far.
drawrect -fn @FP 12 1 10 165 $int($calc(330 * (%i / %found))) 10
Looking at that, we see a lot of familiar parameters. We are drawing a filled rectangle that is 10 pixels high. But look at the X, Y, and W parameters. Since this is a progress bar, the width will vary depending on what the %i variable is, since the %i variable is our loop control variable. Since we want to have a little margin between the edge of our window and the progress bar, we start at X = 10. Since we want the progress bar always at the bottom, we set Y = 165. This will give us a nice 10 pixel margin from the left, right, and bottom. To calculate the progress, we use a simple formula, "$int($calc(330 * (%i / %found)))". (%i / %found) returns the percentage completed. We multiply it by 330, the maximum width of our progress bar. We derived 330 from the original 350, minus 10 pixels for the left margin and 10 pixels for the right margin. A progress bar that is 330 pixels wide represents 100% complete. We then just use $int() since we can't have part of a pixel.

The next line will draw our progress bar frame:
drawrect -n @FP 0 1 10 165 330 10
Again, very familiar, but in this case, we do NOT use the -f parameter. That is because we just want a frame for our progress bar. Also, we want the frame to be width of a completed progress bar, so we can see how much we have left.

And the final /draw* command we use is:
drawpic @FP
Notice no -n parameter. When you call any /draw* command without the -n parameter, it forces the window to be updated. It is recommended that you use this approach when using picture windows, to avoid flickering, especially if you do processing that is very intensive. I used /drawpic here, but you can use any command to make it update, such as /drawfill @FP or /drawtext @FP. When doing the update, no other parameters are required. To finish, we do
  inc %i
}
window -c @FP.Hidden
That just handles our loop control variable, and once the loop is over, it closes the hidden file list window we had, as it is no longer needed. If some error should occur, you can get to the hidden window via the Window menu in mIRC, to close it manually, or you can type /window -c @FP.Hidden.
Conclusion
We only covered a few /draw* commands in this example, but as you can see, they all use similar syntax and all have common elements, such as @window, color, size, x, y, w, and h parameters. In the mIRC help file, you can get a complete list of the /draw* commands with full syntax. Some commands take unlimited parameters, like /drawline. Some let you draw images on your window. The possibilities are endless, and hopefully now you have an idea about how to approach scripting with picture windows.

As mentioned at the beginning of this document, full source code is provided for the example we used:
; usage: /fileprocess <directory> <extension>
fileprocess {
  if ($1 == $null) || ($2 == $null) {
    echo -a * /fileprocess: you must supply directory and extension parameters
    return
  }
  window -hl @FP.Hidden
  window -fp @FP 50 50 350 185

  var %found = $findfile($1, $2, 0, @FP.Hidden)
  var %i = 1
  var %file, %size

  titlebar @FP Processing %found files...

  ; Fill the entire thing with black first
  ; This is basically personal preference
  drawrect -fn @FP 1 1 0 0 350 185

  while (%i <= %found) {
    ; Get the filename
    %file = $line(@FP.Hidden, %i)

    ; Find the size of the file
    %size = $round($calc($file(%file).size / 1024), 1) $+ kb

    ; Scroll the window
    ; "-15" for the X parameter means go up 15 pixels
    ; likewise, "15" for parameter would mean go down
    drawscroll -n @FP 0 -15 0 10 350 150

    ; Fill the area uncovered by the scroll with black
    drawrect -fn @FP 1 1 0 145 350 15

    ; Draw the filename and the size in the new area
    ; cleared by the drawrect command
    drawtext -n @FP 0 "MS Sans Serif" -8 10 145 %i $+ . %file %size

    ; Draw the progress bar at the bottom
    drawrect -fn @FP 12 1 10 165 $int($calc(330 * (%i / %found))) 10

    ; Draw the frame of the progress bar
    drawrect -n @FP 0 1 10 165 330 10

    ; Force the window to update
    drawpic @FP

    inc %i
  }

  ; Close the temporary hidden window
  window -c @FP.Hidden
}
All content is copyright by mircscripts.org and cannot be used without permission. For more details, click here.