home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pentlk11.zip / RECODISP.C < prev    next >
C/C++ Source or Header  |  1994-01-13  |  22KB  |  478 lines

  1. /****************************************************************************
  2. *                                                                           *
  3. *  File Name   : RECODISP.C                                                 *
  4. *                                                                           *
  5. *  Description : Example PENPM Aware Application                            *
  6. *                                                                           *
  7. *  Copyright (C) 1992 IBM Corporation                                       *
  8. *                                                                           *
  9. *  NOTE: The RECODISP program can NOT run by itself. It must be given as    *
  10. *        a command name in Gesture setting page. Click right mouse button   *
  11. *        on a program object in work place shell, for example, calculator.  *
  12. *        Click the arrow in Open and then Settings. Get the Gesture page    *
  13. *        and edit a gesture. Highlight a gesture and click the Edit button. *
  14. *        Give RECODISP as Command and click OK button. If you give the      *
  15. *        gesture on the Calculator, the Pen for OS/2 will initiate the      *
  16. *        RECODISP program.                                                  *
  17. *                                                                           *
  18. *        The RECODISP.EXE must be in a directory given in "PATH=" in        *
  19. *        CONFIG.SYS file.                                                   *
  20. *                                                                           *
  21. *        If you access (read/write) any file, you have to give full path    *
  22. *        for the file.                                                      *
  23. *                                                                           *
  24. *        If you call DosQueryCurrentDir or DosQueryCurrentDisk, the root    *
  25. *        directory of boot disk is usually returned, but this is NOT        *
  26. *        always true. It is unpredictable.                                  *
  27. *                                                                           *
  28. *        While you process the WM_RECO_COMMAND message, do NOT give a       *
  29. *        message/dialog box. Simply post a message to yourself to give      *
  30. *        such box. Otherwise deadlock can occur.                            *
  31. *                                                                           *
  32. *        The RECODATA can be retrieved by RedRecoDataFromEnv at the         *
  33. *        WM_CREATE message and by WM_RECO_COMMAND message. The command,     *
  34. *        arguments, and prefix command handling is NOT same in two messages.*
  35. *        Please check the codes below.                                      *
  36. *                                                                           *
  37. *  DISCLAIMER OF WARRANTIES.  The following [enclosed] code is              *
  38. *      sample code created by IBM Corporation. This sample code is not      *
  39. *      part of any standard or IBM product and is provided to you solely    *
  40. *      for  the purpose of assisting you in the development of your         *
  41. *      applications.  The code is provided "AS IS", without                 *
  42. *      warranty of any kind.  IBM shall not be liable for any damages       *
  43. *      arising out of your use of the sample code, even if they have been   *
  44. *      advised of the possibility of such damages.                          *
  45. *                                                                           *
  46. ****************************************************************************/
  47.  
  48. #define  INCL_DOS
  49. #define  INCL_PM
  50. #define  INCL_GPI
  51. #include <os2.h>
  52.  
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <stdio.h>
  56.  
  57. #include <penpm.h>
  58. #include "recodisp.h"
  59.  
  60. int main(VOID)
  61. {
  62. QMSG     qmsgMain;
  63. HMQ      hmqMain;
  64. HWND     hwndFrame;
  65. HWND     hwndClient;
  66. ULONG    flCreate;
  67.  
  68.   habMain = WinInitialize( (ULONG)NULL );
  69.   hmqMain = WinCreateMsgQueue( habMain, 0L );
  70.  
  71.   WinRegisterClass( habMain,
  72.                     "MyClient",
  73.                     (PFNWP)ClientWndProc,
  74.                     CS_SIZEREDRAW,
  75.                     0UL );
  76.  
  77.   /************************************************************************
  78.   * Tell PM that we want the standard frame window, but we will set the   *
  79.   * the size and position the frame window.  This frame window will       *
  80.   * surround a "MyClient" class client window.                            *
  81.   ************************************************************************/
  82.   flCreate = FCF_STANDARD & ~FCF_SHELLPOSITION | FCF_ICON;
  83.  
  84.   hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
  85.                                   0L,
  86.                                   (PULONG) &flCreate,
  87.                                   "MyClient",
  88.                                   "",
  89.                                   0L,
  90.                                   (HMODULE)NULL,
  91.                                   ID_MAIN,
  92.                                   (PHWND)&hwndClient );
  93.  
  94.   /*************************************************************************
  95.   * Tell PM to display our window at the designated size and place.        *
  96.   *************************************************************************/
  97.   WinSetWindowPos( hwndFrame,
  98.                    HWND_TOP,
  99.                    50, 50, 540, 100,
  100.                    SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW );
  101.  
  102.   while( WinGetMsg( habMain, &qmsgMain, (HWND)NULL, 0, 0 ) )
  103.   {
  104.     WinDispatchMsg( habMain, &qmsgMain );
  105.   }
  106.  
  107.   WinDestroyWindow( hwndFrame );
  108.   WinDestroyMsgQueue( hmqMain );
  109.   WinTerminate( habMain );
  110.   return(FALSE);
  111. }
  112.  
  113. MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  114. {
  115. HPS             hpsClient;
  116. RECTL           rcClient;
  117. APIRET          RedRC;
  118. HWND            hwndHotspot;
  119. HWND            hwndActive;
  120. HWND            hwndFocus;
  121. ULONG           nLen;
  122. HRECO           hReco;
  123. RECOID          rID;
  124. CHAR            achRecoSubsys[15], achRecoEvent[15];
  125. ULONG           ulEventCnt;
  126. ULONG           ulVID;              /* virtual ID of event                */
  127. ULONG           ulCC;               /* charactor code of event            */
  128. static POINTL   ptText, ptText2;
  129. static RECODATA *pRecodata;
  130. static BOOL     fClearClientWindow = FALSE;
  131. static CHAR     achLine[STR_LEN];
  132. static CHAR     achLine2[STR_LEN];
  133. static CHAR     achMsg[STR_LEN], achMsg2[STR_LEN], achMsg3[STR_LEN];
  134. static PCHAR    pCmd, pArg, pPrefixCmd;
  135. static BOOL     fInit = FALSE;
  136.  
  137.   switch( msg )
  138.   {
  139.      case WM_CREATE:
  140.      {
  141.         /********************************************************************
  142.         * The APIs being used in this procedure depend on the PenPM sub-    *
  143.         * system being correctly initialized.  Thus we check to make sure   *
  144.         * PenPM is up before we do anything else.                           *
  145.         ********************************************************************/
  146.         if( WrtWaitActive( WRT_IMMEDIATE_RETURN ) )
  147.         {
  148.            /******************************************************************
  149.            * If PenPM is NOT active then put up a message box and terminate  *
  150.            * the program.                                                    *
  151.            ******************************************************************/
  152.            RedRC = 0;           /* fool the compiler to aviod warning error */
  153.            GetString(hwnd, STR_1, FALSE, RedRC, TRUE);
  154.            break;
  155.         }
  156.  
  157.         /********************************************************************
  158.         * Register reco cmd with PenPM.                                     *
  159.         * If you have another command handler running and if you want to    *
  160.         * remove it, the RedQueryRecoCommand and RedDeregisterRecoCommand   *
  161.         * API's can be used.                                                *
  162.         ********************************************************************/
  163.         RedRC = RedRegisterRecoCommand( CMD_STR, ID_CMD, hwnd );
  164.         if (RedRC)
  165.         {
  166.            GetString(hwnd, STR_5, TRUE, RedRC, TRUE);
  167.            break;
  168.         }
  169.  
  170.         /********************************************************************
  171.         * Retrieve RECODATA from environment.                               *
  172.         * First put NULL for the buffer pointer to get the actual size.     *
  173.         * If NULL is given as buffer pointer, then NO error returned.       *
  174.         * If it is not NULL but the lenght is not sufficient, then          *
  175.         * REDERR_BUF_TOO_SMALL is returned.                                 *
  176.         ********************************************************************/
  177.         nLen = 0;
  178.         RedRecoDataFromEnv( NULL, &nLen );
  179.  
  180.         /********************************************************************
  181.         *  Check whether this program is initiated by Pen system.           *
  182.         ********************************************************************/
  183.         if (!nLen)
  184.         {
  185.            GetString(hwnd, STR_6, FALSE, RedRC, FALSE);
  186.            fInit = TRUE;
  187.            nLen = sizeof(RECODATA) + CCHMAXPATH;
  188.            WinLoadString(habMain,
  189.                          0UL,
  190.                          STR_7,
  191.                          sizeof(achLine2),
  192.                          achLine2);
  193.         }
  194.  
  195.         /*****************************************************************
  196.         *  The actual length of data is returned in nLen.                *
  197.         *****************************************************************/
  198.         pRecodata = (RECODATA *) malloc(nLen);
  199.         if (!pRecodata)
  200.         {
  201.            GetString(hwnd, STR_4, FALSE, RedRC, TRUE);
  202.            break;
  203.         }
  204.  
  205.         if (!fInit)
  206.         {
  207.            RedRC = RedRecoDataFromEnv( pRecodata, &nLen );
  208.            if (RedRC)
  209.            {
  210.               GetString(hwnd, STR_2, TRUE, RedRC, TRUE);
  211.               break;
  212.            }
  213.         }
  214.  
  215.         /****************************************************************
  216.         *  Allocate memory for command, argument, and prefix command.   *
  217.         ****************************************************************/
  218.         pCmd = malloc(LEN_CMD);
  219.         pArg = malloc(LEN_ARG);
  220.         pPrefixCmd = malloc(LEN_PCMD);
  221.         if (!pCmd || !pArg || !pPrefixCmd)
  222.         {
  223.            GetString(hwnd, STR_4, FALSE, RedRC, TRUE);
  224.            break;
  225.         }
  226.  
  227.         /*****************************************************************
  228.         *  Set position in window.                                       *
  229.         *****************************************************************/
  230.         ptText.x = ptText2.x = 20;
  231.         ptText.y = 26;
  232.         ptText2.y = 10;
  233.  
  234.         /*****************************************************************
  235.         *  Load the strings used to give the RECODATA.                   *
  236.         *****************************************************************/
  237.         WinLoadString(habMain, 0UL, STR_3, sizeof(achMsg), achMsg);
  238.         WinLoadString(habMain, 0UL, STR_8, sizeof(achMsg2), achMsg2);
  239.         WinLoadString(habMain, 0UL, STR_9, sizeof(achMsg3), achMsg3);
  240.  
  241.         /*****************************************************************
  242.         *  When the RECODATA is retrieved from environment, the Command, *
  243.         *  Argument, and PrefixCommand are attached after the RECODATA.  *
  244.         *  So, the pszCmd points after the pszPrefixCmd, the pszArg      *
  245.         *  points after the command data, and so forth.                  *
  246.         *  All three data are terminated by NULL character.              *
  247.         *  But the retrieval of RECODATA by WM_RECO_COMMAND message is   *
  248.         *  quite different. Check the message below.                     *
  249.         *****************************************************************/
  250.         WinPostMsg(hwnd, WM_RECO_INFO, NULL, NULL);
  251.         break;
  252.      }
  253.  
  254.      case WM_RECO_COMMAND:
  255.      {
  256.         /********************************************************************
  257.         *  Replace this message handling code with yours for your own       *
  258.         *  command handler based upon the command and argument in RECODATA. *
  259.         ********************************************************************/
  260.  
  261.         fInit = FALSE;
  262.  
  263.         /********************************************************************
  264.         * Copy the RECODATA.                                                *
  265.         ********************************************************************/
  266.         *pRecodata = * (RECODATA *) PVOIDFROMMP(mp2);
  267.  
  268.         /*****************************************************************
  269.         *  The RECODATA is retrieved, but the command, argument, and     *
  270.         *  prefix command must be copied too.  These data are valid      *
  271.         *  while the WM_RECO_COMMAND message is processed.               *
  272.         *****************************************************************/
  273.         if (pRecodata->pszCommand)
  274.         {
  275.            strcpy(pCmd, pRecodata->pszCommand);
  276.         }
  277.         if (pRecodata->pszCmdArgs)
  278.         {
  279.            strcpy(pArg, pRecodata->pszCmdArgs);
  280.         }
  281.         if (pRecodata->pszPrefixCmd)
  282.         {
  283.            strcpy(pPrefixCmd, pRecodata->pszPrefixCmd);
  284.         }
  285.  
  286.         /*****************************************************************
  287.         * Do NOT call WinMessageBox or WinDlgBox because deadlock can    *
  288.         * occur. You can check the command or recoID field in RECODATA,  *
  289.         * and then, based upon the command or ID, you can run program    *
  290.         * designated for the command or ID.                              *
  291.         *****************************************************************/
  292.  
  293.         WinPostMsg(hwnd, WM_RECO_INFO, NULL, NULL);
  294.         return( (MRESULT)(TRUE) );
  295.      }
  296.  
  297.      case WM_RECO_INFO:
  298.         /*****************************************************************
  299.         * Pull out desired data                                          *
  300.         *****************************************************************/
  301.         if (!fInit)
  302.         {
  303.            hwndHotspot = pRecodata->hwnd;
  304.            hwndActive  = pRecodata->hwndActive;
  305.            hwndFocus   = pRecodata->hwndFocus;
  306.  
  307.            WinLoadString(habMain, 0UL, STR_3, sizeof(achMsg), achMsg);
  308.            sprintf(achLine, achMsg, hwndHotspot, hwndActive, hwndFocus);
  309.  
  310.         }
  311.         /******************************************************************
  312.         * Invalidate the client window to force a repaint                 *
  313.         ******************************************************************/
  314.         WinInvalidateRect( hwnd, NULL, TRUE );
  315.  
  316.         break;
  317.  
  318.      case WM_PAINT:
  319.      {
  320.         hpsClient = WinBeginPaint( hwnd, (HPS) NULL, &rcClient );
  321.         WinFillRect( hpsClient, &rcClient, SYSCLR_WINDOW );
  322.  
  323.         /********************************************************************
  324.         * If there was a clear cmd, then clear the client window.           *
  325.         ********************************************************************/
  326.         if( fClearClientWindow )
  327.         {
  328.            fClearClientWindow = FALSE;
  329.         }
  330.         else
  331.         {
  332.            GpiCharStringAt(hpsClient,
  333.                            &ptText,
  334.                            STR_LEN,
  335.                            fInit ? achLine2 : achLine);
  336.            if (!fInit)
  337.            {
  338.               /************************************************************
  339.               *  Give the subsystem and event names if RECODISP is        *
  340.               *  initiated by gesture.                                    *
  341.               ************************************************************/
  342.  
  343.               /************************************************************
  344.               *   Get the reco ID and reco handle from RECODATA.          *
  345.               *   These will give event and subsystem names.              *
  346.               *   Get the virtual ID and character code from RECODATA.    *
  347.               ************************************************************/
  348.               rID = pRecodata->id;
  349.               hReco = pRecodata->hReco;
  350.               ulVID = pRecodata->virtual_id;
  351.               ulCC = pRecodata->char_code;
  352.  
  353.               /****************************************************************
  354.               *  Get the Reco Subsystem name and Number of Events from handle.*
  355.               *  If you have the subsystem name, then the RedQueryRecoHandle  *
  356.               *  API can be used to get the reco handle. achRecoSubsys has    *
  357.               *  "GESTURE".                                                   *
  358.               ****************************************************************/
  359.               RedQueryRecoSubsystem(hReco, achRecoSubsys, &ulEventCnt);
  360.  
  361.               /****************************************************************
  362.               *  Get the Event Name.                                          *
  363.               *  If the event name is available, then the event ID can be     *
  364.               *  retrieved by RedRecoIDFromName.                              *
  365.               ****************************************************************/
  366.               RedRecoNameFromID(hReco, rID, achRecoEvent);
  367.  
  368.               if (ulVID <= 32)
  369.               {
  370.                  ulVID--;            /* Adjust subscript */
  371.                  sprintf(achLine2, achMsg2, achRecoEvent, achVEID[ulVID]);
  372.               }
  373.               else
  374.               {
  375.                  /***********************************************************
  376.                  *  For alphabet chacter gesture                            *
  377.                  ***********************************************************/
  378.                  sprintf(achLine2, achMsg3, achRecoEvent, ulCC );
  379.               }
  380.  
  381.               GpiCharStringAt(hpsClient,
  382.                               &ptText2,
  383.                               STR_LEN,
  384.                               achLine2);
  385.            }
  386.         }
  387.         WinEndPaint( hpsClient );
  388.         break;
  389.      }
  390.  
  391.      case WM_COMMAND:
  392.      {
  393.         switch( SHORT1FROMMP(mp1) )
  394.         {
  395.            case ID_CLEAR:
  396.            {
  397.               /***************************************************************
  398.               * If there was a clear cmd, then tell the procedure to clear   *
  399.               * the client window.                                           *
  400.               ***************************************************************/
  401.               fClearClientWindow = TRUE;
  402.               WinInvalidateRect( hwnd, NULL, TRUE );
  403.               break;
  404.            }
  405.  
  406.            case ID_EXIT:
  407.            default:
  408.               WinPostMsg(hwnd, WM_CLOSE, NULL, NULL);
  409.  
  410.               /**************************************************************
  411.               * Free memory allocated for Recodata, command, argument,      *
  412.               * and prefix command.                                         *
  413.               **************************************************************/
  414.               free(pRecodata);
  415.               free(pCmd);
  416.               free(pArg);
  417.               free(pPrefixCmd);
  418.               break;
  419.         }
  420.         break;
  421.      }
  422.  
  423.      default:
  424.      {
  425.        return( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
  426.      }
  427.   }
  428.   return FALSE;
  429. }
  430.  
  431. /******************************************************************************
  432. *                                                                             *
  433. * Function Name: GetString                                                    *
  434. *                                                                             *
  435. * Description : Load string for each string ID.                               *
  436. *                                                                             *
  437. * Input: hwnd    : Client window handle                                       *
  438. *        nStr_ID : String ID                                                  *
  439. *        fPr     : print flag                                                 *
  440. *        RedRC   : if fPr is TRUE, print this return code.                    *
  441. *        fRet    : if FALSE, return without deregistering the command handler.*
  442. *                                                                             *
  443. * Output:  None.                                                              *
  444. *                                                                             *
  445. ******************************************************************************/
  446. VOID  GetString(HWND hwnd, ULONG nStr_ID, BOOL fPr, APIRET RedRC, BOOL fRet)
  447. {
  448. CHAR   achLine[80], achMsg[80];
  449.  
  450.     WinLoadString(habMain,
  451.                   0UL,
  452.                   nStr_ID,
  453.                   sizeof(achMsg),
  454.                   achMsg);
  455.     if (fPr)
  456.     {
  457.        sprintf(achLine, achMsg, RedRC);
  458.     }
  459.     WinMessageBox( HWND_DESKTOP,
  460.                    hwnd,
  461.                    fPr ? achLine : achMsg,
  462.                    fRet ? NULL : (PSZ) "Warning",
  463.                    1, MB_OK );
  464.  
  465.     if (!fRet)
  466.     {
  467.        return;
  468.     }
  469.  
  470.     /*****************************************************************
  471.     *  Deregister the reco command.                                  *
  472.     *****************************************************************/
  473.     RedDeregisterRecoCommand(hwnd);
  474.  
  475.     WinSendMsg( hwnd, WM_CLOSE, NULL, NULL );
  476.     return;
  477. }
  478.