home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_lrn / hooks / journal / readme.doc < prev    next >
Encoding:
Text File  |  1988-02-22  |  9.8 KB  |  269 lines

  1.    The sample code provided with this Application Note demonstrates the
  2. use of Journal Hooks, WH_JOURNALRECORD and WH_JOURNALPLAYBACK.  The
  3. application, APP, serves only one purpose; it illustrates how to call
  4. the dynamic link library which does all of the journalling work.  The
  5. DLL calls, to record and playback messages are made from the application
  6. module, WNDPROC.C.  The DLL file, JOURNAL.C, contains all of the code
  7. necessary for creating a file of event messages for later playback.
  8. The code should allow quick creation of "hands off" demos for any
  9. application simply having the application call the DLL high-level
  10. functions.
  11.    As an example a file, DIARY.BIN, has been included which demos the
  12. application included with this Apnote.  After running APP.EXE, select
  13. Play from the menu.  Each time Record On is selected from the menu,
  14. DIARY.BIN is overwritten.  Save copies of DIARY.BIN which you do not
  15. want to be destroyed.
  16.    Listed below are general notes on programming all hooks including
  17. journal record and playback.  This memo was prepared after the
  18. Windows 2.03 SDK documentation was printed and better reflects the
  19. hook functions and their use.  The Windows 2.03 SDK Update Document also
  20. has useful hook function information.
  21.  
  22. ==========================================================================
  23.  
  24. Setting A Hook
  25.  
  26. ==========================================================================
  27.  
  28.     /*
  29.      * Make proc instance for the hook, and install, saving the old
  30.      *      hook (which may be NULL)
  31.      */
  32.  
  33.     qprcOurs    = (FARPROC)MakeProcInstance((FARPROC)Hook, hins);
  34.     qprcOld     = (FARPROC)SetWindowsHook(WH_ANY, qprcOurs);
  35.  
  36.     /*
  37.      * Notes:
  38.      *
  39.      *  (1) hins is a handle to our module instance
  40.      *
  41.      *  (2) Hook is our call-back function called by Windows
  42.      *      It should be declared as:
  43.      *          DWORD far pascal Hook (int, WORD, DWORD)
  44.      *      The semantics specific to each hook are below.
  45.      *
  46.      *  (3) qprcOurs and qprcOld are declared FARPROC, and are
  47.      *      likely to be global variables
  48.      *
  49.      *  (4) WH_ANY is any of the Windows Hook codes:
  50.      *          WH_MSGFILTER
  51.      *          WH_JOURNALRECORD
  52.      *          WH_JOURNALPLAYBACK
  53.      *          WH_KEYBOARD
  54.      *          WH_GETMESSAGE
  55.      *          WH_CALLWNDPROC
  56.      *          WH_SYSMSGFILTER
  57.      */
  58.  
  59.  
  60.  
  61. ==========================================================================
  62.  
  63. Removing A Hook
  64.  
  65. ==========================================================================
  66.  
  67.     /*
  68.      * Unhook our hook, and free the proc instance
  69.      */
  70.  
  71.     fSuccess = (BOOL)UnhookWindowsHook(WH_ANY, qprcOurs);
  72.     FreeProcInstance(qprcOurs);
  73.  
  74.     /*
  75.      * Notes:
  76.      *
  77.      *  (1) fSuccess is TRUE is the hook was successfully removed
  78.      *      from the hook chain.  Otherwise it is FALSE.
  79.      *
  80.      *  (2) Obviously, WH_ANY and qprcOurs must correspond to
  81.      *      those arguments used in SetWindowsHook.
  82.  
  83.  
  84.  
  85. ==========================================================================
  86.  
  87. General Notes on Hook Callback Functions
  88.  
  89. ==========================================================================
  90.  
  91.     /*
  92.      *  ALL hooks in Win 2.0 have the same syntactic definition:
  93.      *          DWORD far pascal Hook (int, WORD, DWORD)
  94.      *  (Note that this is different from the current edition
  95.      *  of the documentation, which describes the varying interfaces
  96.      *  of current retail Windows.
  97.      *
  98.      *  All hooks have the following general layout:
  99.      */
  100.  
  101.     DWORD far pascal Hook (hc, wParam, lParam)
  102.     int hc;
  103.     WORD wParam;
  104.     DWORD lParam;
  105.     {
  106.         switch (hc) {
  107.         case ...
  108.  
  109.             break;
  110.         case ...
  111.  
  112.             break;
  113.         default:
  114.             return(DefHookProc(hc, wParam, lParam,
  115.                                (FARPROC far *)&qprcOld);
  116.         }
  117.     return(0L);
  118.     }
  119.  
  120.     /*
  121.      *  The only variation in the hooks are what they do, and the
  122.      *  particular values of hc, the hook code, that are sent to them.
  123.      *
  124.      *  NOTE that all hc's you don't deal with MUST be passed
  125.      *  through the DefHookProc as shown above.
  126.      *
  127.      *  The return value, unless otherwise noted, (and excluding the
  128.      *  stuff returned by DefHookProc), takes either of two values:
  129.      *  FALSE   Windows performs normal handling on the event.
  130.      *  TRUE    Windows discards the event as if it never happened.
  131.      */
  132.  
  133.  
  134.  
  135. ==========================================================================
  136.  
  137. Definitions Of Particular Hook Callback Functions
  138.  
  139. ==========================================================================
  140.  
  141.     /*
  142.      * WH_MSGFILTER
  143.      *
  144.      *  The hook codes (hc) here are the various MSGF constants:
  145.      *      MSGF_DIALOGBOX
  146.      *      MSGF_MESSAGEBOX
  147.      *      MSGF_MENU
  148.      *      MSGF_MOVE
  149.      *      MSGF_SIZE
  150.      *      MSGF_SCROLLBAR
  151.      *      MSGF_NEXTWINDOW
  152.      *  wParam is unused.
  153.      *  lParam contains a long pointer to the message (LPMSG)
  154.      *
  155.      *  NOTE that this hook will only provide you with messages that
  156.      *  are destined for the task which sets the hook.  Use the
  157.      *  WH_SYSMSGFILTER to intercept messages destined for any task.
  158.      */
  159.  
  160.  
  161.  
  162.     /*
  163.      * WH_KEYBOARD
  164.      *
  165.      *  The only hc of interest in HC_ACTION.
  166.      *  wParam has the virtual keycode (VK_*)
  167.      *  lParam has the same contents as lParam in a WM_KEYDOWN message.
  168.      *
  169.      */
  170.  
  171.  
  172.  
  173.     /*
  174.      * WH_JOURNALPLAYBACK
  175.      *
  176.      *  There are two hook codes of interest:
  177.      *
  178.      *  HC_GETNEXT
  179.      *  wParam is unused.
  180.      *  lParam is a long pointer to a SQE structure (LPSQE)
  181.      *      where the hook is to put the current messsage to playback.
  182.      *
  183.      *  HC_SKIP
  184.      *  wParam is unused.
  185.      *  lParam is unused.
  186.      *
  187.      *  The SQE (System Queue Event) is like a MSG structure:
  188.      *  typedef struct {
  189.      *      unsigned message;
  190.      *      WORD wParam1;
  191.      *      WORD wParam2;
  192.      *      long lParam;
  193.      *  } SQE;
  194.      *  I can't really tell you much about the second word paramter,
  195.      *  since I make these things from the WH_JOURNALRECORD hook,
  196.      *  which fills it in.  The message is a regular Window
  197.      *  message (WM_*), the wParam1 is pretty much the same as
  198.      *  the wParam for a regular window message, (e.g. a VK_*
  199.      *  for a message of WM_KEYDOWN), and the lParam is the current time
  200.      *  (expressed as the number of timer ticks since system
  201.      *  generation--see GetTickCount()).
  202.      *
  203.      *  The hook is used as follows.  Windows, after this hook
  204.      *  is installed, disables hardware input.  It will call this
  205.      *  hook in lieu of using the system queue until the hook is removed
  206.      *  via UnhookWindowsHook.  Whenever the hook gets a HC_GETNEXT,
  207.      *  it should poke a SQE through the long pointer given in the
  208.      *  lParam and return the time in timer ticks that needs to
  209.      *  elapse before the event is ready to be played.  The lParam
  210.      *  field of the SQE should also contain the time (not delta
  211.      *  time) to play the event.  If the time to play the event is
  212.      *  now, or has passed, this hook should return 0L.  Whenever
  213.      *  the hook gets a HC_SKIP, it should fetch the next event to
  214.      *  poke through the lParam when it next gets a HC_GETNEXT,
  215.      *  i.e. it should prepare, but not do it.
  216.      *
  217.      *  NOTES:
  218.      *  - The hook may be called mutiple times with HC_GETNEXT
  219.      *      before getting a HC_SKIP.  The hook should keep returning
  220.      *      the same event through the lParam (with the same
  221.      *      time-to-be-played in the lParam of the SQE), and a
  222.      *      decreasing elpased-time-until-event until it becomes
  223.      *      0L, whereafter it returns 0L.
  224.      *  - The first message the hook gets (of these two) can be either
  225.      *      HC_SKIP or HC_GETNEXT.  This is different from Win 1.0.
  226.      *      Your initialization code should be invariant.  (I do my
  227.      *      initialization when I set the hook.)
  228.      *  - If you want to turn the hook off from within the hook, call
  229.      *      UnhookWindowsHook from the HC_SKIP case only.  Anything
  230.      *      else will cause execution to waltz off into the ether.
  231.      *  - If you want to play events as fast as possible, you'll find
  232.      *      that simply returning 0L for every HC_GETNEXT and setting
  233.      *      the play time to the current time won't work.  (You hang).
  234.      *      I've had success using the mouse double-click speed +1 as
  235.      *      the minimum time delay between events (except where the
  236.      *      actual event times are less).
  237.      */
  238.  
  239.  
  240.  
  241.     /*
  242.      * WH_JOURNALRECORD
  243.      *
  244.      *  The hook code of interest is HC_ACTION.
  245.      *  wParam is unused.
  246.      *  lParam is a long pointer to a SQE structure (LPSQE)
  247.      *      with the current message.
  248.      *
  249.      *  The SQE structure is identical to that used by the
  250.      *  WH_JOURNALPLAYBACK structure.  (see above).
  251.      *
  252.      *  I use this hook to record a sequence of user-initiated
  253.      *  events which I later playback, but there are other
  254.      *  uses I imagine.  Since the system time when one records
  255.      *  and when one plays back the recording will, in general,
  256.      *  be different, I keep a global variable around containing
  257.      *  the time at the start of the sequence, and store elapsed
  258.      *  times in the lParam of the SQE.  When I playback the
  259.      *  sequence, I convert those elapsed times into current
  260.      *  times by the inverse operation.
  261.      *
  262.      *  You'll probably wnat to signal your program to turn this
  263.      *  hook off with some special keystroke.  Be sure to turn
  264.      *  it off after the WM_KEYUP.  Turning it off after the
  265.      *  WM_KEYDOWN can have unpredictable results.
  266.      *
  267.      *  The return value from HC_ACTION is ignored.  Return 0L.
  268.      */
  269.