MISC.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:11k
源码类别:

Windows编程

开发平台:

Visual C++

  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:   misc.c
  9. //
  10. //  PURPOSE:  Contains all helper functions "global" to the application.
  11. //
  12. //  FUNCTIONS:
  13. //    CenterWindow    - Center one window over another.
  14. //    ReceiveInBox    - Reads incoming socket data.
  15. //    SendOutBox      - Writes outgoing socket data.
  16. //    AtoH            - Converts ascii string to network order hex
  17. //    BtoH            - Converts ascii byte to hex
  18. //    senddatamessage - Sends a message to the server
  19. //    recvdatamessage - Receives a message from the server
  20. //
  21. //  COMMENTS:
  22. //
  23. //
  24. #include <windows.h>            // required for all Windows applications
  25. #include <windowsx.h>
  26. #include <wsipx.h>
  27. #include <wsnetbs.h>
  28. #include <nspapi.h>
  29. #include "globals.h"            // prototypes specific to this application
  30. //
  31. //  FUNCTION: CenterWindow(HWND, HWND)
  32. //
  33. //  PURPOSE:  Center one window over another.
  34. //
  35. //  PARAMETERS:
  36. //    hwndChild - The handle of the window to be centered.
  37. //    hwndParent- The handle of the window to center on.
  38. //
  39. //  RETURN VALUE:
  40. //
  41. //    TRUE  - Success
  42. //    FALSE - Failure
  43. //
  44. //  COMMENTS:
  45. //
  46. //    Dialog boxes take on the screen position that they were designed
  47. //    at, which is not always appropriate. Centering the dialog over a
  48. //    particular window usually results in a better position.
  49. //
  50. BOOL CenterWindow(HWND hwndChild, HWND hwndParent)
  51. {
  52.     RECT    rcChild, rcParent;
  53.     int     cxChild, cyChild, cxParent, cyParent;
  54.     int     cxScreen, cyScreen, xNew, yNew;
  55.     HDC     hdc;
  56.     // Get the Height and Width of the child window
  57.     GetWindowRect(hwndChild, &rcChild);
  58.     cxChild = rcChild.right - rcChild.left;
  59.     cyChild = rcChild.bottom - rcChild.top;
  60.     // Get the Height and Width of the parent window
  61.     GetWindowRect(hwndParent, &rcParent);
  62.     cxParent = rcParent.right - rcParent.left;
  63.     cyParent = rcParent.bottom - rcParent.top;
  64.     // Get the display limits
  65.     hdc = GetDC(hwndChild);
  66.     cxScreen = GetDeviceCaps(hdc, HORZRES);
  67.     cyScreen = GetDeviceCaps(hdc, VERTRES);
  68.     ReleaseDC(hwndChild, hdc);
  69.     // Calculate new X position, then adjust for screen
  70.     xNew = rcParent.left + ((cxParent - cxChild) / 2);
  71.     if (xNew < 0)
  72.     {
  73.         xNew = 0;
  74.     }
  75.     else if ((xNew + cxChild) > cxScreen)
  76.     {
  77.         xNew = cxScreen - cxChild;
  78.     }
  79.     // Calculate new Y position, then adjust for screen
  80.     yNew = rcParent.top  + ((cyParent - cyChild) / 2);
  81.     if (yNew < 0)
  82.     {
  83.         yNew = 0;
  84.     }
  85.     else if ((yNew + cyChild) > cyScreen)
  86.     {
  87.         yNew = cyScreen - cyChild;
  88.     }
  89.     // Set it, and return
  90.     return SetWindowPos(hwndChild,
  91.                         NULL,
  92.                         xNew, yNew,
  93.                         0, 0,
  94.                         SWP_NOSIZE | SWP_NOZORDER);
  95. }
  96. //
  97. //  FUNCTION: ReceiveInBox(HWND, WPARAM, LPARAM, char *, int)
  98. //
  99. //  PURPOSE:  Reads incoming data from socket and process message
  100. //
  101. //  PARAMETERS:
  102. //    hWnd      - Handle to current window
  103. //    uParam    - WPARAM (unused)
  104. //    lParam    - LPARAM contains event (FD_READ or FD_CLOSE).
  105. //    szRBuf    - Receive Buffer
  106. //    cRBufLen  - size of Receive Buffer
  107. //
  108. //  RETURN VALUE:
  109. //
  110. //    TRUE  - Data Read
  111. //    FALSE - If FD_CLOSE message or recv failed
  112. //
  113. //  COMMENTS:
  114. //
  115. //    Called if socket has data OR if it is closed.  If closed post
  116. //    WM_DISCONNECTED message.  Else read data and make sure it is
  117. //    NULL terminated.
  118. //
  119. BOOL ReceiveInBox(HWND hWnd, WPARAM uParam, LPARAM lParam, char * szRBuf, int cRBufLen)
  120. {
  121.     char outtext[80];
  122.     if (LOWORD(lParam) == FD_CLOSE)                   // Is this a FD_CLOSE event?
  123.     {
  124.         SendMessage(hWnd, MW_DISCONNECTED, 0, 0);     // Yes, post message
  125.         return(FALSE);
  126.     }
  127.     if (!recvdatamessage(&MySock, &xferbuf))         // Receive data
  128.     {
  129.         return(TRUE);
  130.     }
  131.     // Switch on message command
  132.     switch (xferbuf.hdr.command)
  133.     {
  134.         case XFER_DATA:   // Chat data...put it in buffer
  135.             lstrcpy(szRBuf, xferbuf.data);
  136.             cRBufLen = xferbuf.hdr.length - HDRSIZE;
  137.             break;
  138.         case SESSION_CLOSE:  // Peer killed us...cleanup
  139.             MySock.status = SOCKSTAT_AVAILABLE;
  140.             // Clear event indicator since we need to transfer message
  141.          // indications to the dialog we are about to create
  142.             if (WSAAsyncSelect(MySock.sock, hWnd, 0, 0) == SOCKET_ERROR)
  143.             {
  144.                 // oops
  145.                 return FALSE;
  146.             }
  147.             PostMessage(hWnd, WM_COMMAND, MAKELONG(IDM_SELECT, 0), 0);
  148.             wsprintf(outtext, GetStringRes(IDS_CHAT_AVAILABLE), MySock.name);
  149.             SetWindowText(hWnd, outtext);
  150.             return FALSE;
  151.         default:
  152.             break;
  153.             // unexpected meesage...drop it
  154.     }
  155.     return TRUE;
  156. }
  157. //
  158. //  FUNCTION: SendOutBox(char *, int)
  159. //
  160. //  PURPOSE:  Sends outbox text via data message
  161. //
  162. //  PARAMETERS:
  163. //    szSBuf    - Send Buffer
  164. //    cSBufLen  - size of Send Buffer
  165. //
  166. //  COMMENTS:
  167. //
  168. //    Writes send buffer to socket
  169. //
  170. void SendOutBox(char * szSBuf, int cSBufLen)
  171. {
  172.     xferbuf.hdr.signature = MYSIGNATURE;
  173.     xferbuf.hdr.length = cSBufLen + HDRSIZE;
  174.     xferbuf.hdr.command = XFER_DATA;
  175.     lstrcpy(xferbuf.data, szSBuf);
  176.     senddatamessage(MySock.sock, &xferbuf);
  177.     return;
  178. }
  179. //
  180. //  FUNCTION: AtoH(char *, char *, int)
  181. //
  182. //  PURPOSE:  Converts ascii string to network order hex
  183. //
  184. //  PARAMETERS:
  185. //    src    - pointer to input ascii string
  186. //    dest   - pointer to output hex
  187. //    destlen - size of dest
  188. //
  189. //  COMMENTS:
  190. //
  191. //    2 ascii bytes make a hex byte so must put 1st ascii byte of pair
  192. //    into upper nibble and 2nd ascii byte of pair into lower nibble.
  193. //
  194. void AtoH(char * src, char * dest, int destlen)
  195. {
  196.     char * srcptr;
  197.     srcptr = src;
  198.     while(destlen--)
  199.     {
  200.     *dest = BtoH(*srcptr++) << 4;    // Put 1st ascii byte in upper nibble.
  201.     *dest++ += BtoH(*srcptr++);      // Add 2nd ascii byte to above.
  202.     }
  203. }
  204. //
  205. //  FUNCTION: BtoH(char *, char *, int)
  206. //
  207. //  PURPOSE:  Converts ascii byte to numeric
  208. //
  209. //  PARAMETERS:
  210. //    ch - ascii byte to convert
  211. //
  212. //  RETURNS:
  213. //    associated numeric value
  214. //
  215. //  COMMENTS:
  216. //
  217. //    Will convert any hex ascii digit to its numeric counterpart.
  218. //    Puts in 0xff if not a valid hex digit.
  219. //
  220. unsigned char BtoH(char ch)
  221. {
  222.     if (ch >= '0' && ch <= '9') return (ch - '0');        // Handle numerals
  223.     if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA);  // Handle capitol hex digits
  224.     if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA);  // Handle small hex digits
  225.     return(255);
  226. }
  227. //
  228. //  FUNCTION: senddatamessage(SOCKET, LPDATAMSG)
  229. //
  230. //  PURPOSE:  sends a chat message to the server
  231. //
  232. //  PARAMETERS:
  233. //    sock    - our socket handle
  234. //    sendbuf - the message to send
  235. //
  236. //  RETURNS:
  237. //    ascii byte
  238. //
  239. //  COMMENTS:
  240. //    Send() may not be able to send entire message continue to send until
  241. //    entire message is sent
  242. //
  243. BOOL senddatamessage (SOCKET sock, LPDATAMSG sendbuf)
  244. {
  245.     int totalbytes, bytessent;
  246.     bytessent = 0;                          // Set initial count to zero
  247.     totalbytes = sendbuf->hdr.length;     // Set total bytes to send
  248.    // loop until entire message is sent
  249.     while(bytessent < totalbytes)
  250.     {
  251.         bytessent += send(sock,
  252.                           (char *)sendbuf + bytessent,
  253.                           totalbytes - bytessent,
  254.                           0);
  255.     }
  256.     return TRUE;
  257. }
  258. //
  259. //  FUNCTION: recvdatamessage(LPSOCKDATA, LPDATAMSG)
  260. //
  261. //  PURPOSE:  receives chat message from server
  262. //
  263. //  PARAMETERS:
  264. //    lpSockdat - SOCKDATA structure
  265. //    recvbuf   - buffer for incoming data
  266. //
  267. //  RETURNS:
  268. //    TRUE  - Message received
  269. //    FALSE - Message not received
  270. //
  271. //  COMMENTS:
  272. //   For stream sockets we will need to make sure that we read
  273. //    an entire message--no more, no less.  Find message size from
  274. //    message header.
  275. //
  276. BOOL recvdatamessage (LPSOCKDATA lpSockdat, LPDATAMSG recvbuf)
  277. {
  278.     int readsize, totalbytesread, msgsize, bytesread;
  279.     if (lpSockdat->type == SOCK_SEQPACKET)
  280.     {
  281.         // Message mode protocol!!  Just post one big read.
  282.         readsize = sizeof(*recvbuf);
  283.     }
  284.     else
  285.     {
  286.         // Stream mode protocol!!  Just read header...then read data (data size determined
  287.         // from header)
  288.         readsize = HDRSIZE;
  289.     }
  290.     if((totalbytesread = recv(lpSockdat->sock, (char *)recvbuf, readsize, 0)) == SOCKET_ERROR)
  291.     {
  292.         // ERROR  -- just return
  293.         return FALSE;
  294.     }
  295.     // Check for my signature at the beginning of the message
  296.     if(recvbuf->hdr.signature != MYSIGNATURE)
  297.     {
  298.         // I've received some data that's in mid message--drop it
  299.         return FALSE;
  300.     }
  301.     // Read size of message
  302.     msgsize = recvbuf->hdr.length;
  303.     readsize = msgsize - totalbytesread;
  304.     while(totalbytesread < msgsize)
  305.     {
  306.         // we should only get hear for stream sockets
  307.         if((bytesread = recv(lpSockdat->sock,
  308.                              (char *)recvbuf + totalbytesread,
  309.                              readsize,
  310.                              0)) == SOCKET_ERROR)
  311.         {
  312.             if (WSAGetLastError() != WSAEWOULDBLOCK)
  313.             {
  314.                 // ERROR -- throw out message
  315.                 return FALSE;
  316.             }
  317.             // If you got a WSAWOULDBLOCK error, just keep trying...it shouldn't take
  318.             // too much longer for the rest of the message to get here.  Let's hope
  319.             // we don't hog the CPU so the data doesn't get to us.
  320.         }
  321.         totalbytesread += bytesread;
  322.         readsize -= bytesread;
  323.     }
  324.     return TRUE;
  325. }
  326. //---------------------------------------------------------------------------
  327. //
  328. // FUNCTION:    GetStringRes (int id INPUT ONLY)
  329. //
  330. // COMMENTS:    Load the resource string with the ID given, and return a
  331. //              pointer to it.  Notice that the buffer is common memory so
  332. //              the string must be used before this call is made a second time.
  333. //
  334. //---------------------------------------------------------------------------
  335. LPTSTR GetStringRes (int id)
  336. {
  337.   static TCHAR buffer[MAX_PATH];
  338.   buffer[0]=0;
  339.   LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  340.   return buffer;
  341. }