2
0

winevent.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * Program type: API
  3. *
  4. * EVENTS.C -- Example events program
  5. *
  6. * Description: This program does an asynchronous event wait
  7. * on a trigger set up in the sales table of
  8. * employee.fdb.
  9. * Somebody must add a new sales order to alert
  10. * this program. That role can be accomplished
  11. * by running the api16t example program
  12. * after starting this program.
  13. *
  14. * Note: The system administrator needs to create the account
  15. * "guest" with password "guest" on the server before this
  16. * example can be run.
  17. * The contents of this file are subject to the Interbase Public
  18. * License Version 1.0 (the "License"); you may not use this file
  19. * except in compliance with the License. You may obtain a copy
  20. * of the License at http://www.Inprise.com/IPL.html
  21. *
  22. * Software distributed under the License is distributed on an
  23. * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  24. * or implied. See the License for the specific language governing
  25. * rights and limitations under the License.
  26. *
  27. * The Original Code was created by Inprise Corporation
  28. * and its predecessors. Portions created by Inprise Corporation are
  29. * Copyright (C) Inprise Corporation.
  30. *
  31. * All Rights Reserved.
  32. * Contributor(s): ______________________________________.
  33. */
  34. #include <windows.h>
  35. #include <windowsx.h>
  36. #include <ibase.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. /*
  40. ** Local Defines
  41. */
  42. #define USER "guest"
  43. #define PASSWORD "guest"
  44. #define DATABASE "employee.fdb"
  45. #define IDM_EXIT 1
  46. #define WM_DB_EVENT WM_USER + 1
  47. /*
  48. ** This is an event block defined to keep track of all the parameters
  49. ** used to queue and proecess events. A pointer to this structure
  50. ** will be passed as the user argument to gds_que_events.
  51. */
  52. typedef struct _EventBlk {
  53. char *EventBuf;
  54. char *ResultBuf;
  55. short length;
  56. long EventId;
  57. char *EventName;
  58. isc_callback lpAstProc;
  59. isc_db_handle DB;
  60. HWND hWnd;
  61. struct _EventBlk *NextBlk;
  62. } EVENTBLK;
  63. /*
  64. ** GLOBAL VARIABLES
  65. */
  66. char szAppName [] = "Events";
  67. HINSTANCE hInstance;
  68. ISC_STATUS_ARRAY status;
  69. /*
  70. ** FUNCTION PROTOTYPES
  71. */
  72. LRESULT CALLBACK _export WndProc (HWND, UINT, WPARAM, LPARAM) ;
  73. HWND InitApplication(int nCmdShow, HINSTANCE hPrevInstance);
  74. int InitEvent(EVENTBLK *lpEvent, long *DB,
  75. HWND hWnd, char *event);
  76. void ReleaseEvents(EVENTBLK *lpEvent);
  77. #ifdef __cplusplus
  78. extern "C" { /* Assume C declarations for C++ */
  79. #endif /* __cplusplus */
  80. void AstRoutine(EVENTBLK *result, short length,
  81. char *updated);
  82. #ifdef __cplusplus
  83. }
  84. #endif /* __cplusplus */
  85. void WinPrint(char*);
  86. int CHK_ERR(long *gds__status);
  87. /*****************************************************************
  88. *
  89. * WinMain
  90. *
  91. *****************************************************************
  92. *
  93. * Functional description
  94. * Description: Setup the dpb with the username and password
  95. * and attach to the database, employee.fdb.
  96. * If the attach was successful, allocate an event
  97. * control block and register interest in the
  98. * event "new_order".
  99. *
  100. *
  101. ****************************************************************/
  102. int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance,
  103. LPSTR lpszCmdLine, int nCmdShow)
  104. {
  105. MSG msg;
  106. isc_db_handle DB = NULL;
  107. HWND hWnd;
  108. EVENTBLK *lpEventNewOrder = NULL;
  109. char dpb[48];
  110. int i = 0, len;
  111. hInstance = hInst;
  112. hWnd = InitApplication(nCmdShow, hPrevInstance);
  113. if (!hWnd)
  114. {
  115. WinPrint("Unable to initialize main window");
  116. /* Get rid of warning for both Borland and Microsoft */
  117. lpszCmdLine = lpszCmdLine;
  118. return FALSE;
  119. }
  120. /* Format the dpb with the user name a password */
  121. dpb[i++] = isc_dpb_version1;
  122. dpb[i++] = isc_dpb_user_name;
  123. len = strlen (USER);
  124. dpb[i++] = (char) len;
  125. strncpy(&(dpb[i]), USER, len);
  126. i += len;
  127. dpb[i++] = isc_dpb_password;
  128. len = strlen (PASSWORD);
  129. dpb[i++] = len;
  130. strncpy(&(dpb[i]), PASSWORD, len);
  131. i += len;
  132. isc_attach_database(status, 0, DATABASE, &(DB), i, dpb);
  133. /* If the attach was successful, initialize the event handlers */
  134. if (!CHK_ERR(status))
  135. {
  136. /* Allocate our event control block to hold all the event parameters */
  137. lpEventNewOrder = (EVENTBLK *) GlobalAllocPtr(
  138. GMEM_MOVEABLE | GMEM_ZEROINIT,
  139. sizeof(EVENTBLK));
  140. /* Register interest in the "new_order" event */
  141. InitEvent(lpEventNewOrder, (long *)DB, hWnd, "new_order");
  142. }
  143. while (GetMessage(&msg, NULL, 0, 0))
  144. {
  145. TranslateMessage(&msg);
  146. DispatchMessage(&msg);
  147. }
  148. isc_detach_database(status, &DB);
  149. /* Release the allocated event blocks */
  150. ReleaseEvents(lpEventNewOrder);
  151. return msg.wParam;
  152. }
  153. /*****************************************************************
  154. *
  155. * InitApplication
  156. *
  157. *****************************************************************
  158. *
  159. * Functional description:
  160. * Registers the window class and displays the main window.
  161. * Returns:
  162. * window handle on success, FALSE otherwise
  163. *
  164. *****************************************************************/
  165. HWND InitApplication (int nCmdShow, HINSTANCE hPrevInstance)
  166. {
  167. WNDCLASS wndclass;
  168. HWND hWnd;
  169. if (!hPrevInstance)
  170. {
  171. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  172. wndclass.lpfnWndProc = WndProc;
  173. wndclass.cbClsExtra = 0;
  174. wndclass.cbWndExtra = 0;
  175. wndclass.hInstance = hInstance;
  176. wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  177. wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
  178. wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
  179. wndclass.lpszMenuName = szAppName;
  180. wndclass.lpszClassName = szAppName;
  181. if (!RegisterClass(&wndclass))
  182. return NULL;
  183. }
  184. if ((hWnd = CreateWindow(szAppName, "Event Test",
  185. WS_OVERLAPPEDWINDOW,
  186. CW_USEDEFAULT, CW_USEDEFAULT,
  187. CW_USEDEFAULT, CW_USEDEFAULT,
  188. NULL, NULL, hInstance, NULL)) == NULL )
  189. return NULL;
  190. ShowWindow(hWnd, nCmdShow);
  191. UpdateWindow(hWnd);
  192. return hWnd;
  193. }
  194. /*****************************************************************
  195. *
  196. * InitEvents
  197. *
  198. *****************************************************************
  199. *
  200. * Functional description:
  201. * Initialize the event_block, and queue interest in a particular
  202. * event.
  203. * Returns:
  204. * TRUE if success, FALSE if que_events failed.
  205. *
  206. *****************************************************************/
  207. int InitEvent (EVENTBLK *lpEvent, long *DB, HWND hWnd, char *event)
  208. {
  209. /* Allocate the event buffers and initialize the events of interest */
  210. lpEvent->length = (short)isc_event_block(&(lpEvent->EventBuf),
  211. &(lpEvent->ResultBuf),
  212. 1, event);
  213. /* Store any necessary parameters in the event block */
  214. lpEvent->lpAstProc = (isc_callback) MakeProcInstance((FARPROC) AstRoutine,
  215. hInstance);
  216. lpEvent->DB = DB;
  217. lpEvent->hWnd = hWnd;
  218. lpEvent->EventName = event;
  219. /* Request the server to notify when any of our events occur */
  220. isc_que_events(status, &(lpEvent->DB),
  221. &(lpEvent->EventId), lpEvent->length, lpEvent->EventBuf,
  222. lpEvent->lpAstProc, lpEvent);
  223. if (CHK_ERR(status))
  224. return FALSE;
  225. return TRUE;
  226. }
  227. /*****************************************************************
  228. *
  229. * ReleaseEvents
  230. *
  231. *****************************************************************
  232. *
  233. * Functional description:
  234. * Releases the event buffers allocated by isc_event_block
  235. * and releases the main event block.
  236. * Returns:
  237. * none
  238. *
  239. *****************************************************************/
  240. void ReleaseEvents (EVENTBLK *lpEvent)
  241. {
  242. if (lpEvent == NULL)
  243. return;
  244. isc_free(lpEvent->EventBuf);
  245. isc_free(lpEvent->ResultBuf);
  246. (VOID)GlobalFreePtr(lpEvent);
  247. }
  248. /*****************************************************************
  249. *
  250. * WndProc
  251. *
  252. *****************************************************************
  253. *
  254. * Functional description:
  255. * Main window processing function.
  256. * Returns:
  257. * 0 if the message was handled,
  258. * results from DefWindowProc otherwise
  259. *
  260. *****************************************************************/
  261. LRESULT CALLBACK _export WndProc (HWND hWnd, UINT message, WPARAM wParam,
  262. LPARAM lParam)
  263. {
  264. EVENTBLK *lpEvent;
  265. ISC_STATUS_ARRAY Vector;
  266. char msgbuf[200];
  267. switch (message)
  268. {
  269. case WM_COMMAND:
  270. switch (wParam)
  271. {
  272. case IDM_EXIT:
  273. SendMessage(hWnd, WM_CLOSE, 0, 0L);
  274. return 0;
  275. }
  276. break;
  277. case WM_DB_EVENT:
  278. /* The event block is passed in lParam by the ast */
  279. lpEvent = (EVENTBLK *)lParam;
  280. /*
  281. ** isc_event_counts will update Vector with the number
  282. ** of times each event occurred. It will then copy
  283. ** ResultBuf into EventBuf to prepare for the next que_events.
  284. */
  285. isc_event_counts(Vector, lpEvent->length, lpEvent->EventBuf,
  286. lpEvent->ResultBuf);
  287. sprintf(msgbuf, "Event %s triggered with count %ld\n...Resetting"
  288. " count and calling gds_que_events again",
  289. lpEvent->EventName, Vector[0]);
  290. WinPrint(msgbuf);
  291. /* Re-queue the event, so we can do this all over again */
  292. isc_que_events(status, &(lpEvent->DB), &(lpEvent->EventId),
  293. lpEvent->length, lpEvent->EventBuf,
  294. lpEvent->lpAstProc, lpEvent);
  295. CHK_ERR(status);
  296. return 0;
  297. case WM_DESTROY:
  298. PostQuitMessage(0);
  299. return 0;
  300. }
  301. return DefWindowProc(hWnd, message, wParam, lParam);
  302. }
  303. /*****************************************************************
  304. *
  305. * AstRoutine
  306. *
  307. *****************************************************************
  308. *
  309. * Functional description:
  310. * This is the callback routine which is called by the
  311. * gds library when an event occurs in the database.
  312. * The event block which was passed as an argument to
  313. * gds_que_events is received as the first argument,
  314. * along with the updated event buffer and its length.
  315. * Returns:
  316. * none
  317. *
  318. *****************************************************************/
  319. void AstRoutine (EVENTBLK *lpEvent, short length, char *updated)
  320. {
  321. char *ResultBuf = lpEvent->ResultBuf;
  322. /* Update the result buffer with the new values */
  323. while (length--)
  324. *ResultBuf++ = *updated++;
  325. /* Let the parent window know the event triggered */
  326. PostMessage(lpEvent->hWnd, WM_DB_EVENT, 0, (LPARAM) lpEvent);
  327. }
  328. /*****************************************************************
  329. *
  330. * WinPrint
  331. *
  332. *****************************************************************
  333. *
  334. * Functional description:
  335. * Print a message in a message box.
  336. * Returns:
  337. * none
  338. *
  339. *****************************************************************/
  340. void WinPrint (char *line)
  341. {
  342. MessageBox(NULL, line, szAppName, MB_ICONINFORMATION | MB_OK);
  343. }
  344. /*****************************************************************
  345. *
  346. * CHK_ERR
  347. *
  348. *****************************************************************
  349. *
  350. * Functional description:
  351. * If an error was returned in the status vector, print it
  352. * and the post a quit message to terminate the app.
  353. * Returns:
  354. * TRUE if there was error, FALSE otherwise
  355. *
  356. *****************************************************************/
  357. int CHK_ERR (long *status)
  358. {
  359. if (status[1])
  360. {
  361. isc_print_status(status);
  362. PostQuitMessage(1);
  363. return TRUE;
  364. }
  365. return FALSE;
  366. }