home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / power.zip / POWER.C < prev    next >
Text File  |  1994-11-09  |  47KB  |  909 lines

  1. /*______________________________________________________________________
  2. |                PowerThread  (c) 1994 Greg Ratajik                     |
  3. |-----------------------------------------------------------------------|
  4. |               You may use this code in your programs under the        |
  5. |               following conditions:                                   |
  6. |                                                                       |
  7. |               o  You keep this module seperate, with all comments     |
  8. |                  copyright notices intact (You can, of course add to  |
  9. |                  or change to fit your needs, I just ask that you     |
  10. |                  keep the main banners/info intact.)                  |
  11. |                                                                       |
  12. |               o  If you sell a product that uses this, I ask that     |
  13. |                  you put my name and contact info in it,  and what    |
  14. |                  you got out of it.  (This doesn't need to be in a    |
  15. |                  about box, but it would be nice at the end of the    |
  16. |                  credits of the .INF file, or DOC's.)                 |
  17. |                                                                       |
  18. |               Beyond that, go for it!  You're free to hack this up    |
  19. |               in any way that you need.  I'm not asking for any return|
  20. |               on this code, except (mabye?) to provide a quick and    |
  21. |               easy way for fellow OS/2 developers to thread their     |
  22. |               programs.                                               |
  23. |                                                                       |
  24. |                ---------------------------------------------------    |
  25. |               | Special Thanks to Ron Finlayson, for part of the  |   |
  26. |               | initial concept work on this.  It really helps to |   |
  27. |               | have someone to brain storm with! :)              |   |
  28. |                ---------------------------------------------------    |
  29. |                                                                       |
  30. |   *****************************************************************   |
  31. |   *DISCLAIMER OF WARRANTIES.  The following  code is              *   |
  32. |   *sample code created by Greg Ratajik.  The code is provided     *   |
  33. |   *"AS IS", without warranty of any kind.  Greg Ratatjik shall not*   |
  34. |   *be liable for any damages arising out of your use of the sample*   |
  35. |   *code.                                                          *   |
  36. |   *****************************************************************   |
  37. |                                                                       |
  38. |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
  39. | Description:  This module has two main functions in it, PowerCall and |
  40. |               PowerHABCall.  Both of them let an application call a   |
  41. |               function, while processing a PM message, without locking|
  42. |               up PM. The function calls can be treated like  normal   |
  43. |               function that runs consecutively to other function calls|
  44. |               (instead of posting messages back to the parent, or     |
  45. |               having a worker thread processing requests)             |
  46. |                                                                       |
  47. |               The basic flow of this program is:                      |
  48. |                                                                       |
  49. |               PowerHABCall():                                         |
  50. |                                                                       |
  51. |                  Get PM Message                                       |
  52. |                        |                                              |
  53. |                       \|/                                             |
  54. |                   Start Thread --------------                         |
  55. |                        |                    |                         |
  56. |                        |                    |                         |
  57. |                       \|/                  \|/                        |
  58. |                   Process Queue         Call Function                 |
  59. |                        |                    |                         |
  60. |                        |                    |                         |
  61. |                       \|/                  \|/                        |
  62. |                      Return <---------- Notify Function Done          |
  63. |                        |                                              |
  64. |                        |                                              |
  65. |                       \|/                                             |
  66. |                Continue Processing                                    |
  67. |                     Message                                           |
  68. |                                                                       |
  69. |               ======================================================= |
  70. |                                                                       |
  71. |               PowerCall():                                            |
  72. |                                                                       |
  73. |                  Get PM Message                                       |
  74. |                        |                                              |
  75. |                       \|/                                             |
  76. |                   Start Thread --------------                         |
  77. |                        |                    |                         |
  78. |                        |                    |                         |
  79. |                       \|/                  \|/                        |
  80. |                   Start DLG             Call Function                 |
  81. |             (Will process messages)         |                         |
  82. |                        |                    |                         |
  83. |                        |                    |                         |
  84. |                       \|/                  \|/                        |
  85. |                      Return <---------- Post Message To DLG           |
  86. |                        |                                              |
  87. |                        |                                              |
  88. |                       \|/                                             |
  89. |                Continue Processing                                    |
  90. |                     Message                                           |
  91. |                                                                       |
  92. |                                                                       |
  93. |               PowerHABCall is the most staight forward way, but you   |
  94. |               have to pass the HAB.  PowerCall is a little more       |
  95. |               complex, but if you want to display somthing to the user|
  96. |               while the thread is running (i.e. do a timer,and animate|
  97. |               the pointer while the thread is running...) or if you   |
  98. |               don't want to worry about getting the HAB, use          |
  99. |               it.                                                     |
  100. |                                                                       |
  101. |               For more information, and some thoughts on how to use   |
  102. |               this technique, see POWER.DOC                           |
  103. |                                                                       |
  104. |               If you have any questions and comments about this       |
  105. |               technique, you can get in touch with me at:             |
  106. |                                                                       |
  107. |               CompuServe          : 74555,542                         |
  108. |               Internet            : 74555.542@compuserve.com          |
  109. |               Voice               : (305)/340-7985                    |
  110. |               OS/2 ShareWare BBS  : (703)/385-4325                    |
  111. |                                                                       |
  112. | Version    Date       Change                    |
  113. | ------------    ---------  ----------------------------------------    |
  114. | 1.00        09-01-1994 Initial Development                |
  115. | 1.10        11-09-1994 Converted to 32BIT.                |
  116. |_____________________________________________________________________*/
  117. #define INCL_PM             /*  PM Support                           */
  118. #define INCL_DOSPROCESS     /*  Process and thread support           */
  119.  
  120. /*______________________________________________________________________
  121. |                                                                       |
  122. |                         System Includes                               |
  123. |_____________________________________________________________________*/
  124. #define _MT
  125.  
  126. #include <os2.h>            /* Base OS/2 Include                     */
  127. #include <stdlib.h>         /* malloc and free                       */
  128. #include <process.h>        /* _beginthread support                  */
  129.  
  130. /*______________________________________________________________________
  131. |                                                                       |
  132. |             Application Specific Includes & Defines                   |
  133. |_____________________________________________________________________*/
  134. #include "power.h"        /* Prototypes for PowerCalls              */
  135. #include "test.rch"       /* RC info for the DLG                    */
  136.  
  137. /*______________________________________________________________________
  138. |                                                                       |
  139. |  Gobal Local Variables                        |
  140. |_____________________________________________________________________*/
  141. #define STACK_SIZE   15000
  142.  
  143. BOOL   g_bDone = FALSE;  /* Used to tell message loop that thread is done  */
  144. USHORT g_usYPos = 1;
  145.  
  146. /*______________________________________________________________________
  147. |                                                                       |
  148. |  Gobal Local Structures                        |
  149. |_____________________________________________________________________*/
  150. /*____________________________________
  151. |                                     |
  152. | pfnFunctionAddr and hWnd            |
  153. | should be kept in the structure.    |
  154. | pUserParm should be whatever parm   |
  155. | needs to be passed to the user      |
  156. | function.  Any number of user parms |
  157. | can be added, but you must modify   |
  158. | the functions that use the structure|
  159. |____________________________________*/
  160. /*____________________________________
  161. |                                     |
  162. | The primary use of this structure   |
  163. | is to isolate the information that  |
  164. | needs to be passed to the thread.   |
  165. | (You can only pass ONE parm to a    |
  166. | thread) If you don't want to use a  |
  167. | structure, you can use globals.     |
  168. |____________________________________*/
  169. typedef struct _THREAD_CALL_INFO     /* Process Linkage Structure      */
  170.         {
  171.          void     *pfnFunctionAddr;  /* Address of Function to call    */
  172.          HWND      hWnd;             /* HWND of processing DLG.        */
  173.  
  174.          PVOID pUserParm;            /* User parm(s)...                */
  175.  
  176.         } THREAD_CALL_INFO, *PTHREAD_CALL_INFO;
  177.  
  178. /*____________________________________________________________________
  179. |                                      |
  180. |  Function Prototypes.                           |
  181. |____________________________________________________________________*/
  182. MRESULT EXPENTRY PowerCallWndProc  (HWND hWndDlg, ULONG ulMsg, MPARAM mp1, MPARAM mp2);
  183. MRESULT EXPENTRY PowerCallWndProc2 (HWND hWndDlg, ULONG ulMsg, MPARAM mp1, MPARAM mp2);
  184. MRESULT EXPENTRY FrameWindowMsgProc(HWND hWndDlg, ULONG ulMsg, MPARAM mp1, MPARAM mp2);
  185.  
  186. VOID CallFunction    ( PTHREAD_CALL_INFO);  /* Loader for PowerCall        */
  187. VOID CallFunction2   ( PTHREAD_CALL_INFO);  /* Loader for PowerCall        */
  188. VOID CallHABFunction ( PTHREAD_CALL_INFO);  /* Loader for PowerHABCall     */
  189.  
  190. /*__________________________________________________________________________
  191. |                                                                           |
  192. |    Function: PowerHABCall                                                 |
  193. |                                                                           |
  194. | Description: This function calls the passed function with the passed parm,|
  195. |              and then processes the message queue until the thread is done|
  196. |                                                                           |
  197. |              The result is that you can make the call to your function,   |
  198. |              and wait for it to return, without locking PM up.            |
  199. |                                                                           |
  200. |              This is Solution #1, which requires that HAB is passed.      |
  201. |              It should be possible to either have HAB as a global, or     |
  202. |              to ask the system what the HAB is for the process.           |
  203. |                                                                           |
  204. |      Return: BOOL  - You can use the structure to pass back your own      |
  205. |                      return value.  See CallHABFunction for more info.    |
  206. |                                                                           |
  207. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  208. |                            C H A N G E    L O G                           |
  209. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  210. |                                                                           |
  211. |  PRG.    DATE       DESCRIPTION                                           |
  212. |  ----    ---------- ---------------------------------------------------   |
  213. |  RATAJIK 11-01-1994 Initial Developement                                  |
  214. |__________________________________________________________________________*/
  215. BOOL PowerHABCall(HAB    hAB            ,
  216.                   PFN    pfnFunctionAddr,
  217.                   PVOID  pUserParm      )
  218. {
  219. PTHREAD_CALL_INFO ptciData = malloc(sizeof(THREAD_CALL_INFO));
  220. QMSG              qmsg;
  221. INT               pid;
  222.  
  223.  /*____________________________________
  224.  |                                     |
  225.  | Copy the call info to the comm.     |
  226.  | structure.                          |
  227.  |____________________________________*/
  228.  ptciData->pfnFunctionAddr = (void *)pfnFunctionAddr;
  229.  ptciData->pUserParm       = pUserParm;
  230.  
  231.  g_bDone = FALSE;
  232.  
  233.  /*____________________________________
  234.  |                                     |
  235.  | Start the Loader thread.  It will   |
  236.  | call the function passed in         |
  237.  | pfnFunctionAddr.                    |
  238.  |____________________________________*/
  239.  pid=_beginthread(CallHABFunction,   /* Address of the Loader Function     */
  240.                   NULL,              /* Use the programs stack             */
  241.                   STACK_SIZE,        /* Amount of the stack we want to use */
  242.                   (PVOID)ptciData);  /* Info for the Loader Function       */
  243.  
  244.  /*____________________________________
  245.  |                                     |
  246.  | Process messages until g_bDone is   |
  247.  | TRUE.  This, in effect, prevents PM |
  248.  | from locking up while we process the|
  249.  | message that called this function.  |
  250.  |____________________________________*/
  251.  while(WinGetMsg(hAB, (PQMSG)&qmsg, (HWND)NULL, 0, 0) && !g_bDone)
  252.      WinDispatchMsg(hAB, (PQMSG)&qmsg);
  253.  
  254.  /*____________________________________
  255.  |                                     |
  256.  | Free up the Data, and return.  If   |
  257.  | you want to return with another     |
  258.  | type/value, you can use the comm    |
  259.  | structure to pass it.               |
  260.  |____________________________________*/
  261.  free(ptciData);
  262.  return(TRUE);
  263. }
  264.  
  265. /*__________________________________________________________________________
  266. |                                                                           |
  267. |    Function: CallHABunction                                               |
  268. |                                                                           |
  269. | Description: This function is used to call the user function, with any    |
  270. |              parms needed.  When it is done, it will set g_bDone to TRUE, |
  271. |              which will tell the message processing loop to finish. If you|
  272. |              don't want to use a global, you can use another BOOL in the  |
  273. |              passed structure, or a semaphore.                            |
  274. |                                                                           |
  275. |      Return: VOID                                                         |
  276. |                                                                           |
  277. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  278. |                            C H A N G E    L O G                           |
  279. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  280. |                                                                           |
  281. |  PRG.    DATE       DESCRIPTION                                           |
  282. |  ----    ---------- ---------------------------------------------------   |
  283. |  RATAJIK 11-01-1994 Initial Developement                                  |
  284. |__________________________________________________________________________*/
  285. VOID CallHABFunction(PTHREAD_CALL_INFO ptciData)
  286. {
  287.  PFN pfnAddr;
  288.  
  289.  /*____________________________________
  290.  |                                     |
  291.  | Resolve the function address.       |
  292.  |                                     |
  293.  |____________________________________*/
  294.  pfnAddr = (PFN) ptciData->pfnFunctionAddr;
  295.  
  296.  /*____________________________________
  297.  |                                     |
  298.  | Call the function with the parm list|
  299.  | Add vars to the parm list as needed.|
  300.  |____________________________________*/
  301.  pfnAddr(ptciData->pUserParm);
  302.  
  303.  /*____________________________________
  304.  |                                     |
  305.  | Tell the while loop for the queue   |
  306.  | that we are done.                   |
  307.  |____________________________________*/
  308.  g_bDone = TRUE;
  309. }
  310.  
  311. /*__________________________________________________________________________
  312. |                                                                           |
  313. |    Function: PowerCall                                                    |
  314. |                                                                           |
  315. | Description: This function calls the passed function with the passed parm.|
  316. |              It will then do a WinDlgBox.  This will process any message  |
  317. |              untill the thread is done.  The WinDlgBox can also be used to|
  318. |              display a message to the user, while the thead is processing.|
  319. |                                                                           |
  320. |      Return: BOOL  - You can use the structure to pass back your own      |
  321. |                      return value.  See CallHABFunction for more info.    |
  322. |                                                                           |
  323. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  324. |                            C H A N G E    L O G                           |
  325. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  326. |                                                                           |
  327. |  PRG.    DATE       DESCRIPTION                                           |
  328. |  ----    ---------- ---------------------------------------------------   |
  329. |  RATAJIK 11-01-1994 Initial Developement                                  |
  330. |__________________________________________________________________________*/
  331. BOOL PowerCall(PFN   pfnFunctionAddr,
  332.                PVOID pUserParm      )
  333. {
  334. PTHREAD_CALL_INFO ptciData = malloc(sizeof(THREAD_CALL_INFO));
  335. INT               pid;
  336.  
  337.  /*____________________________________
  338.  |                                     |
  339.  | Copy the call info to the comm.     |
  340.  | structure.                          |
  341.  |____________________________________*/
  342.  ptciData->pfnFunctionAddr = (void *)pfnFunctionAddr;
  343.  ptciData->pUserParm       = pUserParm;
  344.  ptciData->hWnd            = NULLHANDLE;    /* The DLG will fill this out for us */
  345.  
  346.  /*____________________________________
  347.  |                                     |
  348.  | Start up the Loader thread.  It will|
  349.  | call the function passed in         |
  350.  | pfnFunctionAddr                     |
  351.  |____________________________________*/
  352.  pid=_beginthread(CallFunction,      /* Address of the Loader Function     */
  353.                   NULL,              /* Use the programs stack             */
  354.                   STACK_SIZE,        /* Amount of the stack we want to use */
  355.                   (PVOID)ptciData);  /* Info for the Loader Function       */
  356.  
  357.  /*____________________________________
  358.  |                                     |
  359.  | Run the DLG.  This has the same     |
  360.  | results as the message loop in      |
  361.  | PowerHABCall.                       |
  362.  |                                     |
  363.  | It will return when the thread posts|
  364.  | a message to it.                    |
  365.  |                                     |
  366.  | You could also do a WinCreateWindow,|
  367.  | and process message, but this way   |
  368.  | you can show somthing to the user.  |
  369.  |____________________________________*/
  370.  WinDlgBox(HWND_DESKTOP,
  371.            HWND_DESKTOP,
  372.            PowerCallWndProc,
  373.            0,
  374.            DLG_THREAD,
  375.            (PVOID)ptciData);    /* Pass this so DLG can get to hwnd   */
  376.  
  377.  /*____________________________________
  378.  |                                     |
  379.  | Free up the Data, and return.  If   |
  380.  | you want to return with another     |
  381.  | type/value, you can use the comm    |
  382.  | structure to pass it.               |
  383.  |____________________________________*/
  384.  free(ptciData);
  385.  return(TRUE);
  386. }
  387.  
  388. /*__________________________________________________________________________
  389. |                                                                           |
  390. |    Function: CallFunction                                                 |
  391. |                                                                           |
  392. | Description: This function is used to call the user function, with any    |
  393. |              parms needed.  When it is done, it will post a message back  |
  394. |              to the DLG to let it know it should dismiss itself.          |
  395. |                                                                           |
  396. |      Return: VOID                                                         |
  397. |                                                                           |
  398. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  399. |                            C H A N G E    L O G                           |
  400. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  401. |                                                                           |
  402. |  PRG.    DATE       DESCRIPTION                                           |
  403. |  ----    ---------- ---------------------------------------------------   |
  404. |  RATAJIK 11-01-1994 Initial Developement                                  |
  405. |__________________________________________________________________________*/
  406. VOID CallFunction(PTHREAD_CALL_INFO ptciData)
  407. {
  408.  PFN pfnAddr;
  409.  
  410.  /*____________________________________
  411.  |                                     |
  412.  | Resolve the function address.       |
  413.  |                                     |
  414.  |____________________________________*/
  415.  pfnAddr = (PFN)ptciData->pfnFunctionAddr;
  416.  
  417.  /*____________________________________
  418.  |                                     |
  419.  | Call the function with the parm list|
  420.  | Add vars to the parm list as needed.|
  421.  |____________________________________*/
  422.  pfnAddr(ptciData->pUserParm);
  423.  
  424.  /*____________________________________
  425.  |                                     |
  426.  | Tell the DLG that we are done.      |
  427.  |                                     |
  428.  |____________________________________*/
  429.  if(ptciData->hWnd)
  430.      WinPostMsg(ptciData->hWnd, WM_INITDLG, (MPARAM)7985, 0);
  431. }
  432.  
  433. /*__________________________________________________________________________
  434. |                                                                           |
  435. |    Function: PowerCallWndProc                                             |
  436. |                                                                           |
  437. | Description: This function acts as a message processor for the message    |
  438. |              queue.  When the thread is done, it will post a message to   |
  439. |              this DLG, which will cause the DLG to finish.                |
  440. |                                                                           |
  441. |              A semaphore might work better here, as it's possible the     |
  442. |              thread could finish before the DLG started. I've never       |
  443. |              had it happen yet, as beginthread general takes a while to   |
  444. |              start up.                                                    |
  445. |                                                                           |
  446. |      Return: MRESULT                                                      |
  447. |                                                                           |
  448. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  449. |                            C H A N G E    L O G                           |
  450. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  451. |                                                                           |
  452. |  PRG.    DATE       DESCRIPTION                                           |
  453. |  ----    ---------- ---------------------------------------------------   |
  454. |  RATAJIK 11-01-1994 Initial Developement                                  |
  455. |__________________________________________________________________________*/
  456. MRESULT EXPENTRY PowerCallWndProc(HWND hWndDlg, ULONG msg,MPARAM mp1, MPARAM mp2)
  457.  
  458. {
  459.    static PTHREAD_CALL_INFO ptciData;
  460.  
  461.    switch (msg)
  462.       {
  463.        /*____________________________________
  464.        |                                     |
  465.        | I'm using WM_INITDLG and 7985 to    |
  466.        | make this very simple.  You can add |
  467.        | your own message ID's if you like.  |
  468.        |____________________________________*/
  469.        case  WM_INITDLG:
  470.              {
  471.               /*____________________________________
  472.               |                                     |
  473.               | The thread will post this message to|
  474.               | us when it is done                  |
  475.               |____________________________________*/
  476.               if(mp1 == (MPARAM)7985)
  477.                  {
  478.                   g_usYPos-= 45;
  479.                   if(g_usYPos < 1)
  480.                       g_usYPos = 1;
  481.  
  482.                   WinDismissDlg(hWndDlg, TRUE);
  483.                  }
  484.               else
  485.                  {
  486.                   /*____________________________________
  487.                   |                                     |
  488.                   | mp2 will contain the comm structure.|
  489.                   | Put the current HWND in to it, so   |
  490.                   | the thread will know where to post  |
  491.                   | the "finished" message.             |
  492.                   |____________________________________*/
  493.                   ptciData = (MPARAM)mp2;
  494.  
  495.                   ptciData->hWnd = hWndDlg;
  496.  
  497.                   /*____________________________________
  498.                   |                                     |
  499.                   | Provide the Running/Wait animation. |
  500.                   |                                     |
  501.                   |____________________________________*/
  502.           WinSubclassWindow(WinWindowFromID(hWndDlg, FRAME_WAIT), FrameWindowMsgProc);
  503.  
  504.                   WinSendMsg( WinWindowFromID(hWndDlg, FRAME_WAIT),
  505.                               WM_CREATE,
  506.                               0, 0);
  507.  
  508.                   /*____________________________________
  509.                   |                                     |
  510.                   | If you don't want the DLG to display|
  511.                   | info to the user, do this (Makes    |
  512.                   | the DLG invisible)                  |
  513.                   |____________________________________*/
  514.           //WinSetWindowPos(hWndDlg, 0,
  515.                   //               0, 0, 0, 0, SWP_HIDE|SWP_MOVE|SWP_SIZE );
  516.  
  517.                   /*____________________________________
  518.                   |                                     |
  519.                   | Quick and easy hack to position     |
  520.                   | dialogs.                            |
  521.                   |____________________________________*/
  522.                   g_usYPos+= 50;
  523.                   if(g_usYPos > 4500)
  524.                     g_usYPos = 1;
  525.  
  526.                   /*____________________________________
  527.                   |                                     |
  528.                   | Otherwise, set the windows position.|
  529.                   |____________________________________*/
  530.                   WinSetWindowPos(hWndDlg, 0,
  531.                                  1, g_usYPos, 0,0, SWP_MOVE);
  532.  
  533.  
  534.                  }
  535.              }
  536.           break;
  537.  
  538.        default:
  539.            return(WinDefDlgProc(hWndDlg, msg, mp1, mp2));
  540.            break;
  541.  
  542.       }
  543.  
  544. return(FALSE);
  545. }
  546.  
  547. /*__________________________________________________________________________
  548. |                                                                           |
  549. |    Function: FrameWindowMsgProc                                           |
  550. |                                                                           |
  551. | Description: This function does a little animation in a frame.  It will   |
  552. |              cycle through the array of bitmaps.  You can replace these   |
  553. |              bitmaps with anything you like.  You may note that the       |
  554. |              this takes a fair amount of CPU time.  If you want to        |
  555. |              lessen the amount of CPU activity used for the animation,    |
  556. |              you can slow it down by increasing the WinStartTimer value.  |
  557. |                                                                           |
  558. |              (This was a last minute hack to show what you could do       |
  559. |               using the DLG version of PowerCall.  Feel free to improve   |
  560. |               it...)                                                      |
  561. |                                                                           |
  562. |      Return: MRESULT                                                      |
  563. |                                                                           |
  564. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  565. |                            C H A N G E    L O G                           |
  566. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  567. |                                                                           |
  568. |  PRG.    DATE       DESCRIPTION                                           |
  569. |  ----    ---------- ---------------------------------------------------   |
  570. |  RATAJIK 11-05-1994 Initial Developement                                  |
  571. |__________________________________________________________________________*/
  572. MRESULT EXPENTRY FrameWindowMsgProc(HWND hWndDlg, ULONG ulMsg, MPARAM mp1, MPARAM mp2)
  573. {
  574.  static HBITMAP hbBMP[BMP_RUN10]; /* Array of Bitmaps to display           */
  575.  static SHORT   sCur = 0;         /* Current Bitmap to display             */
  576.  static SHORT   sDir = 1;         /* Move foward or backwards in the array */
  577.  static BOOL    bFirst = TRUE;
  578.         INT     j;
  579.         HPS     hPS;
  580.         RECTL   rClient;
  581.  
  582.  /*_________________________________________
  583.  |                                          |
  584.  | Process messages from subclassed field.  |
  585.  |_________________________________________*/
  586.  switch(ulMsg)
  587.    {
  588.     case WM_CREATE:
  589.          /*____________________________________
  590.          |                                     |
  591.          | We want to start moving foward in   |
  592.          | the array.                          |
  593.          |____________________________________*/
  594.          sCur = -1;
  595.          sDir = 1;
  596.  
  597.          /*____________________________________
  598.          |                                     |
  599.          | The timer is used to force a re-    |
  600.          | paint the window ever x ms.  The    |
  601.          | actual calculations will be in      |
  602.          | WM_PAINT                            |
  603.          |____________________________________*/
  604.          WinStartTimer(0, hWndDlg, 0, 150);
  605.      break;
  606.  
  607.     case WM_TIMER:
  608.          /*____________________________________
  609.          |                                     |
  610.          | This will generate a WM_PAINT       |
  611.          |                                     |
  612.          |____________________________________*/
  613.          WinInvalidateRect(hWndDlg, NULL, TRUE);
  614.          break;
  615.  
  616.     case WM_PAINT:
  617.          /*____________________________________
  618.          |                                     |
  619.          | Get ready to paint..                |
  620.          |                                     |
  621.          |____________________________________*/
  622.          hPS = WinBeginPaint(hWndDlg, 0, 0);
  623.  
  624.          GpiSetBackColor(hPS, CLR_YELLOW);
  625.  
  626.          if(bFirst)
  627.             {
  628.              bFirst = FALSE;
  629.  
  630.              /*____________________________________
  631.              |                                     |
  632.              | Load the bitmaps into the array.    |
  633.              |                                     |
  634.              |____________________________________*/
  635.              for(j = BMP_RUN1; j < BMP_RUN10; j++)
  636.                {
  637.                 hbBMP[j-BMP_RUN1] = GpiLoadBitmap(hPS, 0, j, 0, 0);
  638.                }
  639.             }
  640.  
  641.          /*____________________________________
  642.          |                                     |
  643.          | Move the current index in the       |
  644.          | current direction.                  |
  645.          |____________________________________*/
  646.          sCur += sDir;
  647.  
  648.          /*____________________________________
  649.          |                                     |
  650.          | If we've gone beyond a boundry,     |
  651.          | start moving in the next direction. |
  652.          |____________________________________*/
  653.          if(sCur >= (BMP_RUN10 - BMP_RUN1))
  654.             sDir = -1;
  655.  
  656.          if(sCur <= 0)
  657.             sDir = 1;
  658.  
  659.          WinQueryWindowRect(hWndDlg, &rClient);
  660.  
  661.          /*____________________________________
  662.          |                                     |
  663.          | Display the bitmap, stretching to   |
  664.          | the frame.                          |
  665.          |____________________________________*/
  666.          WinDrawBitmap(hPS, hbBMP[sCur], NULL, (POINTL *)&rClient, (LONG)1, (LONG)2, DBM_IMAGEATTRS|DBM_STRETCH);
  667.      WinEndPaint(hPS);
  668.  
  669.          break; /* End of WM_PAINT */
  670.    }
  671.  
  672.  return WinDefDlgProc(hWndDlg, ulMsg, mp1, mp2);
  673. }
  674.  
  675.  
  676. /*__________________________________________________________________________
  677. |                                                                           |
  678. |    Function: PowerCall                                                    |
  679. |                                                                           |
  680. | Description: This function calls the passed function with the passed parm.|
  681. |              It will then do a WinDlgBox.  This will process any message  |
  682. |              untill the thread is done.  The WinDlgBox can also be used to|
  683. |              display a message to the user, while the thead is processing.|
  684. |                                                                           |
  685. |      Return: BOOL  - You can use the structure to pass back your own      |
  686. |                      return value.  See CallHABFunction for more info.    |
  687. |                                                                           |
  688. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  689. |                            C H A N G E    L O G                           |
  690. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  691. |                                                                           |
  692. |  PRG.    DATE       DESCRIPTION                                           |
  693. |  ----    ---------- ---------------------------------------------------   |
  694. |  RATAJIK 11-01-1994 Initial Developement                                  |
  695. |__________________________________________________________________________*/
  696. BOOL PowerCall2(PFN   pfnFunctionAddr,
  697.                 PVOID pUserParm      )
  698. {
  699. PTHREAD_CALL_INFO ptciData = malloc(sizeof(THREAD_CALL_INFO));
  700.  
  701.  /*____________________________________
  702.  |                                     |
  703.  | Copy the call info to the comm.     |
  704.  | structure.                          |
  705.  |____________________________________*/
  706.  ptciData->pfnFunctionAddr = (void *)pfnFunctionAddr;
  707.  ptciData->pUserParm       = pUserParm;
  708.  ptciData->hWnd            = NULLHANDLE;  /* The DLG will fill this out for us */
  709.  
  710.  /*____________________________________
  711.  |                                     |
  712.  | Run the DLG.  This has the same     |
  713.  | results as the message loop in      |
  714.  | PowerHABCall.                       |
  715.  |                                     |
  716.  | It will return when the thread posts|
  717.  | a message to it.                    |
  718.  |                                     |
  719.  | You could also do a WinCreateWindow,|
  720.  | and process message, but this way   |
  721.  | you can show somthing to the user.  |
  722.  |____________________________________*/
  723.  WinDlgBox(HWND_DESKTOP,
  724.            HWND_DESKTOP,
  725.            PowerCallWndProc2,
  726.            0,
  727.            DLG_THREAD,
  728.            (PVOID)ptciData);    /* Pass this so DLG can get to hwnd   */
  729.  
  730.  /*____________________________________
  731.  |                                     |
  732.  | Free up the Data, and return.  If   |
  733.  | you want to return with another     |
  734.  | type/value, you can use the comm    |
  735.  | structure to pass it.               |
  736.  |____________________________________*/
  737.  free(ptciData);
  738.  return(TRUE);
  739. }
  740.  
  741. /*__________________________________________________________________________
  742. |                                                                           |
  743. |    Function: CallFunction                                                 |
  744. |                                                                           |
  745. | Description: This function is used to call the user function, with any    |
  746. |              parms needed.  When it is done, it will post a message back  |
  747. |              to the DLG to let it know it should dismiss itself.          |
  748. |                                                                           |
  749. |      Return: VOID                                                         |
  750. |                                                                           |
  751. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  752. |                            C H A N G E    L O G                           |
  753. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  754. |                                                                           |
  755. |  PRG.    DATE       DESCRIPTION                                           |
  756. |  ----    ---------- ---------------------------------------------------   |
  757. |  RATAJIK 11-01-1994 Initial Developement                                  |
  758. |__________________________________________________________________________*/
  759. VOID CallFunction2(PTHREAD_CALL_INFO ptciData)
  760. {
  761.  PFN pfnAddr;
  762.  
  763.  /*____________________________________
  764.  |                                     |
  765.  | Resolve the function address.       |
  766.  |                                     |
  767.  |____________________________________*/
  768.  pfnAddr = (PFN)ptciData->pfnFunctionAddr;
  769.  
  770.  /*____________________________________
  771.  |                                     |
  772.  | Call the function with the parm list|
  773.  | Add vars to the parm list as needed.|
  774.  |____________________________________*/
  775.  pfnAddr(ptciData->pUserParm);
  776.  
  777.  /*____________________________________
  778.  |                                     |
  779.  | Tell the DLG that we are done.      |
  780.  |                                     |
  781.  |____________________________________*/
  782.  if(ptciData->hWnd)
  783.      WinPostMsg(ptciData->hWnd, WM_INITDLG, (MPARAM)7985, 0);
  784. }
  785.  
  786. /*__________________________________________________________________________
  787. |                                                                           |
  788. |    Function: PowerCallWndProc2                                            |
  789. |                                                                           |
  790. | Description: This function acts as a message processor for the message    |
  791. |              queue.  When the thread is done, it will post a message to   |
  792. |              this DLG, which will cause the DLG to finish.                |
  793. |                                                                           |
  794. |              A semaphore might work better here, as it's possible the     |
  795. |              thread could finish before the DLG started. I've never       |
  796. |              had it happen yet, as beginthread general takes a while to   |
  797. |              start up.                                                    |
  798. |                                                                           |
  799. |      Return: MRESULT                                                      |
  800. |                                                                           |
  801. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  802. |                            C H A N G E    L O G                           |
  803. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- |
  804. |                                                                           |
  805. |  PRG.    DATE       DESCRIPTION                                           |
  806. |  ----    ---------- ---------------------------------------------------   |
  807. |  RATAJIK 11-01-1994 Initial Developement                                  |
  808. |__________________________________________________________________________*/
  809. MRESULT EXPENTRY PowerCallWndProc2(HWND hWndDlg, ULONG msg,MPARAM mp1, MPARAM mp2)
  810.  
  811. {
  812.    static PTHREAD_CALL_INFO ptciData;
  813.           INT               pid;
  814.  
  815.    switch (msg)
  816.       {
  817.        /*____________________________________
  818.        |                                     |
  819.        | I'm using WM_INITDLG and 7985 to    |
  820.        | make this very simple.  You can add |
  821.        | your own message ID's if you like.  |
  822.        |____________________________________*/
  823.        case  WM_INITDLG:
  824.              {
  825.               /*____________________________________
  826.               |                                     |
  827.               | The thread will post this message to|
  828.               | us when it is done                  |
  829.               |____________________________________*/
  830.               if(mp1 == (MPARAM)7985)
  831.                  {
  832.                   g_usYPos-= 45;
  833.                   if(g_usYPos < 1)
  834.                       g_usYPos = 1;
  835.  
  836.                   WinDismissDlg(hWndDlg, TRUE);
  837.                  }
  838.               else
  839.                  {
  840.                   /*____________________________________
  841.                   |                                     |
  842.                   | mp2 will contain the comm structure.|
  843.                   | Put the current HWND in to it, so   |
  844.                   | the thread will know where to post  |
  845.                   | the "finished" message.             |
  846.                   |____________________________________*/
  847.                   ptciData = (MPARAM)mp2;
  848.  
  849.                   ptciData->hWnd = hWndDlg;
  850.  
  851.                   /*____________________________________
  852.                   |                                     |
  853.                   | Provide the Running/Wait animation. |
  854.                   |                                     |
  855.                   |____________________________________*/
  856.           WinSubclassWindow(WinWindowFromID(hWndDlg, FRAME_WAIT), FrameWindowMsgProc);
  857.  
  858.                   WinSendMsg( WinWindowFromID(hWndDlg, FRAME_WAIT),
  859.                               WM_CREATE,
  860.                               0, 0);
  861.  
  862.                   /*____________________________________
  863.                   |                                     |
  864.                   | If you don't want the DLG to display|
  865.                   | info to the user, do this (Makes    |
  866.                   | the DLG invisible)                  |
  867.                   |____________________________________*/
  868.           //WinSetWindowPos(hWndDlg, 0,
  869.                   //               0, 0, 0, 0, SWP_HIDE|SWP_MOVE|SWP_SIZE );
  870.  
  871.                   /*____________________________________
  872.                   |                                     |
  873.                   | Quick and easy hack to position     |
  874.                   | dialogs.                            |
  875.                   |____________________________________*/
  876.                   g_usYPos+= 50;
  877.                   if(g_usYPos > 450)
  878.                     g_usYPos = 1;
  879.  
  880.                   /*____________________________________
  881.                   |                                     |
  882.                   | Otherwise, set the windows position.|
  883.                   |____________________________________*/
  884.                   WinSetWindowPos(hWndDlg, 0,
  885.                                  1, g_usYPos, 0, 0, SWP_MOVE);
  886.  
  887.                   /*____________________________________
  888.                   |                                     |
  889.                   | Start up the Loader thread.  It will|
  890.                   | call the function passed in         |
  891.                   | pfnFunctionAddr                     |
  892.                   |____________________________________*/
  893.                   pid=_beginthread(CallFunction2,     /* Address of the Loader Function     */
  894.                                    NULL,              /* Use the programs stack             */
  895.                                    STACK_SIZE,        /* Amount of the stack we want to use */
  896.                                    (PVOID)ptciData);  /* Info for the Loader Function       */
  897.                  }
  898.              }
  899.           break;
  900.  
  901.        default:
  902.            return(WinDefDlgProc(hWndDlg, msg, mp1, mp2));
  903.            break;
  904.  
  905.       }
  906.  
  907. return(FALSE);
  908. }
  909.