home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / SNOOP / SNOOP.C_ / SNOOP.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  18.8 KB  |  610 lines

  1. #define WIN31
  2. #include <windows.h>
  3. #include <penwin.h>
  4. #include <penwoem.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "snoop.h"
  9.  
  10.  
  11. /************************* Module Data **************************************/
  12.  
  13. //Class name
  14. static char szSnoopClassMain[] = "SnoopyClass";
  15.  
  16. //Window Caption
  17. static char szAppName[] = "SnoopyWindow";
  18.  
  19. //Name of penwindows dll
  20. static char szPenWin[] = "penwin.dll";
  21.  
  22. //Instance handle
  23. static HANDLE hInstanceCur;
  24.  
  25. //Main window handle
  26. static HANDLE hwndWindow;
  27.  
  28. static TEXTMETRIC tm;
  29.  
  30. static HANDLE hwndGraph, hwndResult;
  31. static FARPROC lpfnGraph, lpfnResult, lpfnRoHeditProc;
  32.  
  33. HCURSOR hcurAltSelect;
  34.  
  35. //Ink data copy 
  36. static HPENDATA hpendataCopy;
  37.  
  38. //Ink width
  39. static int nInkWidth;
  40.  
  41. //Ink color
  42. static DWORD rgbInk;
  43.  
  44. //TRUE if hook has been set
  45. static BOOL fHookSet;
  46.  
  47. //TRUE if the current display is to be retained
  48. static BOOL fHold = FALSE;
  49.  
  50. //Buffers used in translation
  51. static char szSyeBuff[2048];
  52. static char szSyvBuff[2048];
  53.  
  54. //Mapping table for Gesture Strings
  55. static SYVID rgGestures[]=
  56.     {
  57.     SYV_EXTENDSELECT,   " ExtendSelect! ",
  58.     SYV_UNDO,           " Undo! ",
  59.     SYV_COPY,           " Copy! ",
  60.     SYV_CUT,                " Cut! ",
  61.     SYV_PASTE,          " Paste! ",
  62.     SYV_CLEARWORD,      " Delete Words!",
  63.     SYV_CORRECT,        " Correct! ",
  64.     SYV_BACKSPACE,      " Backspace! ",
  65.     SYV_SPACE,          " Space! ",
  66.     SYV_RETURN,         " Return! ",
  67.     SYV_TAB,                " Tab! ",
  68.     SYV_CLEAR,          " Delete!",
  69.     };
  70.  
  71. // Prefix for displaying circled letter gestures
  72. static char szCircleG[] = "Circle - ";
  73.  
  74. //Annotation strings
  75. static char szGraph[] = "Graph";
  76. static char szResult[] = "Result";
  77.  
  78. // Ink display offset
  79. static POINT ptInk;
  80.  
  81. static POINT grTOrg = {0, 2};
  82.  
  83. static POINT grOrg;
  84. static POINT grExt;
  85.  
  86. static POINT resOrg;
  87. static POINT resExt;
  88.  
  89. static POINT resTOrg;
  90.  
  91. static int grXText, resXText;
  92.  
  93. static char szInitError[] = "Error during init process";
  94.  
  95. /****************************************************************************/
  96.  
  97. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  98.     LPSTR lpszCommandLine, int cmdShow)
  99. /*******************************************************************
  100.  
  101. FUNCTION:   WinMain(hInstance, hPrevInstance, lpszCommandLine, cmdShow)
  102.  
  103. PURPOSE:        Windows Entry Point
  104.  
  105. *******************************************************************/
  106.     {
  107.     MSG msg;
  108.  
  109.     // register classes, init objects, set globals, prefs, etc:
  110.     if (!FInitSnoop(hInstance, hPrevInstance))
  111.         exit(-1);
  112.  
  113.     // Initialize the application instance
  114.     if (FInitInstance(hInstance, hPrevInstance, cmdShow))
  115.         {
  116.         while (GetMessage((LPMSG)&msg, NULL, 0, 0) )
  117.             {
  118.             TranslateMessage((LPMSG)&msg);
  119.             DispatchMessage((LPMSG)&msg);
  120.             }
  121.         }
  122.     else
  123.         msg.wParam = (WPARAM)-1;
  124.  
  125.     return msg.wParam;
  126.     }
  127.  
  128. BOOL PASCAL FInitSnoop(HANDLE hInstance, HANDLE hPrevInstance)
  129. /****************************************************************
  130.  
  131. FUNCTION:   FInitSnoop(hInstance, hPrevInstance)
  132.  
  133. PURPOSE:       Init for all instances of the application
  134.  
  135. COMMENTS:   Register the main window class for the first
  136.                 instance of the program.
  137.  
  138. *****************************************************************/
  139.     {
  140.     WNDCLASS wndClass;
  141.  
  142.     hInstanceCur = hInstance;   // set global
  143.  
  144.     if (!hPrevInstance)
  145.         {
  146.         // Main Window
  147.         wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  148.         wndClass.hIcon = LoadIcon(hInstance, (LPSTR)"iconSnoop");
  149.         wndClass.lpszMenuName = NULL;
  150.         wndClass.lpszClassName = (LPSTR)szSnoopClassMain;
  151.         wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW+1;
  152.         wndClass.hInstance = hInstance;
  153.         wndClass.style = CS_VREDRAW | CS_HREDRAW;
  154.         wndClass.lpfnWndProc = SnoopWndProc;
  155.         wndClass.cbClsExtra = 0;
  156.         wndClass.cbWndExtra = 0;
  157.         if (!RegisterClass((LPWNDCLASS) &wndClass))
  158.             return FALSE;
  159.         }
  160.     return TRUE;
  161.     }
  162.  
  163. BOOL PASCAL FInitInstance(HANDLE hInstance, HANDLE hPrevInstance, int cmdShow)
  164. /*******************************************************************************
  165.  
  166. FUNCTION:   FInitInstance(hInstance, hPrevInstance, cmdShow)
  167.  
  168. PURPOSE:        Initialize this instance of the application
  169.  
  170. COMMENTS:   
  171.                 Create main window. Set the hook so that all recognition
  172.                 results are delivered to this instance before being
  173.                 passed on to the recipient.
  174.  
  175. ********************************************************************************/
  176.     {
  177.     HANDLE hPenWin;
  178.  
  179.     //Create the main window
  180.    hwndWindow = CreateWindow((LPSTR)szSnoopClassMain,
  181.                              (LPSTR)szAppName,
  182.                              WS_OVERLAPPEDWINDOW,
  183.                              0, 0, GetSystemMetrics(SM_CXFULLSCREEN),
  184.                              7 * GetSystemMetrics(SM_CYCAPTION),
  185.                              (HWND)NULL,
  186.                              (HMENU)LoadMenu(hInstance, MAKEINTRESOURCE(menuSnoop)),
  187.                              (HANDLE)hInstance,
  188.                              (LPSTR)NULL);
  189.  
  190.    if (!hwndWindow)
  191.        return FALSE;
  192.  
  193.     // Calculate the relative positions of all items on the screen
  194.     CalcTopology(hwndWindow);
  195.  
  196.     // Create the EDIT control to show the Symbol Graph
  197.     hwndGraph = CreateWindow("EDIT", NULL
  198.                                         , WS_CHILDWINDOW|WS_BORDER|WS_VISIBLE|ES_AUTOHSCROLL|ES_READONLY,
  199.                                         grOrg.x, grOrg.y,
  200.                                         grExt.x, grExt.y,
  201.                                         hwndWindow,
  202.                                         idGraph,
  203.                                         (HANDLE)hInstance,
  204.                                         (LPSTR)NULL);
  205.  
  206.     // Create the EDIT control to show the recognition result
  207.     hwndResult = CreateWindow("EDIT", NULL
  208.                                         , WS_CHILDWINDOW|WS_BORDER|WS_VISIBLE|ES_AUTOHSCROLL|ES_READONLY
  209.                                         ,resOrg.x, resOrg.y
  210.                                         ,resExt.x, resExt.y
  211.                                         ,hwndWindow
  212.                                         ,idResult
  213.                                         ,(HANDLE)hInstance
  214.                                         ,NULL);
  215.  
  216.  
  217.     //Set the results hook
  218.    fHookSet = SetRecogHook(HWR_RESULTS, HKP_SETHOOK, hwndWindow);
  219.  
  220.     //If any of these steps failed bail out
  221.     if(!hwndGraph || !hwndResult || !fHookSet)
  222.         {
  223.         MessageBox(hwndWindow, szInitError, NULL, MB_ICONEXCLAMATION|MB_OK);
  224.         DestroyWindow(hwndWindow);
  225.         return(FALSE);
  226.         }
  227.  
  228.     // Subclass the controls to show alternate cursor
  229.  
  230.     lpfnRoHeditProc = MakeProcInstance((FARPROC)RoHeditProc, hInstanceCur);
  231.  
  232.     lpfnGraph = (FARPROC)SetWindowLong(hwndGraph, GWL_WNDPROC, (LPARAM)lpfnRoHeditProc);
  233.     lpfnResult = (FARPROC)SetWindowLong(hwndResult, GWL_WNDPROC, (LPARAM)lpfnRoHeditProc);
  234.  
  235.     // Load the alternate cursor from penwin.dll
  236.     hPenWin = LoadLibrary(szPenWin);
  237.     hcurAltSelect = LoadCursor(hPenWin, IDC_ALTSELECT);
  238.     FreeLibrary(hPenWin);
  239.  
  240.     ShowWindow(hwndWindow, cmdShow);
  241.    UpdateWindow(hwndWindow);
  242.  
  243.    return(TRUE);
  244.     }
  245.  
  246. long FAR PASCAL __export SnoopWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  247. /***************************************************************************
  248.  
  249. FUNCTION:   SnoopWndProc(hwnd, message, wParam, lParam)
  250.  
  251. PURPOSE:        Windows message handling procedure
  252.  
  253. COMMENTS:
  254.                 Also handles WM_HOOKRCRESULT which the penwin.dll sends
  255.                 to every window that has set the hook.
  256.  
  257. ***************************************************************************/
  258.     {
  259.     HDC hDC;
  260.     long lRet = 1L;
  261.     static long lCall=0;
  262.     LPRCRESULT lpResT;
  263.     PAINTSTRUCT ps;
  264.  
  265.     switch (message)
  266.         {
  267.         case WM_CREATE:
  268.             EnableMenuItem(GetMenu(hwnd), miRelease, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
  269.             break;
  270.         case WM_SIZE:
  271.             {
  272.             //Recalculate the width of both the edit controls
  273.             grExt.x = resExt.x = LOWORD(lParam) - (max(grXText, resXText)+5) - 5;
  274.             grExt.y = resExt.y = (int)(1.5 * tm.tmHeight);
  275.  
  276.             //Resize them
  277.             if(hwndGraph)
  278.                 MoveWindow(hwndGraph, grOrg.x, grOrg.y, grExt.x, grExt.y, TRUE);
  279.             if(hwndResult)
  280.                 MoveWindow(hwndResult, resOrg.x, resOrg.y, resExt.x, resExt.y, TRUE);
  281.             }
  282.             break;
  283.         case WM_PAINT:
  284.             if(hpendataCopy)
  285.                 {
  286.                 hDC = BeginPaint(hwnd, &ps);
  287.                 SetBkMode(hDC, TRANSPARENT);
  288.                 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  289.  
  290.                 //Draw annotation text
  291.                 TextOut(hDC, grTOrg.x, grTOrg.y, szGraph, _fstrlen(szGraph));
  292.                 TextOut(hDC, resTOrg.x, resTOrg.y, szResult, _fstrlen(szResult));
  293.  
  294.                 //Show the ink exactly the user drew it
  295.                 RedisplayPenData(hDC, hpendataCopy, &ptInk, NULL, nInkWidth, rgbInk);
  296.  
  297.                 EndPaint(hwnd, &ps);
  298.                 }
  299.             break;
  300.  
  301.         case WM_HOOKRCRESULT:
  302.          {
  303.             PENDATAHEADER pendataheader;
  304.  
  305.             // Break if we are holding the results of earlier recognition
  306.             if (fHold)
  307.                 break;
  308.  
  309.             //Get the pointer to the recognition results structure
  310.             lpResT = (LPRCRESULT)lParam;
  311.  
  312.             //Convert the result into ANSI string
  313.             SyvToStr(lpResT->lpsyv, lpResT->cSyv, szSyvBuff, sizeof(szSyvBuff)-1, FALSE);
  314.  
  315.             //Show it in the Result EDIT control
  316.             SetWindowText(hwndResult, szSyvBuff);
  317.  
  318.             //Convert the symbol graph into ANSI string
  319.             SyvToStr(lpResT->syg.lpsye, lpResT->syg.cSye, szSyeBuff, sizeof(szSyeBuff)-1, TRUE);
  320.  
  321.             //Show it in the Graph EDIT control
  322.             SetWindowText(hwndGraph, szSyeBuff);
  323.  
  324.             //Delete any older pen data
  325.             if (hpendataCopy)
  326.                 DestroyPenData(hpendataCopy);
  327.  
  328.             // Make a copy of the pendata
  329.             hpendataCopy = DuplicatePenData(lpResT->hpendata, 0);
  330.  
  331.             //Save the ink color
  332.             rgbInk = lpResT->lprc->rgbInk;
  333.  
  334.             //and the width
  335.             nInkWidth = lpResT->lprc->nInkWidth;
  336.  
  337.             GetPenDataInfo(hpendataCopy, &pendataheader, NULL, 0);
  338.  
  339.             // Offset the pendata so all points are wrt. the top left
  340.             //corner of it's bounding rect which is at 0, 0
  341.             OffsetPenData(hpendataCopy, -pendataheader.rectBound.left
  342.                                 ,-pendataheader.rectBound.top);
  343.  
  344.             InvalidateRect(hwnd, NULL, TRUE);
  345.             UpdateWindow(hwnd);
  346.             break;
  347.          }
  348.  
  349.         case WM_CLOSE:
  350.             //Remove the hook
  351.             if(fHookSet)
  352.                 SetRecogHook(HWR_RESULTS, HKP_UNHOOK, hwnd);
  353.  
  354.             //Destroy the edit controls
  355.             if(hwndGraph)
  356.                 DestroyWindow(hwndGraph);
  357.             if(hwndResult)
  358.                 DestroyWindow(hwndResult);
  359.  
  360.             if(lpfnRoHeditProc)
  361.                 FreeProcInstance(lpfnRoHeditProc);
  362.  
  363.             if(hcurAltSelect)
  364.                 DestroyCursor(hcurAltSelect);
  365.  
  366.             PostQuitMessage(0);
  367.             break;
  368.  
  369.         case WM_COMMAND:
  370.             if (FDispatchMenu(hwnd, wParam, lParam))
  371.             return 1;
  372.             break;
  373.  
  374.         case WM_DESTROY:
  375.             break;
  376.  
  377.         default:
  378.             break;
  379.         }
  380.  
  381.     return DefWindowProc(hwnd, message, wParam, lParam);
  382.     }
  383.  
  384. VOID PASCAL SyvToStr(LPVOID lpData, int cItem, LPSTR lpstr, int cMax, BOOL fSye)
  385. /*******************************************************************************
  386.  
  387. FUNCTION:   SyvToStr(lpData, cItem, lpstr, cMax, fSye)
  388.  
  389. PURPOSE:        Converts from SYV to form to ANSI in order to display
  390.  
  391. COMMENTS:
  392.                 Converts meta symbols SYV_BEGINOR, SYV_ENDOR and SYV_OR
  393.                 to '{', '}' and '|' respectively.
  394.                 Also converts gestures to strings
  395.  
  396. *******************************************************************************/
  397.     {
  398.     int i, j, cLen;
  399.     SYV syvT;
  400.     char buff[33];
  401.  
  402.     for(i=j=0; i< cItem; ++i)
  403.         {
  404.         syvT = (fSye)?((LPSYE)lpData)[i].syv : ((LPSYV)lpData)[i];
  405.  
  406.         cLen = 1;
  407.         switch(syvT)
  408.             {
  409.         case SYV_BEGINOR:
  410.             lpstr[j] = '{';
  411.             break;
  412.         case SYV_ENDOR:
  413.             lpstr[j] = '}';
  414.             break;
  415.         case SYV_OR:
  416.             lpstr[j] = '|';
  417.             break;
  418.         case SYV_EMPTY:
  419.             lpstr[j] = '_';
  420.             break;
  421.         case SYV_SPACENULL:
  422.             cLen = 0;
  423.             break;
  424.         case SYV_SOFTNEWLINE:
  425.             lpstr[j] = (char)ANSI_PARA_MARK;      // parragraph mark
  426.             break;
  427.  
  428.         default:
  429.             //If this is a gesture
  430.             if(FIsGesture(syvT))
  431.                 {
  432.                 //Convert to string
  433.                 cLen = IGestureString(syvT, buff, sizeof(buff)-1);
  434.  
  435.                 //And append it to the output buffer.
  436.                 if(cLen)
  437.                     {
  438.                     cLen = ((cLen + j) < cMax)?cLen:(cMax-j-1);
  439.                     if(cLen>0)
  440.                         _fstrncpy(&lpstr[j], buff, cLen);
  441.                     }   
  442.                 }
  443.             //This could just be a SYV for an ANSI character
  444.             else if(!SymbolToCharacter(&syvT, 1, &lpstr[j], NULL))
  445.                 lpstr[j] = '?';
  446.             
  447.             if (lpstr[j] == '\0')
  448.                 cLen = 0;
  449.             else if (lpstr[j] == ANSI_NEW_LINE)     // New Line
  450.                 lpstr[j] = (char)ANSI_PARA_MARK; // parragraph mark
  451.             }
  452.         j += cLen;
  453.         }
  454.         lpstr[j] = '\0';
  455.     }
  456.  
  457.  
  458. int PASCAL IGestureString(SYV syvGes, LPSTR lpstr, int cMac)
  459. /*****************************************************************************
  460.  
  461. FUNCTION:   IGestureString(syvGes, lpstr, cMac)
  462.  
  463. PURPOSE:        Convert the SYV for a gesture to a corresponding string
  464.  
  465. COMMENTS:
  466.  
  467.         the rgGestures table above maps the SYVs to the corresponding strings
  468.  
  469. *****************************************************************************/
  470.     {
  471.     int i, cLen=0;
  472.     BOOL    fFound = FALSE;
  473.  
  474.     // If this a Circled letter gesture
  475.     if (FIsAppGesture(syvGes))
  476.         {
  477.     // Form a string with "circle -"  prefix
  478.  
  479.         _fstrncpy(lpstr, szCircleG, sizeof(szCircleG));
  480.         if (syvGes >= SYV_CIRCLEUPA && syvGes <= SYV_CIRCLEUPZ)
  481.             lpstr[sizeof(szCircleG) - 1] = (BYTE)LOWORD(syvGes - SYV_CIRCLEUPA + 'A');
  482.         else 
  483.             lpstr[sizeof(szCircleG) - 1] = (BYTE)LOWORD(syvGes - SYV_CIRCLELOA + 'a');
  484.         lpstr[sizeof(szCircleG)] = '\0';
  485.         cLen = sizeof(szCircleG);
  486.         }
  487.     else
  488.         {
  489.     //Must be a command gesture, look in the table
  490.         for(i=0; i<(sizeof(rgGestures)/sizeof(SYVID)); ++i)
  491.             {
  492.             if(syvGes == rgGestures[i].syv)
  493.                 {
  494.                 cLen = _fstrlen(rgGestures[i].lpstr);
  495.                 cLen = min(cLen, cMac);
  496.                 _fstrncpy(lpstr, rgGestures[i].lpstr, cLen);
  497.                 fFound = TRUE;
  498.                 break;
  499.                 }
  500.             }
  501.  
  502.         }
  503.     return(cLen);
  504.     }
  505.  
  506.  
  507. BOOL PASCAL FDispatchMenu(HWND hwnd, WORD wParam, long lParam)
  508. /*****************************************************************************
  509.  
  510. FUNCTION:   FDispatchMenu(hwnd, wParam, lParam)
  511.  
  512. PURPOSE:        Executes the menu commands
  513.  
  514. COMMENTS:
  515.  
  516. *****************************************************************************/
  517.     {
  518.     BOOL fOk = hwnd != NULL;
  519.  
  520.     if (fOk)
  521.         {
  522.         switch (wParam)
  523.             {
  524.             case miHold:
  525.                 fHold = TRUE;
  526.                 EnableMenuItem(GetMenu(hwnd), miHold, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 
  527.                 EnableMenuItem(GetMenu(hwnd), miRelease, MF_BYCOMMAND | MF_ENABLED);
  528.                 DrawMenuBar(hwnd);
  529.                 break;
  530.  
  531.             case miRelease:
  532.                 fHold = FALSE;
  533.                 EnableMenuItem(GetMenu(hwnd), miRelease, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); 
  534.                 EnableMenuItem(GetMenu(hwnd), miHold, MF_BYCOMMAND | MF_ENABLED);
  535.                 DrawMenuBar(hwnd);
  536.                 break;
  537.  
  538.             default:
  539.                 fOk = FALSE;
  540.                 break;
  541.             }
  542.         }
  543.     return fOk;
  544.     }
  545.  
  546. VOID PASCAL CalcTopology(HWND hwndWindow)
  547. /*****************************************************************************
  548.  
  549. FUNCTION:   VOID CalcTopology(hwndWindow)
  550.  
  551. PURPOSE:        To calculate the relative positions of various items
  552.                 on the screen
  553.  
  554. COMMENTS:
  555.  
  556. *****************************************************************************/
  557.     {
  558.     HDC hDC;
  559.  
  560.     hDC = GetDC(hwndWindow);
  561.  
  562.     //Get the textmetrics for the default font in the device context
  563.     GetTextMetrics(hDC, &tm);
  564.  
  565.     grXText = LOWORD(GetTextExtent(hDC, szGraph, _fstrlen(szGraph)));
  566.     resXText = LOWORD(GetTextExtent(hDC, szResult, _fstrlen(szResult)));
  567.  
  568.     grOrg.y = grTOrg.y;
  569.     grOrg.x = grTOrg.x + max(grXText, resXText)+5;
  570.  
  571.     resOrg.x = grOrg.x;
  572.     resOrg.y = (int)(grOrg.y + 1.5 * tm.tmHeight+5);
  573.  
  574.     resTOrg.x = grTOrg.x;
  575.     resTOrg.y = resOrg.y;
  576.  
  577.     // Setup the negative offset for the pendata origin.
  578.     // The x and y values are chosen so that the ink is displayed
  579.     // just below the Hedit control showing the results
  580.  
  581.     ptInk.x = -grOrg.x;
  582.     ptInk.y = (int)(-(resTOrg.y+1.5 * tm.tmHeight+4));
  583.  
  584.     ReleaseDC(hwndWindow, hDC);
  585.     }
  586.  
  587. /***************************************************************************
  588.  
  589. FUNCTION:   RoHeditProc(hwnd, message, wParam, lParam)
  590.  
  591. PURPOSE:        Subclassed message handling procedure for the two edit controls.
  592.  
  593. COMMENTS:
  594.                 Handles only thw WM_SETCURSOR message. This is done in order
  595.                 not to show the pen cursor in a readonly edit control, to
  596.                 indicate that the control cannot be written into.
  597. ***************************************************************************/
  598. long FAR PASCAL __export RoHeditProc(HWND hwnd, unsigned message, WORD wParam, long lParam)
  599.     {
  600.     switch(message)
  601.         {
  602.         case WM_SETCURSOR:
  603.             SetCursor(hcurAltSelect);
  604.             //Tell windows we took care of it
  605.             return(0L);
  606.         }
  607.     // Pass on all the other messages to the original procedure(s)
  608.     CallWindowProc((hwnd==hwndGraph)?lpfnGraph:lpfnResult, hwnd, message, wParam, lParam);
  609.     }
  610.