WinRgn.dll v1.2

by dohcan (dohcan@mircscripts.org)

-----

v1.2 Changes
1.  Added polygon support.  See below for examples.
2.  Made /winrgn a little better (outputs line where error occurred).


v1.1 Changes

1.  Made delete work better. (Tip from ^Andy)
2.  Added wrInvertRegion, works just like the rest.
3.  Fixed /winrgn to work with only one parameter (wrVersion, wrResetWindow). If
    you do not choose to use the provided /winrgn, make sure you call $dll()
    with at least three parameters, or it will not work correctly.

-----

The purpose of this DLL is to allow you to define "window regions" to windows
inside of mIRC.  You can use this to make round windows, windows with holes in
them, and many more combinations.

The functions you use to manipulate the windows are as follows:

(all function names are case sensitive)


wrSelectWindow <handle>

  Should be the first function you call after creating your window.  This sets
  it as the working window, and this is the window the other functions have
  an effect on.  You also use this to switch between multiple windows.
  
  Ex: $dll(WinRgn.dll, wrSelectWindow, $window(@test).hwnd)

-
  
wrSetMode <rmRect|rmRoundRect|rmElliptical>

  Sets the mode of the region that is set, added, or deleted with wrSetRegion,
  wrAddRegion, and wrDeleteRegion.  It effects the window that was selected with
  wrSelectWindow.  Defaults to rmRect.
  
  Ex: $dll(WinRgn.dll, wrSetMode, rmRoundRect)

-
  
wrSetRegion     <X1 Y1 X2 Y2 [CW CH]>
wrAddRegion     <X1 Y1 X2 Y2 [CW CH]>
wrDeleteRegion  <X1 Y1 X2 Y2 [CW CH]>
wrInvertRegion  <X1 Y1 X2 Y2 [CW CH]>

  These functions set, add, delete, or invert the region of the window.  BEFORE
  you add, delete, or invert from a region, you must first set the region with
  wrSetRegion.  The CW and CH parameters are used when the wrSetMode is set to
  rmRoundRect.  If the mode is rmRoundRect, all 6 parameters are REQUIRED.
  
  Ex: $dll(WinRgn.dll, wrSetRegion, 0 0 500 300)
  Ex: $dll(WinRgn.dll, wrDeleteRegion, 10 10 490 290)

-
  
wrSetModePoly <rpmSolid|rpmAlternate>

  Sets the mode when creating polygon regions.  rpmSolid means any overlapping
  areas are filled, regardless of how many times they are overlapped.
  rpmAlternate means overlapping areas are alternated.  Defaults to rpmSolid.

-
  
wrSetRegionPoly     <X1 Y1 X2 Y2 X3 Y3 ... XN YN>
wrAddRegionPoly     <X1 Y1 X2 Y2 X3 Y3 ... XN YN>
wrDeleteRegionPoly  <X1 Y1 X2 Y2 X3 Y3 ... XN YN>
wrInvertRegionPoly  <X1 Y1 X2 Y2 X3 Y3 ... XN YN>

  These functions work much like the previous functions, only they set, add,
  delete, or invert a polygon region composed of points.  You can use up to 256
  points at a time.  If this is not enough points, you can simply add more
  regions.
  
  Ex: $dll(WinRgn.dll, wrSetRegionPoly, 0 0 20 20 50 50)
  Ex: $dll(WinRgn.dll, wrSetRegionPoly, 0 0 10 0 35 50 75 100)

-

wrResetWindow

  Resets the window to its original state.
  
  Ex: $dll(WinRgn.dll, wrResetWindow, NOT_USED)

-
  
wrVersion
  
  Returns version info for the DLL.
  
  Ex: $dll(WinRgn.dll, wrVersion, NOT_USED)

-----

All functions return E_* or S_* depending on whether or not an error occurred.
If you have used Necroman's DLLs, I use the same return values as him, for
consistency and familiarity.  I encourage other DLL writers to do the same.

-----

Here are some examples:


; set to the actual path of your DLL
_winrgn return c:\delphi5\projects\winrgn\WinRgn.dll
winrgn {
  var %result = $dll($_winrgn, $1, $iif($len($2-), $2-, NOT_USED))
  if (E_* iswm %result) {
    echo -a * Error: %result ( $+ $script $+ , line $scriptline $+ )
    halt
  }
}

; /WinRgnTest1
; creates a circular window
WinRgnTest1 {
  ; create a test window
  window -p +d @testwindow 20 20 300 300

  ; set it as the active working window
  winrgn wrSelectWindow $window(@testwindow).hwnd

  ; change the mode to elliptical
  winrgn wrSetMode rmElliptical

  ; set the region; it will be a circle with a
  ; diameter of 300 px
  winrgn wrSetRegion 0 0 300 300
}

; /WinRgnTest2
; creates a rounded rectangular window
; with two smaller circles at the bottom
WinRgnTest2 {
  ; create a test window
  window -p +d @testwindow 20 20 500 300

  ; set it as the active working window
  winrgn wrSelectWindow $window(@testwindow).hwnd

  ; change the mode to rounded rectangle
  winrgn wrSetMode rmRoundRect

  ; set the initial region to 500 200 with a corner
  ; width of 30 and corner height of 30
  winrgn wrSetRegion 0 0 500 200 30 30

  ; change the mode to elliptical
  winrgn wrSetMode rmElliptical

  ; add a circle at the bottom left corner
  ; under the round rectangle
  winrgn wrAddRegion 0 200 100 300

  ; add another circle the bottom right
  ; corner
  winrgn wrAddRegion 400 200 500 300
}

; /WinRgnTest3
; create a star-shaped window
WinRgnTest3 {
  ; create a test window, hidden
  ; hiding the window while performing
  ; operation reduces flicker
  window -ph +d @testwindow 20 20 400 400

  ; fill it with black
  drawrect -f @testwindow 1 1 0 0 400 400

  ; set it as the working window
  winrgn wrSelectWindow $window(@testwindow).hwnd

  ; set the mode to solid
  winrgn wrSetModePoly rpmSolid
  ; if you were to switch the mode, the star
  ; would have its center missing, since the
  ; areas overlap
  ;winrgn wrSetModePoly rpmAlternate

  ; create a star
  winrgn wrSetRegionPoly 200 25 350 400 0 150 400 150 50 400

  ; show the window
  window -wa @testwindow
}

; makes the active window look like a block of swiss cheese (^Andy's example)
; /swiss [num]
; * Note: use "/winrgn wrResetWindow 0" to fix it.
swiss {
  var %w = $active, %n = $iif(($1 isnum),$1,20)
  
  ; select active window
  winrgn wrSelectWindow $window(%w).hwnd
  
  ; change mode to rectangle
  winrgn wrSetMode rmRect
  
  ; set entire region of window
  winrgn wrSetRegion 0 0 $window(%w).w $window(%w).h
  
  ; change mode to elliptical
  winrgn wrSetMode rmElliptical
  while (%n) { 
    var %d = $rand(25,75), %x = $rand(0,$calc($window(%w).w -%d)), %y = $rand(0,$calc($window(%w).h -%d))
    
    ; delete random holes in window
    winrgn wrDeleteRegion %x %y $calc(%x +%d) $calc(%y +%d)
    
    dec %n
  }
}


-----

Extra notes:  Be sure to always set the region of a window before attempting to
add or delete from it, as it may not have the desired effects.

The X2 and Y2 parameters are not width and height, but X and Y coordinates.

The wrMiscFuncs.pas file included with the DLL contains miscellaneous functions
used within the project.  Some are older, some are newer, so that is why they
aren't entirely consistent with the rest of the project.  They were included
rather than including Borland's own SysUtils.pas, which adds considerable size
to the DLL.

IF you have the mode set to rmRoundRect, you MUST use 6 parameters when calling 
wrSet/wrAdd/wrDeleteRegion.  If you do not use 6 parameters, you will get an
error.

IF you are using polygon regions, the number of parameters must be an even
number, otherwise you will get errors.

You MAY mix normal regions and polygon regions.

You may want to unload the dll via /dll -u <file name>, unless you plan on
changing the window continously.  By default, WinRgn.dll does not unload itself
automatically, so that the active window is retained and is available throughout
the session.  Please note that if you do unload the dll with /dll -u, you will
have to use wrSelectWindow to set the window as active again.

If you have any questions, email me at dohcan@mircscripts.org.