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.


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,

Asterisks in password

The Progress fill-in widget has a :blank attribute that you can use when creating a password field. But most Windows applications use asterisks instead of blanks.
It's fairly simple to have asterisks (or any other password-character) in Progress too:

  {windows.i}
  DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO.
  RUN SendMessage{&A} IN hpApi (fill-in_password:HWND, 
                                {&EM_SETPASSWORDCHAR}, 
                                ASC("*"),
                                0,
                                OUTPUT ReturnValue).

Explanation


Login

.


Popup windows from HTML Help

The previous topic calling HTML Help described how to call HtmlHelp to show a normal HTML topic. Here is how to use HtmlHelp to show a popup or contexthelp-window.

The declaration for the HtmlHelp function is now slightly different: pszFile is now declared as a LONG parameter because we will have to pass it the NULL value. This is the new declaration:

&GLOBAL-DEFINE HH_DISPLAY_TEXT_POPUP 14
 
PROCEDURE HtmlHelpA EXTERNAL "hhctrl.ocx" PERSISTENT :
   DEFINE INPUT PARAMETER  hwndCaller AS LONG.
   DEFINE INPUT PARAMETER  pszFile    AS LONG.
   DEFINE INPUT PARAMETER  uCommand   AS LONG.
#
Syndicate content