Win32 API samples

This collection of code snippets used to be hosted on www.global-shared.com.
It is an old collection: it all began in 1996 or 1997, when Progress 8 was new and many of us were still using Windows 3.1 !!
Unlike wine or paintings, program code doesn't get better when it ages. You can find fragments that can be improved because Microsoft continuously expands their API, or are outdated because Progress has added features to the ABL so we don't need to use the WIN32 API anymore.


Backgrounds

.


The keyboard: reading and setting toggle states

This example reads the toggle states of the three most commonly used toggle keys: Capslock, Numlock and Insert. The example also changes these three toggle states: you will see the LED's on your keyboard change.
The GetKeyboardState procedure fetches the keystates of 256 keys at once. There's also a GetKeyState procedure to fetch the state for 1 particular key, but there is no SetKeyState procedure for one key so if you need to change a keystate you will have to use SetKeyboadState and set them all.

{windows.i}
 
DEFINE VARIABLE CapsLockToggle AS LOGICAL.
DEFINE VARIABLE NumLockToggle AS LOGICAL.

Disable and re-enable CTRL-ALT-DELETE, ALT-TAB and CTRL-ESC

by Stuart Morris

Usefull when that process really should not be interupted. Note: It can cripple the PC

&GLOBAL-DEFINE A A
&GLOBAL-DEFINE SPI_SCREENSAVERRUNNING 97
 
DEFINE VARIABLE retVal   AS INTEGER NO-UNDO.
DEFINE VARIABLE lv-dummy AS INTEGER NO-UNDO.
 
PROCEDURE SystemParametersInfo{&A} EXTERNAL "USER32.DLL":U :
  DEFINE INPUT  PARAMETER uAction  AS LONG NO-UNDO.
  DEFINE INPUT  PARAMETER uParam   AS LONG NO-UNDO.
  DEFINE INPUT  PARAMETER lpvParam AS LONG NO-UNDO.
  DEFINE INPUT  PARAMETER fuWinIni AS LONG NO-UNDO.
  DEFINE OUTPUT PARAMETER retVal   AS LONG NO-UNDO.

Keyboard

.


Dial a telephone number

The Tapi (Telephony API) can be used to dial a telephone number or pager.
This source is from Johann van der Merwe.
His introduction says:
This is an example of what we use. The code is not cleaned up. We also
use our own dialing properties (for instance a outside line). Hope this
helps. Use MSDN to look up tapiRequestMakeCall for parameter info.

DEFI: DO ON ERROR UNDO, RETURN "ERROR-DEFI":U:
 
  DEFINE INPUT PARAMETER TelNoStr AS CHARACTER NO-UNDO. 
 
  DEFINE VARIABLE GetLine     AS CHARACTER NO-UNDO.
  DEFINE VARIABLE TelNo       AS MEMPTR    NO-UNDO.
  DEFINE VARIABLE i           AS INTEGER   NO-UNDO.

MAPI return codes

By Johann van der Merwe.

 
PROCEDURE MapiReturnCode  :
 
INPUT PARAMETER ResultInt AS INTEGER. /* result from MAPISendMail */
DEFINE VARIABLE RESULT AS CHARACTER NO-UNDO.
 
IF ResultInt <> 0 THEN DO:  /* 0 = Success */ 
   CASE ResultInt:
     WHEN  1 THEN RESULT = "User Abort".
     WHEN  2 THEN RESULT = "Failure".
     WHEN  3 THEN RESULT = "Login Failure".
     WHEN  4 THEN RESULT = "Disk Full".
     WHEN  5 THEN RESULT = "Insufficient Memory".
     WHEN  6 THEN RESULT = "Blk Too Small".
     WHEN  8 THEN RESULT = "Too Many Sessions".
     WHEN  9 THEN RESULT = "Too Many Files".

Using Outlook to send e-mail

There are many ways to send email, smtpmail.p from freeframework.org is known to be very good.
In the past there have been many quesions about Outlook. Here is one code snippet, seen on Peg in an email from John Lubenow (I hope we have permission to use this, if not just delete this topic and let me know please)

/** Send Outlook Mail **/
DEFINE INPUT PARAMETER mailto AS CHARACTER FORMAT "x(30)".
DEFINE INPUT PARAMETER mailcc AS CHARACTER FORMAT "x(30)".
DEFINE INPUT PARAMETER subject AS CHARACTER FORMAT "x(50)".
DEFINE INPUT PARAMETER body AS CHARACTER FORMAT "x(255)".

    DEFINE VARIABLE chOutlook AS COM-HANDLE NO-UNDO.

Interfacing with MAPI (email)

There are different kinds of solutions for using Email from Progress. For example, there are several ActiveX components, there is a Progress 7+8 product with source made by Ketil Parow (you can download a trial version at http:www.sn.no/~ketilp/misc/mapi.zip), you can use the MAPI OLE automation server (there is a document about that on the ActiveX pages on www.dotr.com) or you can use the MAPI through its native API. On this site we'll only discuss the API kind of solutions.
The next sourcecode example was posted by Jeff Ledbetter and was earlier found in Profiles. I ported it to 32-bit.


a MAPI approach with one attachment

This solution is made by Johann van der Merwe.
It allows one attachment.

{windows.i}
 
RUN mapi ( "you@work.com",
           "yourwife@home.com",
           "late for dinner",
           "something came up..",
           "c:\images\flowers.bmp"
          ).
 
 
/* ========================================================================== */
 
PROCEDURE MAPI :
 
DEFINE INPUT PARAMETER OriginName   AS CHARACTER.
DEFINE INPUT PARAMETER RecipName    AS CHARACTER.
DEFINE INPUT PARAMETER Subject      AS CHARACTER.
DEFINE INPUT PARAMETER Bodytext     AS CHARACTER.
DEFINE INPUT PARAMETER FilePathName AS CHARACTER.

eMail

Some articles about how to send, or read e-mail from within Progress


(hexa)decimal values in registry

Suppose there is a registry key

     HKEY_LOCAL_MACHINE\Software\Nerdware\Test

and suppose it contains a DWORD value, named "count".
This source example will read the value of "count", identifies the datatype, and increment the value of "count" by one.

{windows.i} /* March 28, 1998 or later */
 
DEFINE VARIABLE key-hdl        AS INTEGER NO-UNDO.
DEFINE VARIABLE lpBuffer       AS MEMPTR  NO-UNDO.
DEFINE VARIABLE lth            AS INTEGER NO-UNDO.
DEFINE VARIABLE reslt          AS INTEGER NO-UNDO.
DEFINE VARIABLE datatype       AS INTEGER NO-UNDO.             
DEFINE VARIABLE icount         AS INTEGER NO-UNDO.

Enumerating registry values

This example enumerates all values in a given registry key.
In this case, it will return a list of all installed printers (with their names and ports), so it actually does the same as the EnumPrinters function.
As explained in the registry introduction you should prefer to use the EnumPrinters function instead of this RegEnumA stuff, because Microsoft may decide to store the printers info elsewhere in the future, while the EnumPrinters API will be maintained.

{windows.i}  /* March 28, 1998 or later */
 
DEFINE VARIABLE hKey        AS INTEGER NO-UNDO.
DEFINE VARIABLE hPrinterkey AS INTEGER NO-UNDO.

RegCreateKeyEx

Function RegCreateKeyEx creates a registry key and opens it. If the key already exists, the function will just open it.

{windows.i}
 
&SCOPED-DEFINE KEY_ALL_ACCESS 983103
&SCOPED-DEFINE REG_OPTION_NON_VOLATILE 0
&SCOPED-DEFINE REG_OPTION_VOLATILE 1
&SCOPED-DEFINE REG_CREATED_NEW_KEY 1
&SCOPED-DEFINE REG_OPENED_EXISTING_KEY 2                                                 
 
PROCEDURE RegCreateKeyEx{&A} EXTERNAL {&ADVAPI} :
  DEFINE INPUT  PARAMETER hkey                 AS LONG.
  DEFINE INPUT  PARAMETER lpszSubKey           AS CHARACTER.
  DEFINE INPUT  PARAMETER dwReserved           AS LONG.

Registry

There are P4GL functions for setting and getting registry information. I am not familiar with those P4GL functions so it may be silly to use Windows functions instead.

One thing the P4GL can not do is accessing (hexa)decimal data.
Before you try to access the registry directly you should try to find some specialized API call for the requested information type.

For example:

You can read a list of available printers from the registry, but you can also use the EnumPrinters API function for this task. It is generally speaking better to use the API function, because these are documented while the exact registry-locations are not. The EnumPrinters example is only one example. I don't know, but I guess there are documented functions for everything in the registry.


GetUserName

The 'name' field (in a login dialog) can be initialized with the name by which the user is known in Windows.
You can try to find this name in the registry but you better let Windows do it for you, using the GetUserName function.

{windows.i}
 
   DEFINE VARIABLE NAME AS CHARACTER NO-UNDO.
   RUN WinUserName(OUTPUT NAME).
   fill-in_name:SCREEN-VALUE = NAME.
 
PROCEDURE WinUserName :
   DEFINE OUTPUT PARAMETER NAME AS CHARACTER.
 
   DEFINE VARIABLE nr AS INTEGER NO-UNDO INITIAL 100.
   DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO.
   NAME = FILL(" ", nr).
   RUN GetUserName{&A} IN hpApi (INPUT-OUTPUT NAME,
#
Syndicate content