This is a multi-part message in MIME format.
--------------080603000702030103020107
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

In the great tradition of (most) Christmas Presents,
this is one you didn't ask for, you didn't want,
and you will probably never use.

It is a status message / progressbar utility.
A StatusMsg/ProgBar capability is one of the most
serious omissions of wsh/vbs, if not _the_ most
serious omission. Every other scripting language
(that I know of) does have a StatusMsg/ProgBar
capability.

As you know, scripters have not stood idly by and
accepted this deficiency. There are a great number
of StatusMsg/ProgBar utilities already available out
there (and most are offered for free). They are
usually written in vb, but any competent language
could be used.

What is unusual about _THIS_ StatusMsg/ProgBar utility
is that it is written in script. More specifically,
it is written in vbs using api's called by DynaWrap to
create the graphical interface. I know what you're
thinking -- DynaWrap is a 3rd-party control, and
not "pure" script.

I would assert that DynaWrap is "almost pure" script.
Here's the argument. For one, it comes with code,
and so you can reassure yourself that nothing under-
handed is going on. For another, the code was
originally published in the Microsoft Developer's
Journal, and so by implication it bears the imprimature
of Microsoft. DynaWrap is no stranger to the scripting
ng's. It has been mentioned in the scripting ng's for
years (since 1999) and is frequently suggested for use
when somebody wishes to do something outside the realm
of "pure" script. Finally, it is "lite weight". The dll
is only 36kb, and there are no vbRuntimes used. Compared
with (bloated) InternetExplorer, which is the usual
suggestion here for use as a scripting StatusMsg/ProgBar
dialog, DynaWrap is exceedingly "lite weight".

Yes, DynaWrap is lacking in features for use with serious
heavy-duty api's. Most importantly for gui programming,
it is lacking in any typedef capability, and there is no
provision for callbacks. With this in mind, a StatusMsg/
ProgBar utility is about as far as one can go with DynaWrap,
because it is a "dialog" -- but the dialog is only "one-way"
(you are telling the user something, but not allowing him/her
to talk back). It is the "talking-back" part that requires
callbacks. That is, you need to make provisions for the
system send to you notification messages indicating that
the user is interacting with your dialog (buttons were
clicked, etc).

So here it is, for what it's worth. The first attachment
is the StatusMsg/ProgBar utility, wrapped up as a scripting
component in a "wsc" file. You may regester the wsc and
call it from script, or you may also just load it from a
local file. Or, if you don't like dealing with components,
you can just extract the relevant code and stick it directly
into your script. The other attachment is a demo script.
The "boilerplate" below describes how to get DynaWrap,
just in case you don't have it.

cheers, jw


--- <DynaWrap Boilerplate> ---
It is possible to declare-and-call an api from script,
but you must use a third-party control to do so,
or else write one yourself.

It has already been correctly pointed out that there
is no api-capability in "pure" script.

If you are willing to use a third-party control, then
one such control, called "DynaWrap", can be found on
Guenter Born's website (note: Guenter refers to it as
"DynaCall"). Here is the link to it:

http://people.freenet.de/gborn/WSHBazaar/WSHDynaCall.htm

On that page you will find a download for the control,
plus some code samples.

Note: you may find additional sample code by searching
the archives of the wsh and vbscript ng's.

Note also: DynaWrap does have its limitations. There are
certain things it can't do. For example, you can't call
api's which take typedefs as parameters, and you can't call
api's "by ordinal". But it will work for most of the
"usual suspects".

And finally, DynaWrap doesn't work entirely as advertised.
For example, it is supposed to allow for the declaration of
several api definitions in one instance of itself. I could
never get that to work (in win9x). You will need a new
instance of DynaWrap for every api, or else re-instantiate
the object for every api. Someday I'm going to learn enough
c++ to fix that...
--- </DynaWrap Boilerplate> ---


--------------080603000702030103020107
Content-Type: text/plain;
name="StatusMsgProgBarDialog.wsc.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="StatusMsgProgBarDialog.wsc.txt"

<?xml version="1.0"?>
<component>

<?component error="true" debug="true"?>

<registration
description="StatusMsgProgBarDialog"
progid="StatusMsgProgBarDialog.WSC"
version="1.00"
classid="{e3638360-6d72-11da-a061-d0265bc1a60b}"
>
</registration>

<public>
<property name="pbBackColor">
<get/>
<put/>
</property>
<property name="pbForeColor">
<get/>
<put/>
</property>
<property name="titlebarCaption">
<get/>
<put/>
</property>
<property name="txtStatusMessage">
<get/>
<put/>
</property>
<property name="iPctComplete">
<get/>
<put/>
</property>
<method name="Create_ProgbarDialog">
<PARAMETER name="sCaption"/>
</method>
<method name="PostStatusAndPct">
<PARAMETER name="sStatusMsg"/>
<PARAMETER name="iPct"/>
</method>
<method name="CloseDialog">
</method>
</public>

<script language="VBScript">
<![CDATA[
Option Explicit
'
' --- description block --------------------------
' Title: A Status Message / Progressbar Utility...
'
' Description: O.K., so there are plenty of these dialogs around,
' but it was in intriguing challenge to program this
' with DynaWrap...
'
' Author: mr_unreliable
'
' Usage: Use at you own risk, tested on win98se...
'
' --- revision history ---------------------------
' 10Dec05: original attempt, using the wshATO "MakeWindow" script as inspiration...
' 11Dec05: couldn't get valid instance handle for THIS script, and so using
' the desktop instance handle, for now. (Maybe inspiration will strike later)...
' 11Dec05: in an attempt to get color into the progbar, used "SetTextColor" but
' that didn't work(?). So, used "DrawText" to draw the text (i.e., the blocks)
' to the textbox, but that apparently draws "on" the box, not "in" the box,
' that is, the image doesn't "persist" (ugh!)...
' 12Dec05: changing approach to using a static control, and inserting a bitmap
' image (i.e., a "rectangle" drawn in to resemble a progbar)...
' 14Dec05: redraw the bitmap "every time" (rather than attempting to retain/modify it)...
' 15Dec05: move the status msg / progbar dialog code to a "wsc" component,
' for the "usual reasons", i.e., "packaging"...
' --- end of description block -------------------
'
' --- global variables ---------------------------
Dim oDW ' as object (instantiated later)...
Dim m_hWndDlg, m_hStatic, m_hProgbar ' as long(s) (handles)
Dim m_hFontMsg, m_hFontLogo ' as font handle(s)
Dim m_hInstance ' as instance handle

Dim wdDlg : wdDlg = 440
Dim htDlg : htDlg = 115
Dim wdProgbar, htProgbar ' as long
'
Dim hDCProgbar, hDCPBSave ' as long
Dim hBmp : hBmp = 0 : Dim hDCMem : hDCMem = 0 ' as handles to system objects
Dim hBackPen, hBackBrush ' as long (handles)
Dim hBarPen, hBarBrush ' as long (handles)
'
Dim pbBackColor : pbBackColor = "&HFFFFFF" ' white
Dim pbForeColor : pbForeColor = "&HFF0000" ' blue
Dim titlebarCaption : titlebarCaption = " StatusMsg / ProgressBar Dialog "
Dim txtStatusMessage: txtStatusMessage = " StatusMsg goes here... "
Dim iPctComplete : iPctComplete = 0

' system constants (oops, can't use constants here -- FOR SHAME MICROSOFT!!!)
Dim SW_HIDE : SW_HIDE = 0 ' showwindow constants
Dim SW_SHOW : SW_SHOW = 5
Dim FW_NORMAL : FW_NORMAL = 400 ' 100=Light, 400=Normal, 700=Bold, 900=Heavy
Dim FW_BOLD : FW_BOLD = 700
'
Dim nRtn ' as long (hold api return value)
' --- End of declarations and constants ----------

Public Function get_pbBackColor()
get_pbBackColor = pbBackColor
End function

Public Function put_pbBackColor(crNew)
pbBackColor = crNew
End function

Public Function get_pbForeColor()
get_pbForeColor = pbForeColor
End function

Public Function put_pbForeColor(crNew)
pbForeColor = crNew
End function

Public Function get_titlebarCaption()
get_titlebarCaption = titlebarCaption
End function

Public Function put_titlebarCaption(sNewCaption)
titlebarCaption = sNewCaption

' todo: add code to insert this caption into the titlebar...
End function

Public Function get_txtStatusMessage()
get_txtStatusMessage = txtStatusMessage
End function

Public Function put_txtStatusMessage(sNewMsg)
txtStatusMessage = sNewMsg

' stick the new status message into the static control...
Call SetWindowText(m_hStatic, txtStatusMessage)

Call UpdateWindow(m_hWndDlg) ' otherwise known as: form.refresh

End function

Public Function get_iPctComplete()
get_iPctComplete = iPctComplete
End function

Public Function put_iPctComplete(iNewPctComp)
iPctComplete = iNewPctComp

Call RepaintProgBar(iPctComplete) ' update progbar...

Call UpdateWindow(m_hWndDlg) ' otherwise known as: form.refresh

End function


' --- CREATE PROGBAR DIALOG ----------------------

Public Function Create_ProgbarDialog(sCaption, pxLeft, pxTop)
' MsgBox(sCaption)

Dim hWndDlg, hLogo ' as long(s) handles
Dim dwStyle, dwExStyle ' as long
'
Const WS_VISIBLE = &H10000000 ' window style bits
Const WS_CAPTION = &HC00000 ' WS_BORDER Or WS_DLGFRAME
Const WS_POPUP = &H80000000
Const WS_CHILD = &H40000000
'
Const WS_EX_NOPARENTNOTIFY = &H4
Const WS_EX_CLIENTEDGE = &H200
'
Const SS_BITMAP = &H0000000E ' static control style bits
'
Const WM_SETFONT = &H30
'
Const PS_SOLID = 0 ' pen style
'
Const SWP_NOMOVE = &H2
Const SWP_NOZORDER = &H4
Const SWP_NOSIZE = &H1
Const SWP_SHOWWINDOW = &H40
Const HWND_TOPMOST = -1
'
Dim swpFlags ' as long
' --- end of declarations and constants ----------

titlebarCaption = sCaption

' get an instance handle for THIS instance of wscript (tricky)...
m_hInstance = GetInstanceHandle()

dwStyle = WS_POPUP Or WS_CAPTION
dwExStyle = WS_EX_NOPARENTNOTIFY

' ----------------------------------------------
' note: typically, one would set up a window class of one's own, so as to
' be able to define the look-and-feel of the window. That is, the icon
' the cursor, the background/text colors, etc. But more importantly,
' you also supply a wndproc address, i.e., a routine to process messages
' coming from the window (i.e., to detect "events").
' But that requires a typedef, and a wndproc, things that are way
' beyond the capabilities of DynaWrap. And so, we will attempt to
' get by with a "system standard" window class, namely: "#32770"...
' That is the standard "dialog class", and as such there is a "default
' wndproc" built into the system, which will handle the minimal functions
' expected of a window. (Good Luck!)...
' ----------------------------------------------
hWndDlg = CreateWindowEx(0, "#32770", titlebarCaption, dwStyle, _
pxLeft,pxTop, wdDlg,htDlg, 0, 0, m_hInstance, 0) ' was CStr(m_sWndClass)
' ----------------------------------------------

' add some (child) controls to the window (note: static = label)...
m_hStatic = CreateWindowEx(0, "Static", "Script Status Messages go here.. ", _
WS_CHILD Or WS_VISIBLE, 20, 5, wdDlg - 20, 20, hWndDlg, 0, m_hInstance, 0)

' create the "progbar" window (i.e., using a "static" showing a bitmap)...
wdProgbar = wdDlg - 25 - 6 : htProgbar = 22
m_hProgbar = CreateWindowEx(WS_EX_CLIENTEDGE, "Static", "", _
WS_CHILD Or WS_VISIBLE Or SS_BITMAP , 10, 35, wdProgbar, htProgbar, hWndDlg, 0, m_hInstance, 0)

hLogo = CreateWindowEx(0, "Static", "brought to you by jawar productions (all rights reserved)... ", _
WS_CHILD Or WS_VISIBLE, wdDlg - 290, 75, 380, 25, hWndDlg, 0, m_hInstance, 0)


' (note: should probably go get these colors from sysinfo)...
hBackPen = CreatePen(PS_SOLID, 1, pbBackColor) ' C0C0C0) ' msGray
hBackBrush = CreateSolidBrush(pbBackColor) ' C0C0C0) ' aka, Silver

hBarPen = CreatePen(PS_SOLID, 1, pbForeColor) ' crBlue)
hBarBrush = CreateSolidBrush(pbForeColor) ' crBlue)

Call RepaintProgBar(0) ' paint in background...

' create fonts (otherwise the default fonts for this system will be used)...
m_hFontMsg = GetFontHandle("MS Sans Serif", 10, 0, FW_BOLD, False)
m_hFontLogo = GetFontHandle("Arial", 7, 0, FW_NORMAL, True) ' aspect ratio = 0 is default

' now, set prepared fonts into their respective controls.
Call SendMessage(m_hStatic, WM_SETFONT, m_hFontMsg, 0)
Call SendMessage(hLogo, WM_SETFONT, m_hFontLogo, 0)

' Call ShowWindow(hWndDlg, SW_SHOW) ' show the window here...
' msgbox("ck static")

' show the window here, and attempt to push it to the front...
swpFlags = SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE
Call SetWindowPos(hWndDlg, HWND_TOPMOST, 0, 0, 0, 0, swpFlags)

' note: this "ought not" to be necessary, but without it the logo
' seems to be reluctant to initially appear (paint itself)???
Call UpdateWindow(hWndDlg) ' otherwise known as: form.refresh

Create_ProgbarDialog = hWndDlg ' return value (window handle)

End Function


' --- POST STATUS MSG _AND_ PCT COMPLETE ---------

Public Function PostStatusAndPct(sNewMsg, iNewPctComp)
txtStatusMessage = sNewMsg
iPctComplete = iNewPctComp

' stick the new status message into the static control...
Call SetWindowText(m_hStatic, txtStatusMessage)

Call RepaintProgBar(iPctComplete) ' update progbar...

Call UpdateWindow(m_hWndDlg) ' otherwise known as: form.refresh

End function


' --- CLOSE DIALOG -------------------------------

Public Function CloseDialog()

Call ShowWindow(m_hWndDlg, SW_HIDE) ' hide the window, before messing around...

' nota bene: if you save/restore the COMPLETE device context, then
' you don't need to put the dc back the way it was before exiting...
' clean-up gdi system objects...
Call RestoreDC(hDCProgbar, hDCPBSave) ' return progbar DC to original state

Call DestroyWindow(m_hWndDlg)

' release "system objects" (we do our bit to help prevent "memory leaks")...
Call DeleteObject(hBmp)

Call DeleteObject(hBackPen) ' return system object(s)
Call DeleteObject(hBackBrush)

Call DeleteObject(hBarPen) ' return system object(s)
Call DeleteObject(hBarBrush)

Call DeleteObject(m_hFontMsg)
Call DeleteObject(m_hFontLogo)

End Function


' ================================================
' PRIVATE (INTERNAL) FUNCTIONS, (from here on out)
' ================================================

' --- REPAINT PROGBAR ----------------------------

Private Function RepaintProgBar(iPct)
Const STM_SETIMAGE = &H172 ' winuser.h
Const IMAGE_BITMAP = 0

' ==============================================
' Discussion: dealing with the problem of "persistance". You can get a reference
' to the device context of a static control, set the fore/back colors and then
' draw shapes or text on it, and it looks ok. BUT what is happening is that
' you are drawing on the screen. You can see what you draw, at least when
' you draw it -- but if your window gets hidden and then re-appears that drawing
' will have disappeared. In geek-speak, your image didn't "persist".
'
' In vb, that "persistance" issue is auto-magically taken care of for you.
' VB intercepts any system messages telling you to re-draw the control, and
' does it. However, in this case we are "flying-without-the-net", i.e., we
' are relying on the "default wndproc's" because we can't setup a callback
' wndproc for our window with dynawrap.
'
' And so, we are going to have to take other measures to insure that we get
' "persistance" of the progbar graphics. We are going to use "brute force".
' That is, we are going to make up a "memory bitmap" with the graphics we want,
' and then insert the bitmap into an appropriately-styled static control,
' which will then take over and resolutely display the graphics "come-what-may"...
' ==============================================

' get device context (of the progbar/static control)...
hDCProgbar = GetDC(m_hProgbar)
' save existing device context of control, before messing around (DA, pg 490)...
hDCPBSave = SaveDC(hDCProgbar)

Dim hNewBmp
' create a bitmap (compatible with the display), in memory...
hNewBmp = CreateCompatibleBitmap(hDCProgbar, wdProgbar, htProgbar)
BugAssert (hNewBmp <> 0), " could not create compatible bitmap"

' then create a "memory device" compatible DC...
hDCMem = CreateCompatibleDC(hDCProgbar)
BugAssert (hDCMem <> 0), " could not create compatible dc"

' select the new bitmap, pen and brush objects into the (memory) device context...
Dim hPrevBmp, hPrevPen, hPrevBrush ' as long
hPrevBmp = SelectObject(hDCMem, hNewBmp)
hPrevPen = SelectObject(hDCMem, hBackPen) ' select pen into DC...
hPrevBrush = SelectObject(hDCMem, hBackBrush)

' clean up (erase) the memory bitmap, by painting in a rectangle with the
' background (msGray) color. This is being done because the progressbar bar
' doesn't initially fill up the static control...
' Windows draws the outline of the figure with the current pen selected,
' and the figure is filled with the current brush selected (CP 558)...
nRtn = Rectangle(hDCMem, 0,0, wdProgbar, htProgbar)
BugAssert (nRtn <> 0), " .. Rectangle returned an error"

' --- draw in the progbar, if any --------------
If (iPct > 0) then
' change pens (to draw color portion)...
hPrevPen = SelectObject(hDCMem, hBarPen) ' select pen into DC...
hPrevBrush = SelectObject(hDCMem, hBarBrush)

' calculate the length of the progbar. Let 100pct be (wdProgbar - 2).
' then, the length is iPct/100 * (wdProgbar - 2)...
Dim pxProgbar : pxProgbar = iPct/100 * (wdProgbar - 2)
nRtn = Rectangle(hDCMem, 2,2, pxProgbar, htProgbar - 1) ' allowance for frame
BugAssert (nRtn <> 0), " .. Rectangle returned an error"
End If ' test iPct
' --- finished with drawing the progbar --------

' set bitmap image into the static control...
nRtn = SendMessage(m_hProgbar, STM_SETIMAGE, IMAGE_BITMAP, hNewBmp)

' cleanup time...
Call SelectObject(hDCMem, hPrevBmp) ' probably not necessary (see RestoreDC)
if (hBmp <> 0) then Call DeleteObject(hBmp) ' release old bitmap...
hBmp = hNewBmp ' preserve this (new) bitmap, while it's being displayed

' finished drawing, restore device context, release system resources...
Call RestoreDC(hDCMem, hDCPBSave) ' note PB DC same as original hDCMem(?)
Call DeleteDC(hDCMem)
Call ReleaseDC(m_hProgbar, hDCProgbar)
' ==============================================

' Call UpdateWindow(m_hWndDlg) ' otherwise known as: form.refresh

End Function



' --- GET INSTANCE HANDLE (of Desktop -- cheat, cheat) ---

Private Function GetInstanceHandle()
' Dim hInstance

' Discussion: getting an instance handle with vb is easy, as there is
' an already defined hInstance property of the vbApp object.
' Unfortunately, wscript doesn't provide this, so we will have to
' go get it using "brute force" (i.e., go get it the hard way).
' That involves some tricky-dicky stuff. First, we are going to
' have to find wscript's "hidden window" (yes Dorothy, there _IS_
' a wscript window -- how do you think wscript communicates with
' the system, eh?). Assuming we can find that hidden window, then
' we can use that go get our hInstance, using gwl_hInstance which
' gets the instance handle for a window...
' --- end of discussion --------------------------

' get an instance handle (from vbApp object, for now),
' but that's not a "pure" DynaWrap play...
' hInstance = oATO.vbApp.hInstance ' requires wshATO, verboten here...

' More Discussion: had to temporarily give up on getting the hInstance
' for THIS script. Enumming the "thread windows" would have found it
' directly, but that requires a "callback routine" which can't be done in
' script without using something with more capabilities than DynaWrap.
' Another approach would be enumming ALL the desktop windows, which would
' work with DynaWrap, using getDesktop window and then GetNextWindow on
' down the chain, but then, if you have more than one wscript instance
' running, how do you detect which one is yours??? (Maybe comparing
' command lines would work -- if one could guarantee a unique command line)...
'
' And so for now, we will be using the "desktop instance", which is easy
' to get. (Caveat Emptor: if your window uses the wscript instance, then
' the window auto-magically goes away when your script terminates.
' But, if you use the "desktop instance" then you better make sure that
' you kill the window BEFORE you close, or the window is most likely to
' hang around forever). Yes, yes, I know, it's ugly...
' --- end of discussion (part2) ------------------

Dim hDesktop ' as long (handle)
Const GWL_HINSTANCE = (-6)
Dim hDeskInstance ' as long (handle)

hDesktop = GetDesktopWindow()
hDeskInstance = GetWindowLong(hDesktop, GWL_HINSTANCE)

GetInstanceHandle = hDeskInstance ' hInstance ' return result
End Function


' --- GET FONT HANDLE ----------------------------

Private Function GetFontHandle(sFontName, ptSiz, AspectRatio, fntWeight, vItalic)
Dim hFont ' as font handle
' font-related constants, (note: the "weight constants defined globally)...
' Const FW_NORMAL = 400 ' 100=Light, 400=Normal, 700=Bold, 900=Heavy
' Const FW_BOLD = 700
'
Const DEFAULT_ASPECTRATIO = 0
Const DEFAULT_CHARSET = 1
Const OUT_DEFAULT_PRECIS = 0
Const CLIP_DEFAULT_PRECIS = 0
Const DEFAULT_QUALITY = 0
Const DEFAULT_PITCH = 0
Const FF_DONTCARE = 0
'
Const LOGPIXELSY = 90 ' Logical pixels/inch in Y
' --- end of declarations and constants ----------

' Make it negative, so as to apply to "glyph", rather than "cell".
' Dim cf_PtSize : cf_PtSize = - CSng(GetDeviceCaps(GetDC(hWndDlg), LOGPIXELSY) / 72)
' forget the api's for now, just plug it in...
Dim cf_PtSize : cf_PtSize = - CSng(96 / 72) ' micron crt logpixelsy = 96
' --- finished with font conversion factor -----

Dim htFont, wdFont ' as long
htFont = Int(ptSiz * cf_PtSize)
wdFont = Int((ptSiz * cf_PtSize) * AspectRatio) ' was DEFAULT_ASPECTRATIO

' convert vbScript boolean to system true/false...
Dim bItalic ' as system t/f
If vItalic then
bItalic = 1 ' system true, i.e., want it as italic
Else
bItalic = 0 ' system false, i.e. not italic (regular)
End If

hFont = CreateFont(htFont, wdFont, 0, 0, fntWeight, bItalic, _
0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, _
DEFAULT_QUALITY, DEFAULT_PITCH Or FF_DONTCARE, sFontName)

GetFontHandle = hFont
End Function



' ================================================
' ================================================
' === "WRAPPERS" FOR API CALLS (DynaWrap style) ==
'
' the DynaWrap doc is rather inscrutable, but as best I can make out,
' DynaWrap can only accomodate ONE api declaration at a time.
' (If I'm wrong, maybe you experts can straighten me out on this).
'
' Assuming that my one-at-a-time hypothesis is correct,
' then one has two choices:
' - you need to set up a separate obj for EVERY api (ugh!), or
' - declare the api's to be used (one-at-a-time) as you go,
' which is what you see here (yes, it's "ugly")...

' ----------------------------------------------
' the DynaWrap parameters are:
' i => the number and data type of the function's parameters
' f => type of call _stdcall or _cdecl.
' (Default to _stdcall. If that doesn't work use _cdecl).
' r => return data type.

' the data type declarations are:
' c => VT_I4: c signed char
' d => VT_R8: d 8 byte real
' f => VT_R4: f 4 byte real
' h => VT_I4: h HANDLE
' l => VT_I4: l long
' p => VT_PTR: p pointer
' s => VT_LPSTR: s string
' t => VT_I2: t short
' u => VT_UINT: u unsigned int
' w => VT_LPWSTR: w wide string
' r => VT_BYREF: (pass by reference) for strings only.
'
' the call type declarations are:
' s => _stdcall (standard vb-type call)
' => _cdecl (c++ type call)
' ----------------------------------------------

' ================================================
' ================================================



Private Function CreateWindowEx(dwExStyle, sClassName, sWindowName, dwStyle, dwLeft,dwTop, _
dwWidth,dwHeight, hWndParent, hMenu, hInstance, lpParam)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "CreateWindowExA", "i=lsslllllllll", "f=s", "r=h"
CreateWindowEx = oDW.CreateWindowExA(CLng(dwExStyle), CStr(sClassName), CStr(sWindowName), _
CLng(dwStyle), CLng(dwLeft),CLng(dwTop), CLng(dwWidth),CLng(dwHeight), _
CLng(hWndParent), CLng(hMenu), CLng(hInstance), CLng(lpParam))
End Function


' Declare Function CreatePen Lib "gdi32" Alias "CreatePen" _
' (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long

Private Function CreatePen(nPenStyle, nWidth, crColor)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "CreatePen", "i=lll", "f=s", "r=l"
CreatePen = oDW.CreatePen(CLng(nPenStyle), CLng(nWidth), CLng(crColor))
End Function

' Declare Function CreateSolidBrush Lib "gdi32" Alias "CreateSolidBrush" _
' (ByVal crColor As Long) As Long

Private Function CreateSolidBrush(crColor)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "CreateSolidBrush", "i=l", "f=s", "r=l"
CreateSolidBrush = oDW.CreateSolidBrush(CLng(crColor))
End Function

' Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
' (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Function SendMessage(hWnd, wMsg, wParam, lParam)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "SendMessageA", "i=llll", "f=s", "r=l"
SendMessage = oDW.SendMessageA(CLng(hWnd), CLng(wMsg), CLng(wParam), CLng(lParam))
End Function

' Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" _
' (ByVal hWnd As Long, ByVal lpString As String) As Long

Private Function SetWindowText(hWnd, lpString)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "SetWindowText", "i=ls", "f=s", "r=l"
SetWindowText = oDW.SetWindowText(CLng(hWnd), CStr(lpString))
End Function

' Declare Function ShowWindow Lib "user32" Alias "ShowWindow" _
' (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

Private Function ShowWindow(hWnd, nCmdShow)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "ShowWindow", "i=ll", "f=s", "r=l"
ShowWindow = oDW.ShowWindow(CLng(hWnd), CLng(nCmdShow))
End Function

' Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" _
' (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, _
' ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Function SetWindowPos(hWnd, hWndInsertAfter, x,y, cx,cy, wFlags)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "SetWindowPos", "i=lllllll", "f=s", "r=l"
SetWindowPos = oDW.SetWindowPos(CLng(hWnd), CLng(hWndInsertAfter), _
CLng(x), CLng(y), CLng(cx), CLng(cy), CLng(wFlags))
End Function

' Declare Function UpdateWindow Lib "user32" Alias "UpdateWindow" _
' (ByVal hWnd As Long) As Long

Private Function UpdateWindow(hWnd)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "UpdateWindow", "i=l", "f=s", "r=l"
UpdateWindow = oDW.UpdateWindow(CLng(hWnd))
End Function

' Declare Function DeleteObject Lib "gdi32" Alias "DeleteObject" _
' (ByVal hObject As Long) As Long

Function DeleteObject(hObject)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "DeleteObject", "i=l", "f=s", "r=l"
DeleteObject = oDW.DeleteObject(CLng(hObject))
End Function

' Declare Function DestroyWindow Lib "user32" Alias "DestroyWindow" _
' (ByVal hWnd As Long) As Long

Function DestroyWindow(hWnd)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "DestroyWindow", "i=l", "f=s", "r=l"
DestroyWindow = oDW.DestroyWindow(CLng(hWnd))
End Function

' Declare Function GetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Long

Private Function GetDesktopWindow()
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "GetDesktopWindow", "f=s", "r=h" ' no inputs
GetDesktopWindow = oDW.GetDesktopWindow()
End Function


Private Function GetWindowLong(hWnd, nIndex)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "GetWindowLong", "i=ll", "f=s", "r=l"
GetWindowLong = oDW.GetWindowLong(CLng(hWnd), CLng(nIndex))
End Function

' Declare Function GetDC Lib "user32" Alias "GetDC" (ByVal hWnd As Long) As Long

Private Function GetDC(hWnd)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "USER32.DLL", "GetDC", "i=l", "f=s", "r=l"
GetDC = oDW.GetDC(CLng(hWnd))
End Function

' Declare Function SaveDC Lib "gdi32" Alias "SaveDC" (ByVal hDC As Long) As Long

Private Function SaveDC(hDC)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "SaveDC", "i=l", "f=s", "r=l"
SaveDC = oDW.SaveDC(CLng(hDC))
End Function

' Declare Function CreateCompatibleBitmap Lib "gdi32" Alias "CreateCompatibleBitmap" _
' (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long

Private Function CreateCompatibleBitmap(hDC, nWidth, nHeight)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "CreateCompatibleBitmap", "i=lll", "f=s", "r=h"
CreateCompatibleBitmap = oDW.CreateCompatibleBitmap(CLng(hDC), CLng(nWidth), CLng(nHeight))
End Function

' Declare Function CreateCompatibleDC Lib "gdi32" Alias "CreateCompatibleDC" _
' (ByVal hDC As Long) As Long

Private Function CreateCompatibleDC(hDC)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "CreateCompatibleDC", "i=l", "f=s", "r=l"
CreateCompatibleDC = oDW.CreateCompatibleDC(CLng(hDC))
End Function

' Declare Function CreatePen Lib "gdi32" Alias "CreatePen" _
' (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long

Private Function CreatePen(nPenStyle, nWidth, crColor)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "CreatePen", "i=lll", "f=s", "r=l"
CreatePen = oDW.CreatePen(CLng(nPenStyle), CLng(nWidth), CLng(crColor))
End Function

' Declare Function CreateSolidBrush Lib "gdi32" Alias "CreateSolidBrush" _
' (ByVal crColor As Long) As Long

Private Function CreateSolidBrush(crColor)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("DynamicWrapper") ' start over...
' register (declare) this flavor of api call...
oDW.Register "GDI32.DLL", "CreateSolidBrush", "i=l", "f=s", "r=l"
CreateSolidBrush = oDW.CreateSolidBrush(CLng(crColor))
End Function

' Declare Function SelectObject Lib "gdi32" Alias "SelectObject" _
' (ByVal hDC As Long, ByVal hObject As Long) As Long

Private Function SelectObject(hDC, hObject)
Set oDW = nothing ' clear any previous instance
Set oDW = CreateObject("