home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / winsock / globchat / client / globcl.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  15KB  |  543 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   globcl.c
  9. //
  10. //  PURPOSE:   Implement the windows procedure for the main application
  11. //    windows.  Also implement the generic message and command dispatchers.
  12. //
  13. //  FUNCTIONS:
  14. //    WndProc           - Processes messages for the main window.
  15. //    MsgCreate         - Initializes Edit Controls for text input/output.
  16. //    MsgSize           - Adjusts size of Edit Controls when window is resized.
  17. //    MsgSetfocus       - Keeps window focus on edit control instead of parent.
  18. //    MsgDataready      - Reads data from incoming IPC mechanism.
  19. //    MsgRefreshdisplay - Refills Inbox edit control text contents
  20. //    MsgDisconnected   - Cleans up connection killed by other side
  21. //    MsgCommand        - Handle the WM_COMMAND messages for the main window.
  22. //    MsgDestroy        - Handles the WM_DESTROY message by calling
  23. //                        PostQuitMessage().
  24. //    CmdOutbox         - Handles messages from Outbox edit control.
  25. //    CmdDisconnected   - Disconnects current connection
  26. //    CmdEndChat        - Ends Peer to Peer session
  27. //    CmdExit           - Handles the file exit command by calling destory
  28. //                        window on the main window.
  29. //
  30. //  COMMENTS:
  31. //
  32.  
  33. #include <windows.h>            // required for all Windows applications
  34. #include <windowsx.h>
  35. #include <wsipx.h>
  36. #include <wsnetbs.h>
  37. #include <nspapi.h>
  38. #include "globals.h"            // prototypes specific to this application
  39.  
  40.  
  41. // Main window message table definition.
  42. MSD rgmsd[] =
  43. {
  44.     {WM_CREATE,         MsgCreate},
  45.     {WM_SIZE,           MsgSize},
  46.     {WM_SETFOCUS,       MsgSetfocus},
  47.     {WM_COMMAND,        MsgCommand},
  48.     {WM_DESTROY,        MsgDestroy},
  49.     {MW_DATAREADY,      MsgDataready},
  50.     {MW_DISCONNECTED,   MsgDisconnected},
  51.     {MW_DISPLAYREFRESH, MsgRefreshdisplay}
  52. };
  53.  
  54. MSDI msdiMain =
  55. {
  56.     sizeof(rgmsd) / sizeof(MSD),
  57.     rgmsd,
  58.     edwpWindow
  59. };
  60.  
  61.  
  62. // Main window command table definition.
  63. CMD rgcmd[] =
  64. {
  65.     {IDM_CONNECT,           CmdConnect},
  66.     {IDM_SELECT,            CmdSelect},
  67.     {IDM_EXIT,              CmdExit},
  68.     {IDM_ABOUT,             CmdAbout},
  69.     {ID_OUTBOX,             CmdOutbox},
  70.     {IDM_DISCONNECT_SERVER, CmdDisconnect},
  71.     {IDM_END_CHAT,          CmdEndChat}
  72. };
  73.  
  74. CMDI cmdiMain =
  75. {
  76.     sizeof(rgcmd) / sizeof(CMD),
  77.     rgcmd,
  78.     edwpWindow
  79. };
  80.  
  81.  
  82. //
  83. //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
  84. //
  85. //  PURPOSE:  Processes messages for the main window.
  86. //
  87. //  PARAMETERS:
  88. //    hwnd     - window handle
  89. //    uMessage - message number
  90. //    wparam   - additional information (dependant on message number)
  91. //    lparam   - additional information (dependant on message number)
  92. //
  93. //  RETURN VALUE:
  94. //    The return value depends on the message number.  If the message
  95. //    is implemented in the message dispatch table, the return value is
  96. //    the value returned by the message handling function.  Otherwise,
  97. //    the return value is the value returned by the default window procedure.
  98. //
  99. //  COMMENTS:
  100. //    Call the DispMessage() function with the main window's message dispatch
  101. //    information (msdiMain) and the message specific information.
  102. //
  103.  
  104. LRESULT CALLBACK WndProc(HWND   hwnd,
  105.                          UINT   uMessage,
  106.                          WPARAM wparam,
  107.                          LPARAM lparam)
  108. {
  109.     return DispMessage(&msdiMain, hwnd, uMessage, wparam, lparam);
  110. }
  111.  
  112. //
  113. //  FUNCTION: MsgCreate(HWND, UINT, WPARAM, LPARAM)
  114. //
  115. //  PURPOSE: Creates Inbox and Outbox Edit controls
  116. //
  117. //  PARAMETERS:
  118. //
  119. //    hwnd      - Window handle
  120. //    uMessage  - Message number (Unused)
  121. //    wparam    - Extra data     (Unused)
  122. //    lparam    - Extra data     (Unused)
  123. //
  124. //  RETURN VALUE:
  125. //
  126. //    Always returns 0 - Message handled
  127. //
  128. //  COMMENTS:
  129. //
  130. //
  131.  
  132. LRESULT MsgCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  133. {
  134.     // Create Edit control for typing to be sent to server
  135.     hOutWnd = CreateWindow("EDIT",
  136.                            NULL,
  137.                            WS_BORDER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
  138.                            ES_MULTILINE | ES_AUTOVSCROLL,
  139.                            0,0,0,0,
  140.                            hwnd,
  141.                            (HMENU) ID_OUTBOX,
  142.                            (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
  143.                            0);
  144.     // Create Edit control for typing to be received from server
  145.     hInWnd = CreateWindow("EDIT",
  146.                           NULL,
  147.                           WS_BORDER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
  148.                           ES_MULTILINE | ES_AUTOVSCROLL,
  149.                           0,0,0,0,
  150.                           hwnd,
  151.                           (HMENU) ID_INBOX,
  152.                           (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
  153.                           0);
  154.  
  155.     return (TRUE);
  156. }
  157.  
  158. //
  159. //  FUNCTION: MsgSize(HWND, UINT, WPARAM, LPARAM)
  160. //
  161. //  PURPOSE: Adjust Size of Inbox and Outbox Edit controls
  162. //
  163. //  PARAMETERS:
  164. //
  165. //    hwnd      - Window handle
  166. //    uMessage  - Message number (Unused)
  167. //    wparam    - Extra data     (Unused)
  168. //    lparam    - Parent Window Size
  169. //
  170. //  RETURN VALUE:
  171. //
  172. //    Always returns 0 - Message handled
  173. //
  174. //  COMMENTS:
  175. //
  176. //
  177.  
  178. LRESULT MsgSize(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  179. {
  180.     // Size OutBox Edit Control
  181.     MoveWindow(hOutWnd,
  182.                1,1,                    // Upper Left Corner
  183.                LOWORD(lparam) - 2,         // Width of Parent Window
  184.                (HIWORD(lparam) / 2) - 2 ,     // Half the height of Parent
  185.                TRUE);                  // repaint
  186.  
  187.     // Size Inbox Edit Control
  188.     MoveWindow(hInWnd,
  189.                1, (HIWORD(lparam) / 2) + 1,  // Half Way down right side
  190.                LOWORD(lparam) - 2,         // Width of Parent Window
  191.                (HIWORD(lparam) / 2) - 2,      // Half the height of Parent
  192.                TRUE);                  // repaint
  193.     return (TRUE);
  194. }
  195.  
  196. //
  197. //  FUNCTION: MsgSetfocus(HWND, UINT, WPARAM, LPARAM)
  198. //
  199. //  PURPOSE: Keeps Window focus on edit control
  200. //
  201. //  PARAMETERS:
  202. //
  203. //    hwnd      - Window handle
  204. //    uMessage  - Message number (Unused)
  205. //    wparam    - Extra data     (Unused)
  206. //    lparam    - Extra data     (Unused)
  207. //
  208. //  RETURN VALUE:
  209. //
  210. //    Always returns 0 - Message handled
  211. //
  212. //  COMMENTS:
  213. //
  214. //
  215.  
  216. LRESULT MsgSetfocus(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  217. {
  218.     SetFocus(hOutWnd);  // Don't let main window have focus
  219.     return (TRUE);
  220. }
  221.  
  222. //
  223. //  FUNCTION: MsgDataready(HWND, UINT, WPARAM, LPARAM)
  224. //
  225. //  PURPOSE: Read data and post message to display data
  226. //
  227. //  PARAMETERS:
  228. //
  229. //    hwnd      - Window handle
  230. //    uMessage  - Message number (Unused)
  231. //    wparam    - forwarded to ReceiveInBox
  232. //    lparam    - forwarded to ReceiveInBox
  233. //
  234. //  RETURN VALUE:
  235. //
  236. //    Always returns 0 - Message handled
  237. //
  238. //  COMMENTS:
  239. //
  240. //
  241.  
  242. LRESULT MsgDataready(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  243. {
  244.     // Call protocol specific function to Read data and put in szRcvBuf
  245.     if(ReceiveInBox(hwnd, wparam, lparam, szRcvBuf, sizeof(szRcvBuf)))
  246.     {
  247.         PostMessage(hwnd, MW_DISPLAYREFRESH, 0, 0);
  248.     }
  249.     else
  250.     {
  251.         PostMessage(hwnd, IDM_SELECT, 0, 0);
  252.     }
  253.     return(TRUE);
  254. }
  255.  
  256. //
  257. //  FUNCTION: MsgRefreshdisplay(HWND, UINT, WPARAM, LPARAM)
  258. //
  259. //  PURPOSE: Display socket data in inbox
  260. //
  261. //  PARAMETERS:
  262. //
  263. //    hwnd      - Window handle
  264. //    uMessage  - Message number (Unused)
  265. //    wparam    - Extra Data     (Unused)
  266. //    lparam    - Extra Data     (Unused)
  267. //
  268. //  RETURN VALUE:
  269. //
  270. //    Always returns 0 - Message handled
  271. //
  272. //  COMMENTS:
  273. //
  274. //
  275.  
  276. LRESULT MsgRefreshdisplay(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  277. {
  278.     MSG peekmsg;
  279.  
  280.     // Don't bother displaying if there is already another update queued
  281.     if(PeekMessage(&peekmsg, hwnd, MW_DATAREADY, MW_DISPLAYREFRESH, PM_NOREMOVE))
  282.     {
  283.        return(TRUE);
  284.     }
  285.     // Put data in szRcvBuf in InBox
  286.     SendDlgItemMessage(hwnd,
  287.                        ID_INBOX,
  288.                        EM_SETSEL,
  289.                        0,-1);
  290.     SendDlgItemMessage(hwnd,
  291.                        ID_INBOX,
  292.                        EM_REPLACESEL,
  293.                        0,
  294.                        (LPARAM)szRcvBuf);
  295.     return(TRUE);
  296. }
  297.  
  298. //
  299. //  FUNCTION: MsgDisconnected(HWND, UINT, WPARAM, LPARAM)
  300. //
  301. //  PURPOSE: Cleanup connection dropped from other side
  302. //
  303. //  PARAMETERS:
  304. //
  305. //    hwnd      - Window handle
  306. //    uMessage  - Message number (Unused)
  307. //    wparam    - Extra data     (Unused)
  308. //    lparam    - Extra data     (Unused)
  309. //
  310. //  RETURN VALUE:
  311. //
  312. //    Always returns 0 - Message handled
  313. //
  314. //  COMMENTS:
  315. //
  316. //
  317.  
  318. LRESULT MsgDisconnected(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  319. {
  320.     HMENU hmenu;
  321.  
  322.     // Let the user know
  323.  
  324.     MessageBox(hwnd,
  325.                GetStringRes(IDS_CONNECTION_STOPPED),
  326.                GetStringRes(IDS_CHAT_DLG_STOPPED),
  327.                MB_OK);
  328.  
  329.     // cleanup socket
  330.     closesocket(MySock.sock);
  331.     // Fix menus
  332.     hmenu = GetMenu(hwnd);
  333.     EnableMenuItem(hmenu, IDM_CONNECT, MF_ENABLED);
  334.     EnableMenuItem(hmenu, IDM_DISCONNECT_SERVER, MF_GRAYED);
  335.     EnableMenuItem(hmenu, IDM_END_CHAT, MF_GRAYED);
  336.     SetWindowText(hwnd, szTitle);
  337.     return(TRUE);
  338. }
  339.  
  340. //
  341. //  FUNCTION: MsgCommand(HWND, UINT, WPARAM, LPARAM)
  342. //
  343. //  PURPOSE: Handle the WM_COMMAND messages for the main window.
  344. //
  345. //  PARAMETERS:
  346. //    hwnd     - window handle
  347. //    uMessage - WM_COMMAND (Unused)
  348. //    GET_WM_COMMAND_ID(wparam, lparam)   - Command identifier
  349. //    GET_WM_COMMAND_HWND(wparam, lparam) - Control handle
  350. //
  351. //  RETURN VALUE:
  352. //    The return value depends on the message number.  If the message
  353. //    is implemented in the message dispatch table, the return value is
  354. //    the value returned by the message handling function.  Otherwise,
  355. //    the return value is the value returned by the default window procedure.
  356. //
  357. //  COMMENTS:
  358. //    Call the DispCommand() function with the main window's command dispatch
  359. //    information (cmdiMain) and the command specific information.
  360. //
  361.  
  362. LRESULT MsgCommand(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  363. {
  364.     return DispCommand(&cmdiMain, hwnd, wparam, lparam);
  365. }
  366.  
  367.  
  368. //
  369. //  FUNCTION: MsgDestroy(HWND, UINT, WPARAM, LPARAM)
  370. //
  371. //  PURPOSE: Calls PostQuitMessage().
  372. //
  373. //  PARAMETERS:
  374. //
  375. //    hwnd      - Window handle  (Unused)
  376. //    uMessage  - Message number (Unused)
  377. //    wparam    - Extra data     (Unused)
  378. //    lparam    - Extra data     (Unused)
  379. //
  380. //  RETURN VALUE:
  381. //
  382. //    Always returns 0 - Message handled
  383. //
  384. //  COMMENTS:
  385. //
  386. //
  387.  
  388. LRESULT MsgDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  389. {
  390.     PostQuitMessage(0);
  391.     return 0;
  392. }
  393.  
  394. //
  395. //  FUNCTION: CmdOutbox(HWND, WORD, WORD, HWND)
  396. //
  397. //  PURPOSE: Handle messages from Outbox--Send data if EN_CHANGE
  398. //
  399. //  PARAMETERS:
  400. //    hwnd     - The window.
  401. //    wCommand - ID_OUTBOX (unused)
  402. //    wNotify  - Notification number (unused)
  403. //    hwndCtrl - NULL (unused)
  404. //
  405. //  RETURN VALUE:
  406. //    Always returns 0 - command handled.
  407. //
  408. //  COMMENTS:
  409. //
  410. //
  411.  
  412. LRESULT CmdOutbox(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  413. {
  414.     int cSendLen;
  415.  
  416.     if (wNotify != EN_CHANGE)  // We only care if text has changed
  417.     {
  418.         return 0;
  419.     }
  420.     // Text has changed!  Put OutBox's text in szSndBuf
  421.     cSendLen = GetDlgItemText(hwnd,
  422.                               ID_OUTBOX,
  423.                               szSndBuf,
  424.                               sizeof(szSndBuf));
  425.  
  426.     cSendLen++;   // Add a byte for the NULL terminator
  427.  
  428.     // Do a send
  429.     SendOutBox(szSndBuf, cSendLen);
  430.     return 0;
  431. }
  432.  
  433. //
  434. //  FUNCTION: CmdDisconnect(HWND, WORD, WORD, HWND)
  435. //
  436. //  PURPOSE: Cut off session and fix menus appropriately
  437. //
  438. //  PARAMETERS:
  439. //    hwnd     - The window.
  440. //    wCommand - ID_OUTBOX (unused)
  441. //    wNotify  - Notification number (unused)
  442. //    hwndCtrl - NULL (unused)
  443. //
  444. //  RETURN VALUE:
  445. //    Always returns 0 - command handled.
  446. //
  447. //  COMMENTS:
  448. //
  449. //
  450.  
  451. LRESULT CmdDisconnect(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  452. {
  453.     HMENU hmenu;
  454.  
  455.     closesocket(MySock.sock);
  456.  
  457.     // Fix menus
  458.     hmenu = GetMenu(hwnd);
  459.     EnableMenuItem(hmenu, IDM_CONNECT, MF_ENABLED);
  460.     EnableMenuItem(hmenu, IDM_DISCONNECT_SERVER, MF_GRAYED);
  461.     EnableMenuItem(hmenu, IDM_END_CHAT, MF_GRAYED);
  462.     SetWindowText(hwnd, szTitle);
  463.     return 0;
  464. }
  465.  
  466. //
  467. //  FUNCTION: CmdEndChat(HWND, WORD, WORD, HWND)
  468. //
  469. //  PURPOSE: End Peer to Peer session
  470. //
  471. //  PARAMETERS:
  472. //    hwnd     - The window.
  473. //    wCommand - IDM_END_CHAT (unused)
  474. //    wNotify  - Notification number (unused)
  475. //    hwndCtrl - NULL (unused)
  476. //
  477. //  RETURN VALUE:
  478. //    Always returns 0 - command handled.
  479. //
  480. //  COMMENTS:
  481. //
  482. //
  483.  
  484. LRESULT CmdEndChat(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  485. {
  486.     HMENU hmenu;
  487.     char outtext[80];
  488.  
  489.     // Send SESSION_CLOSE message
  490.     xferbuf.hdr.signature = MYSIGNATURE;
  491.     xferbuf.hdr.length = HDRSIZE;
  492.     xferbuf.hdr.command = SESSION_CLOSE;
  493.     senddatamessage(MySock.sock, &xferbuf);
  494.  
  495.     // Currently socket is set to notify this parent window of events.
  496.    // We need to stop this so that the dialog that we are about to
  497.    // display will get events instead.
  498.     if (WSAAsyncSelect(MySock.sock, hwnd, 0, 0) == SOCKET_ERROR)
  499.     {
  500.         // Oops
  501.         return 0;
  502.     }
  503.  
  504.     // Put up select dialog
  505.     PostMessage(hwnd, WM_COMMAND, MAKELONG(IDM_SELECT, 0), 0);
  506.  
  507.     // Fix menus
  508.     hmenu = GetMenu(hwnd);
  509.     EnableMenuItem(hmenu, IDM_CONNECT, MF_ENABLED);
  510.     EnableMenuItem(hmenu, IDM_DISCONNECT_SERVER, MF_GRAYED);
  511.     EnableMenuItem(hmenu, IDM_END_CHAT, MF_GRAYED);
  512.  
  513.     wsprintf(outtext, GetStringRes(IDS_CHAT_AVAILABLE), MySock.name);
  514.     SetWindowText(hwnd, outtext);
  515.     return 0;
  516. }
  517.  
  518. //
  519. //  FUNCTION: CmdExit(HWND, WORD, WORD, HWND)
  520. //
  521. //  PURPOSE: Exit the application.
  522. //
  523. //  PARAMETERS:
  524. //    hwnd     - The window.
  525. //    wCommand - IDM_EXIT            (unused)
  526. //    wNotify  - Notification number (unused)
  527. //    hwndCtrl - NULL                (unused)
  528. //
  529. //  RETURN VALUE:
  530. //    Always returns 0 - command handled.
  531. //
  532. //  COMMENTS:
  533. //
  534. //
  535.  
  536. LRESULT CmdExit(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  537. {
  538.     closesocket(MySock.sock);
  539.     WSACleanup();
  540.     DestroyWindow(hwnd);
  541.     return 0;
  542. }
  543.