Wintertree Software Inc.

Sentry Spelling Checker Engine - Support

Home Site index Contact us Catalog Shopping Cart Products Support Search

You are here: Home > Support > Sentry Spelling Checker Engine > Using Sentry Windows SDK with PowerBuilder


Using Sentry Windows SDK with PowerBuilder

Product: Sentry Spelling Checker Engine Windows SDK

The following information may help customers who need to integrate Sentry Spelling Checker Engine into a PowerBuilder application.

Contents:

Function declarations

Sentry API functions documented in the Sentry Programmer's Guide are shown in C/C++ syntax. The following table shows how to translate C/C++ data types into PowerBuilder data types:

C/C++ type Type description C/C++ example Equivalent PowerBuilder type PowerBuilder Example
char * String, or more accurately, pointer to an array of characters char *fileName ref String ref String fileName
SSCE_CHAR * String, or more accurately, pointer to an array of Latin-1 characters
(i.e., text being spell-checked)
SSCE_CHAR *errWord ref String ref String errWord
SSCE_S16 Signed, 16-bit integer SSCE_S16 blkId integer integer blkId
SSCE_S16 * Pointer to a signed, 16-bit integer
("pointer" meaning "pass by reference")
SSCE_S16 *format ref integer ref integer format
SSCE_S32 Signed, 32-bit integer SSCE_S32 strLen long long strLen
SSCE_S32 * Pointer to a signed, 32-bit integer
("pointer" meaning "pass by reference")
SSCE_S32 *cursor ref long ref long cursor
SSCE_U16 Unsigned, 16-bit integer SSCE_U16 fileNameSz integer integer fileNameSz
HWND Window handle HWND parentWin ulong ulong parentWin
HINSTANCE Instance handle HINSTANCE clientInst ulong ulong clientInst

For pointer-type parameters (denoted by "*", as in SSCE_CHAR *str) the keyword "const" indicates that the parameter is passed by reference but will not be modified by the called function. If "const" is missing, the parameter is either an output parameter (meaning it is modified to by the called function) or an input/output parameter (meaning its value is read by the called function and may be modified by the called function). PowerBuilder has no equivalent, so the "const" keyword can be omitted, but you should be aware of its meaning.

Following are some example function declarations:

(Note that references to SSCE5532.DLL should be changed to the name of the Sentry DLL included with your version of the Sentry Windows SDK.)

NOTE: The PowerBuilder API function definitions must be configured to pass ANSI (single-byte) strings to the Sentry DLL, by including the ";ANSI" in the "ALIAS FOR" parameter. Passing Unicode strings to Sentry will not work. (It will typically appear like every block of text is one character long.)

About the Sentry license key (Version 5.15 and earlier)

In Sentry Windows SDK version 5.15 and earlier, the license key is provided as a hexadecimal constant. Unfortunately, PowerBuilder lacks a means for expressing hexadecimal constants, so the license key must be converted to decimal before it can be passed to the SSCE_SetKey function. Convert your license key from hexadecimal to decimal using a hex-capable calculator (if you don't have one, use the Windows calculator in "Scientific" mode). For example, 1234ABCD hexadecimal is 305441741 decimal. If the hexadecimal key begins with 8, 9, A, B, C, D, E or F, convert it to a negative decimal number by subracting 4294967296 (decimal) after converting your key to decimal. For example, if your key is ABCD1234 hexadecimal, convert it to decimal: 2882343476. Because the key starts with "A," subtract 4294967296: -1412623820.

Note that in Sentry Windows SDK 5.16 and later, the license key is provided as a long decimal integer, so conversion is not necessary. Pass the key provided by Wintertree Software to the SSCE_SetKey function as-is.

Interactively checking text in a DataWindow

PowerBuilder Datawindows cannot be accessed directly by Sentry, since they are internal PB constructs that don't provide a handle and message processing abilities expected by Sentry. To spell check the content of a DataWindow, you need to extract the text at the PowerBuilder level, then using an event handler with code similar to that shown above for MLE controls, call SSCE_CheckBlockDlg to check the extracted text. When the corrected text is returned after being processed by the enduser, use the corrected text to replace the text in the Datawindow.

Interactively checking text in a multi-line edit control

To check spelling of the text in a multi-line edit (MLE) control (myMLE in this example):

First, declare the following local (or global) external functions:

Function integer SSCE_SetKey(long key) Library "SSCE5532.DLL"
Function integer SSCE_CheckCtrlDlg(ulong parentWin, ulong ctrlWin, integer selectedOnly) library "SSCE5532.DLL" Alias for "SSCE_CheckCtrlDlg;ANSI"

Next, insert statements similar to the following in an event handler (e.g., in response to a menu selection or button press:

   ulong ull_key = 305441741  /* Sentry license key converted to decimal */
long ll_rc
ll_rc = SSCE_SetKey(ull_key)
ll_rc = SSCE_CheckCtrlDlg(Handle(This), Handle(myMLE), 0)

Invoke the event handler to which you added the call to SSCE_CheckCtrlDlg. You should see the spelling-checker dialog box.

Interactively checking text in a Rich Text Edit control

Checking a Rich Text Edit (RTE) control is the same as for a MLE (see above), except for some extra steps required to get the correct handle value for the control. In PowerBuilder, using Handle(rte) actually gets you a handle to a higher-level PowerBuilder "wrapper" around the actual RTE control. So to get the RTE handle for use with Sentry requires some additional steps.

First, declare the following local (or global) external functions:

Protected Function ulong FindWindowEx(ulong hwndParent, ulong hwndChildAfter, string lpszClass, long lpszWindow) Library "user32.dll" ALIAS FOR "FindWindowExW"

Then, for versions before PowerBuilder 2021, insert statements similar to the following in an event handler (or better, create a local function)

   ulong hWin_wrapper
   ulong hWin_control

   hWin_wrapper = Handle( RTEcontrol )
   IF hWin_wrapper > 0 THEN
    hWin_wrapper = FindWindowEx(hWin_wrapper,0, "PBTxTextControl", 0)
	IF hWin_wrapper > 0 THEN
     hWin_wrapper = FindWindowEx(hWin_wrapper,0, "AfxOleControl42u", 0)
     IF hWin_wrapper > 0 THEN
      hWin_control = FindWindowEx(hWin_wrapper,0, "TX16P", 0)
      IF hWin_control = 0 THEN
       hWin_control = FindWindowEx(hWin_wrapper,0, "TX15P", 0)
       IF hWin_control = 0 THEN
        hWin_control = FindWindowEx(hWin_wrapper,0, "TX14P", 0)
        IF hWin_control = 0 THEN
         hWin_control = FindWindowEx(hWin_wrapper,0, "TX13P", 0)
         IF hWin_control = 0 THEN
          hWin_control = FindWindowEx(hWin_wrapper,0, "TX12P", 0)
          IF hWin_control = 0 THEN
           hWin_control = FindWindowEx(hWin_wrapper,0, "TX11P", 0)
          END IF
         END IF
        END IF
       END IF
      END IF
     END IF
    END IF
   END IF
   

Different versions of PowerBuilder use different versions of the RTE control with different TXnnP class names. You can use tools such an WinSpy or Windows Inspector (a highly recommended free tool from Binary Fortress–https://www.binaryfortress.com/WindowInspector/) to find the specific classnames used by your version of PowerBuilder.

PowerBuilder 2021 makes a change to the wrapper classnames, requiring the following:

   ulong hWin_wrapper
   ulong hWin_control

   hWin_wrapper = Handle( RTEcontrol )
   IF hWin_wrapper > 0 THEN
    hWin_wrapper = FindWindowEx(hWin_wrapper,0, "PBTxTextControl", 0)
	IF hWin_wrapper > 0 THEN
     hWin_wrapper = FindWindowEx(hWin_wrapper,0, "AfxOleControl90u", 0)
     IF hWin_wrapper > 0 THEN
      hWin_control = FindWindowEx(hWin_wrapper,0, "TX28", 0)
     END IF
    END IF
   END IF
   

Once the handle of the actual control has been found, then add the call to SSCE_CheckCtrlDlg.

   ll_rc = SSCE_CheckCtrlDlg(Handle(This), hWin_control, 0)
   

Checking PowerBuilder Controls in the Background ("As You Type")

Many customers want to do background ("as you type") checking of text in PowerBuilder controls. As with interactive checking, you cannot do this kind of spell checking with DataWindows.

You can do background spell checking with both multi-line edit controls and Rich Text Edit controls, although because a standard edit control can only change the font or color for all of the text in the control, you have to do something else such as highlight an image or a label on the screen outside of the screen when a spelling error is detected. (Please see the Programmer's Guide or the sample PowerBuilder demo application for more information.)

The Rich Text Edit control in PowerBuilder allows Sentry to do background spell checking. There is one quirk: you cannot have misspelled text "marked" with a colour, but should just use the option to indicate that misspelled words are to be underlined, which will cause a wavy red line to appear under the word. (If you try to specify a color, regardless of what color code you provide, misspelled words will be shown in green text, and the API call to show the context menu will not be able to find the misspelled words in the RTE control.)

For both types of control, the primary event to trap is the Key (or KeyDown) event. (This may need to be added as a new event to an MLE control as it is not shown by default in the PowerBuilder IDE.) Then in the event handler, call the API to check what was just typed into the control. For an RTE control you need to obtain the handle of the "real" RTE control, as described above, while for an MLE control you can just use the standard Handle(mle_controlname).

   ll_rc = SSCE_CheckCtrlBackgroundNotify(hWin_control, 8, 0)
   

The second event to trap is the RButtonDown event to handle when the user right-clicks on a misspelled word in the control. Convert the coordinates of where the mouse was clicked into pixels and then call the Sentry API to display the context menu. A menu will only be displayed if the cursor was over a misspelled word when it was clicked.

   ll_x = UnitsToPixels(xpos, XUnitsToPixels!)
   ll_y = UnitsToPixels(ypos, YUnitsToPixels!)

   ll_rc = SSCE_CheckCtrlBackgroundMenu(hWin_control, ll_x, ll_y,8, 0)
   


Home Site index Contact us Catalog Shopping Cart Products Support Search


Copyright © 2015 Wintertree Software Inc.