Here is an example of a main script that opens a REXX GUI window. The window has two menu items under Twain. Select source... brings up a dialog box listing the various data sources on the computer, so that the user can select one. Acquire... starts the acquire process and downloads one image from the chosen data source. (ie, We pass a 1 to TwainAcquire to accept only 1 image).

The start of the script FuncDefs a couple Windows OS functions we need in order to display a DIB in our GUI window. We call GuiWindowDefaults to enable twain support, then call TwainInit, and finally TwainOpenDSM to open the Data Source manager. The order of these calls is fairly important.

When the user selects the Acquire menu item, we call TwainAcquire.

When the twain device finally signals us that the image is ready to be retrieved, we call TwainGetImage to retrieve it. We tell TwainGetImage to call our subroutine named HandleBitmap. This subroutine calls TwainCreateDIB to get a DIB of the bitmap handle passed by TwainGetImage. Then our subroutine returns a 1 to tell TwainGetImage to free that bitmap handle (now that we have our own DIB of it). We could call TwainSaveDIB here if we wanted to save the image to disk.

Where we draw the bitmap is in our WM_PAINT event handler.

/*
GUIBEGIN
WINDOW , 0, 0, 400, 200, POPUP|CAPTION|SYSMENU|MINBOX|MAXBOX|THICK, , Twain Demo
   FONT 8, 400, MS Shell Dlg
   MENU
DEND

MENU
   HEADING &Twain
      ITEM Ac&quire..., AcquireTwain
      ITEM &Select Source..., PickTwainSource
   <
DEND
GUIEND
*/

LIBRARY rexxgui
NUMERIC DIGITS 10
DO
   FuncDef("BeginPaint","32u,void,void stor","user32")
   FuncDef("EndPaint","32,void,void","user32")

   CATCH FAILURE
      CONDITION("M")
      RETURN
END

/* We want SYNTAX raised for REXX GUI and TWAIN functions. */
GuiErr = "SYNTAX"
GuiHeading = 1
TwainErr = "SYNTAX"
TwainHeading = 1

/* No DIB yet gotten */
DIB = 0

DO
   /* Call GuiWindowDefaults() and indicate we want TWAIN support enabled. You
    * likely would pass other values too if you want extended support, such as
    * your own icon, cursor, HTML support, etc. NOTE: GuiWindowDefaults() must
    * be called BEFORE any windows are open, or any TWAIN functions are called.
    */
   GuiWindowDefaults(, , , , "TWAIN")

   /* Initialize TWAIN support. */
   TwainInit(1 /* USA */, "Twain Demo", 1)

   GuiCreateWindow('NORMAL')

   /* Open the Twain Data Source manager. Tell it to report
    * TWAIN events to our above window.
    */
   TwainOpenDSM(GuiWindow)

   /* We trap SYNTAX just in case any initialization above fails. */
   CATCH SYNTAX
      CONDITION('M')

   /* Close the TWAIN Data Source manager if it was open. NOTE:
    * This is safe to call even if not open.
    */
   TwainCloseDSM()

   /* End the script. */
   RETURN
END

Again:
DO FOREVER

   GuiGetMsg()

   IF EXISTS('GuiObject') == 0 THEN DO
      IF EXISTS('GuiSignal') THEN DO
      END
   END
   ELSE DO
      IF EXISTS('GuiSignal') == 0 THEN DROP (GuiObject)
      ELSE SELECT GuiObject

         /* Was it some Twain event? If so, then GuiObject == 'TWAIN'. NOTE: This
          * implies that you should never create a child window layout with an
          * object name of 'TWAIN' if you're using twain support.
          */
         WHEN 'TWAIN' THEN DO

            /* Is another image (bitmap) ready for us to retrieve from the TWAIN
             * data source?
             */
            IF GuiSignal == 'XFER' THEN DO

               /* Fill in our "BitmapInfo" stem variable with information about
                * the image. This isn't a required step. It's just something
                * that you can do if you want a little more information about
                * the image before you do the TwainGetImage() below.
                */
               TwainGetImageInfo("BitmapInfo")

               /* Fetch the image, and call our subroutine "HandleBitmap" to do
                * something with it. Alternately, we could call TwainAck() to
                * skip this image, or TwainCancel() to cancel the transfer of
                * all remaining images.
                */
               TwainGetImage("HandleBitmap")

               /* Force the window to be redrawn */
               GuiRefresh(, 1)
            END

         END /* TWAIN */

         OTHERWISE
      END
   END

   CATCH SYNTAX
      IF GuiInfo() \== "" THEN DO
         CONDITION('M')
         SIGNAL Again
      END

   FINALLY
      GuiDestroyWindow()
END
RETURN

/* ==================== TwainAcquire() ==================
 * The event handler for the "Twain -> Acquire..." menu
 * item. Reginald calls this when the user selects that
 * item.
 */

AcquireTwain:
   /* Free any DIB we got before. It's OK to call this even if
    * we didn't get a DIB
    */
   TwainFreeDIB(DIB)

   /* Start an Acquire operation. GuiGetMsg() will return as
    * each image is ready for us to TwainGetImage(). NOTE:
    * TwainAcquire() will open whatever data source the user
    * selected via TwainSelectSource() and then close it when
    * we're done with the Acquire operation. We accept only
    * 1 image.
    */
   TwainAcquire(1)
   RETURN

/* ==================== TwainSource() ==================
 * The event handler for the "Twain -> Select source..."
 * menu item. Reginald calls this when the user selects
 * that item.
 */

PickTwainSource:
   /* Present a dialog box listing the names of all the
    * available TWAIN data sources on this computer, and
    * let the user pick one. NOTE: If an error or cancel,
    * SYNTAX is raised.
    */
   TwainSelectSource()
   RETURN

/* ==================== HandleBitmap() ==================
 * Called by TwainGetImage() to pass us the handle to some
 * bitmap of the next acquired image. Here we do whatever
 * we want with the bitmap (ie, save it to disk, display
 * it in a window, etc). Then we return one of the following:
 *
 * 1 =  Free the bitmap.
 * 0 =  Don't free the bitmap (ie, we will take responsibility
 *      for it).
 * No return = Free the bitmap and cancel the acquire operation.
 */

HandleBitmap:
   /* Get a Device Independent Bitmap (DIB) from the passed handle */
   DIB = TwainCreateDIB(ARG(1))

   /* If we wanted to save the image to disk, we could do so. But
    * we need a filename for it. It wouldn't be good to present a
    * file dialog here, right in the middle of an acquire operation,
    * so one alternative would be to create a temporary filename.
    */
   /* TwainSaveDIB(DIB, "C:\MyImage.bmp") */

   /* Let RXTWAIN free the handle now */
   RETURN 1


/* ==================== WM_PAINT() =====================
 * The PAINT event handler for my window. Reginald calls
 * this whenever the window needs to be redrawn.
 */

WM_PAINT:
   /* Erase the background and get a device context */
   hDC = BeginPaint(GuiWindow, ps)

   /* Draw the bitmap */
   TwainDrawDIB(DIB, hDC)

   /* End paint */
   EndPaint(GuiWindow, ps)

   /* Don't let REXX GUI handle this */
   RETURN ""