EditCtls.C
上传用户:woweijixie
上传日期:2018-12-11
资源大小:131k
文件大小:12k
源码类别:

TAPI编程

开发平台:

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) 1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE: EditCtls.c
  9. //
  10. //  PURPOSE: Handles the UI Edit controls to get data from user and display
  11. //    data recieved from the COMM port.
  12. //
  13. //  EXPORTED FUNCTIONS:  These functions are for use by other modules.
  14. //    InitEditCtls              - Initialize the edit controls.
  15. //    SizeEditCtls              - Size and resize the edit controls.
  16. //    SetFocusEditCtls          - Set the focus to the correct edit control.
  17. //    WriteToDisplayCtl         - Write a string to the Display edit control.
  18. //    PostWriteToDisplayCtl     - Posts a message to the UI thread
  19. //                                with data to write.
  20. //
  21. //  INTERNAL FUNCTIONS:  These functions are for this module only.
  22. //    SubclassInputEditProc     - Subclass proc to catch the 'enter' keystroke.
  23. //
  24. // COMMENTS:
  25. //   This sample uses exceptionally simple terminal emulation: none.
  26. //   There are two edit controls involved.  One for the user to type the
  27. //   outgoing strings (called the InputCtl) and another to display both
  28. //   transmitted and received strings (called the DisplayCtl).  There is
  29. //   absolutely *no* translation of incoming strings, and the only
  30. //   modifications to outgoing strings is to append "/r/n" to it.
  31. //
  32. //   This sample only emulates line mode transmission.  The string is only
  33. //   read from the InputCtl when the 'Enter' key is typed.
  34. //
  35. #include <windows.h>
  36. #include <string.h>
  37. #include "globals.h"
  38. #include "EditCtls.h"
  39. #include "CommCode.h"
  40. #include "toolbar.h"
  41. #include "statbar.h"
  42. // Maximum size of Edit control buffers
  43. #define MAXDISPLAYSIZE 0xF000  // Almost 64K
  44. #define MAXINPUTSIZE 0x400      // 1K
  45. #define PWM_WRITESTRING WM_USER + 741 // Arbitrary number
  46. HWND hWndInputCtl;      // Edit control to get input from user
  47. HWND hWndDisplayCtl;    // Edit control to display all output
  48. HWND hWndParent;        // Parent window of edit controls
  49. WNDPROC lpfnInputEdit;  // Storage for subclassed edit control function
  50. // Prototype for the subclassed procedure.
  51. LRESULT CALLBACK SubclassInputEditProc(
  52.     HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  53. //
  54. //  FUNCTION: InitEditCtls(HWND)
  55. //
  56. //  PURPOSE: Initialize the UI edit controls.
  57. //
  58. //  PARAMETERS:
  59. //    hWndMain - The window that is to contain the edit controls.
  60. //
  61. //  RETURN VALUE:
  62. //    TRUE if the edit controls are successfully initialized.
  63. //
  64. //  COMMENTS:
  65. //    This function should only need to be called once, when
  66. //    creating the main window.  The only reason it could fail
  67. //    is if the edit controls couldn't be created.
  68. //
  69. BOOL InitEditCtls(HWND hWndMain)
  70. {
  71.     hWndParent = hWndMain;
  72.     if (!hWndMain)
  73.     {
  74.         OutputDebugString("Invalid parent hWnd for EditCtls!n");
  75.         return FALSE;
  76.     }
  77.     hWndDisplayCtl = CreateWindowEx(
  78.         WS_EX_CLIENTEDGE,
  79.         "EDIT","",
  80.         WS_CHILD | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE
  81.         | ES_OEMCONVERT | WS_VISIBLE | WS_BORDER,
  82.         0, 0, 0, 0, hWndParent,
  83.         NULL, hInst, NULL);
  84.     hWndInputCtl = CreateWindowEx(
  85.         WS_EX_CLIENTEDGE,
  86.         "EDIT","",
  87.         WS_CHILD | ES_AUTOHSCROLL | WS_VISIBLE | WS_BORDER,
  88.         0, 0, 0, 0, hWndParent,
  89.         NULL, hInst, NULL);
  90.     if (!hWndDisplayCtl || !hWndInputCtl)
  91.     {
  92.         OutputDebugString("Unable to create EditCtls.n");
  93.         return FALSE;
  94.     }
  95.     SendMessage(hWndInputCtl, EM_LIMITTEXT, MAXINPUTSIZE, 0);
  96.     SendMessage(hWndDisplayCtl, EM_LIMITTEXT, MAXDISPLAYSIZE, 0);
  97.         // This is where we subclass the input edit control
  98.         // so we can catch the 'enter' keystroke
  99.     lpfnInputEdit = (WNDPROC)
  100.         SetWindowLong(hWndInputCtl, GWL_WNDPROC, (long) SubclassInputEditProc);
  101.     return TRUE;
  102. }
  103. //
  104. //  FUNCTION: SizeEditCtls
  105. //
  106. //  PURPOSE: Sizes, resizes and positions the edit controls.
  107. //
  108. //  PARAMETERS:
  109. //    none
  110. //
  111. //  RETURN VALUE:
  112. //    none
  113. //
  114. //  COMMENTS:
  115. //    Anytime the parent window is resized, it needs to signal
  116. //    the edit controls to also resize.  The size of the edit
  117. //    controls assumes that the edit controls are going to 
  118. //    contain the full client area of the parent, allowing for
  119. //    the toolbar and statusbar.
  120. //
  121. void SizeEditCtls()
  122. {
  123.     RECT rectParent, rectTemp;
  124.     LONG HeightToolbar, HeightStatusbar;
  125.     LONG HeightDisplayCtl, HeightInputCtl;
  126.     LONG WidthCtls;
  127.     LONG yposTopInputCtl, yposTopDisplayCtl;
  128.     HDC hdc;
  129.     TEXTMETRIC tm;
  130.     // Get the client area of the parent.
  131.     if (!GetClientRect(hWndParent, &rectParent))
  132.     {
  133.         OutputDebugString("GetClientRect on EditCtls parent failedn");
  134.         return;
  135.     }
  136.     // leave a pixel on each side
  137.     WidthCtls = rectParent.right - 2;
  138.     
  139.     // Allow for the toolbar at the top.
  140.     GetWindowRect(hWndToolbar, &rectTemp);
  141.     HeightToolbar = rectTemp.bottom - rectTemp.top;
  142.     // Allow for the statusbar at the bottom.
  143.     GetWindowRect(hWndStatusbar, &rectTemp);
  144.     HeightStatusbar = rectTemp.bottom - rectTemp.top;
  145.     // How high should the input control be?
  146.     hdc = GetDC(hWndInputCtl);
  147.     GetTextMetrics(hdc, &tm);
  148.     ReleaseDC(hWndInputCtl, hdc);
  149.     HeightInputCtl = tm.tmHeight + tm.tmExternalLeading + 6;
  150.         // 6 == 3 extra pixels between text and edit control vertical borders.
  151.     // Position Input control.
  152.     yposTopInputCtl = rectParent.bottom - HeightStatusbar - HeightInputCtl - 1;
  153.     // Position Display control.
  154.     yposTopDisplayCtl = rectParent.top + HeightToolbar + 2;
  155.     HeightDisplayCtl = yposTopInputCtl - yposTopDisplayCtl - 1;
  156.     // Move them both.
  157.     MoveWindow(
  158.         hWndInputCtl,
  159.         1, yposTopInputCtl,
  160.         WidthCtls, HeightInputCtl,
  161.         TRUE);
  162.     MoveWindow(
  163.         hWndDisplayCtl,
  164.         1, yposTopDisplayCtl,
  165.         WidthCtls, HeightDisplayCtl,
  166.         TRUE);
  167. }
  168. //
  169. //  FUNCTION: SetFocusEditCtls
  170. //
  171. //  PURPOSE: Sets the focus to the correct edit control.
  172. //
  173. //  PARAMETERS:
  174. //    none
  175. //
  176. //  RETURN VALUE:
  177. //    none
  178. //
  179. //  COMMENTS:
  180. //    Everytime the parent window gets focus, it needs to signal
  181. //    the edit controls to set focus also.  This very simple
  182. //    algorythm always sets focus to the Input control.
  183. //
  184. void SetFocusEditCtls()
  185. {
  186.     DefWindowProc(hWndParent, WM_SETFOCUS, (WPARAM) NULL, (LPARAM) NULL);
  187.     if (GetFocus() == hWndParent)
  188.         SetFocus(hWndInputCtl);
  189.     return;
  190. }
  191. //
  192. //  FUNCTION: SubclassInputEditProc
  193. //
  194. //  PURPOSE: Subclass proceedure of Input control.
  195. //
  196. //  PARAMETERS:
  197. //    Standard WNDPROC parameters.
  198. //
  199. //  RETURN VALUE:
  200. //    Standard WNDPROC return value.
  201. //
  202. //  COMMENTS:
  203. //    We subclass the Input edit control so that we can catch the 'Enter'
  204. //    keystroke (VK_RETURN).  This is how we know when the user wants to
  205. //    transmit something to the COMM port.  This indeed means that only
  206. //    line based terminal emulation is supported by this sample.  However,
  207. //    it makes editing the outgoing text much easier.
  208. //
  209. //    WriteCommString is the call that writes a string to the COMM port.
  210. //    However, the string that is written *must* be allocated with
  211. //    LocalAlloc, and if WriteCommString succeeds, then it will also
  212. //    LocalFree the string.  If WriteCommString fails, then it refused
  213. //    the string and its our job to free it.
  214. //
  215. LRESULT CALLBACK SubclassInputEditProc(
  216.     HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  217. {
  218.     switch(message)
  219.     {
  220.         case WM_CHAR:
  221.             // Found a RETURN keystroke!
  222.             if ((TCHAR) wParam == VK_RETURN)
  223.             {
  224.                 
  225.                 LPSTR pszString;
  226.                 long lSizeofString;
  227.                 // Get the size of the string to send.
  228.                 lSizeofString = 
  229.                     SendMessage(hWndInputCtl, WM_GETTEXTLENGTH, 0, 0);
  230.                 // Allocate enough space for the string and "r"
  231.                 pszString = (LPSTR) LocalAlloc(LPTR, lSizeofString +2);
  232.                 // Get the string
  233.                 SendMessage(hWndInputCtl, WM_GETTEXT,
  234.                     lSizeofString + 1, (LPARAM) pszString);
  235.                 // Terminate it.
  236.                 strcat(pszString, "r");
  237.                 lSizeofString += 1;
  238.                 // If the write to Comm failed, its probably because
  239.                 // a connection isn't made yet.
  240.                 if (WriteCommString(pszString, lSizeofString))
  241.                 {
  242.                     // This is what we'd do to local echo user input
  243.                     // Unnecessary usually.
  244.                     //WriteToOutputEdit(pszString, lSizeofString);
  245.                     ;
  246.                 }
  247.                 else
  248.                 {
  249.                     WriteToDisplayCtl("Not yet connectedr", 20);
  250.                     // The comm code refused the string, so we must free it.
  251.                     LocalFree(pszString);
  252.                 }
  253.                 // Clear the Input control.
  254.                 SendMessage(hWndInputCtl, WM_SETTEXT, 0, (LPARAM) "");
  255.                 // Don't let default processing handle the RETURN key.
  256.                 return 0;
  257.             }
  258.             break;
  259.         case PWM_WRITESTRING:
  260.             WriteToDisplayCtl((LPSTR) lParam, (DWORD) wParam);
  261.             LocalFree((LPSTR) lParam);
  262.             break;
  263.         default:
  264.             break;
  265.     }
  266.     return CallWindowProc(lpfnInputEdit, hWnd, message, wParam, lParam);
  267. }
  268. //
  269. //  FUNCTION: WriteToDisplayCtl(LPSTR, DWORD)
  270. //
  271. //  PURPOSE: Writes a string to the Display control.
  272. //
  273. //  PARAMETERS:
  274. //    lpNewString       - The string to display.
  275. //    dwSizeofNewString - The length of the string.
  276. //
  277. //  RETURN VALUE:
  278. //    none.
  279. //
  280. //  COMMENTS:
  281. //
  282. void WriteToDisplayCtl(LPSTR lpNewString, DWORD dwSizeofNewString)
  283. {
  284.     DWORD dwSizeofEdit;
  285.     dwSizeofEdit = SendMessage(hWndDisplayCtl, WM_GETTEXTLENGTH, 0, 0);
  286.     if ((dwSizeofEdit + dwSizeofNewString) > MAXDISPLAYSIZE)
  287.     {
  288.         // Suggestion for future additions:
  289.         // Handle edit control overflow by deleting from top of edit control
  290.     }
  291.     // Actually place the string into the Display control.
  292.     SendMessage(hWndDisplayCtl, EM_SETSEL, dwSizeofEdit, dwSizeofEdit);
  293.     SendMessage(hWndDisplayCtl, EM_REPLACESEL, 0, (LPARAM) lpNewString);
  294.     SendMessage(hWndDisplayCtl, EM_SETSEL, 
  295.         dwSizeofEdit+dwSizeofNewString, dwSizeofEdit+dwSizeofNewString);
  296. }
  297. //
  298. //  FUNCTION: PostWriteToDisplayCtl(LPSTR, DWORD)
  299. //
  300. //  PURPOSE: Writes a string to the Display control.
  301. //
  302. //  PARAMETERS:
  303. //    lpNewString       - The string to display.
  304. //    dwSizeofNewString - The length of the string.
  305. //
  306. //  RETURN VALUE:
  307. //    none.
  308. //
  309. //  COMMENTS:
  310. //
  311. //    Its very important that when data is recieved from the comm port,
  312. //    the thread reading the comm port doesn't have to wait for the
  313. //    data to be interpreted.  Instead, it posts the data to the main UI
  314. //    thread to be handled when it is convenient.  This is the API to
  315. //    wrap up the PostMessage.
  316. //
  317. //    Note that the string posted must be LocalAlloc()d, and its the job
  318. //    of the window recieving the message to LocalFree it.
  319. //
  320. BOOL PostWriteToDisplayCtl(LPSTR lpNewString, DWORD dwSizeofNewString)
  321. {
  322.     return PostMessage(hWndInputCtl, PWM_WRITESTRING, 
  323.         (WPARAM)dwSizeofNewString, (LPARAM) lpNewString);
  324. }