InPlaceEdit.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include "pch.h"
  2. #include "InPlaceEdit.h"
  3. #include "GridCtrl.h"
  4. /////////////////////////////////////////////////////////////////////////////
  5. // CInPlaceEdit
  6. CInPlaceEdit::CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
  7. int nRow, int nColumn, CString sInitText,
  8. UINT nFirstChar)
  9. {
  10. m_sInitText = sInitText;
  11. m_nRow = nRow;
  12. m_nColumn = nColumn;
  13. m_nLastChar = 0;
  14. m_bExitOnArrows = (nFirstChar != VK_LBUTTON); // If mouse click brought us here,
  15. // then no exit on arrows
  16. m_Rect = rect; // For bizarre CE bug.
  17. DWORD dwEditStyle = WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL //|ES_MULTILINE
  18. | dwStyle;
  19. if (!Create(dwEditStyle, rect, pParent, nID)) return;
  20. SetFont(pParent->GetFont());
  21. SetWindowText(sInitText);
  22. SetFocus();
  23. switch (nFirstChar) {
  24. case VK_LBUTTON:
  25. case VK_RETURN: SetSel((int)_tcslen(m_sInitText), -1); return;
  26. case VK_BACK: SetSel((int)_tcslen(m_sInitText), -1); break;
  27. case VK_TAB:
  28. case VK_DOWN:
  29. case VK_UP:
  30. case VK_RIGHT:
  31. case VK_LEFT:
  32. case VK_NEXT:
  33. case VK_PRIOR:
  34. case VK_HOME:
  35. case VK_SPACE:
  36. case VK_END: SetSel(0, -1); return;
  37. default: SetSel(0, -1);
  38. }
  39. // Added by KiteFly. When entering DBCS chars into cells the first char was being lost
  40. // SenMessage changed to PostMessage (John Lagerquist)
  41. if (nFirstChar < 0x80)
  42. PostMessage(WM_CHAR, nFirstChar);
  43. else
  44. PostMessage(WM_IME_CHAR, nFirstChar);
  45. }
  46. CInPlaceEdit::~CInPlaceEdit()
  47. {
  48. }
  49. BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit)
  50. //{{AFX_MSG_MAP(CInPlaceEdit)
  51. ON_WM_KILLFOCUS()
  52. ON_WM_CHAR()
  53. ON_WM_KEYDOWN()
  54. ON_WM_GETDLGCODE()
  55. ON_WM_CREATE()
  56. //}}AFX_MSG_MAP
  57. END_MESSAGE_MAP()
  58. ////////////////////////////////////////////////////////////////////////////
  59. // CInPlaceEdit message handlers
  60. // If an arrow key (or associated) is pressed, then exit if
  61. // a) The Ctrl key was down, or
  62. // b) m_bExitOnArrows == TRUE
  63. void CInPlaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  64. {
  65. if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
  66. nChar == VK_DOWN || nChar == VK_UP ||
  67. nChar == VK_RIGHT || nChar == VK_LEFT) &&
  68. (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0))
  69. {
  70. m_nLastChar = nChar;
  71. GetParent()->SetFocus();
  72. return;
  73. }
  74. CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
  75. }
  76. // As soon as this edit loses focus, kill it.
  77. void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd)
  78. {
  79. CEdit::OnKillFocus(pNewWnd);
  80. EndEdit();
  81. }
  82. void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  83. {
  84. if (nChar == VK_TAB || nChar == VK_RETURN)
  85. {
  86. m_nLastChar = nChar;
  87. GetParent()->SetFocus(); // This will destroy this window
  88. return;
  89. }
  90. if (nChar == VK_ESCAPE)
  91. {
  92. SetWindowText(m_sInitText); // restore previous text
  93. m_nLastChar = nChar;
  94. GetParent()->SetFocus();
  95. return;
  96. }
  97. CEdit::OnChar(nChar, nRepCnt, nFlags);
  98. // Resize edit control if needed
  99. // Get text extent
  100. CString str;
  101. GetWindowText(str);
  102. // add some extra buffer
  103. str += _T(" ");
  104. CWindowDC dc(this);
  105. CFont *pFontDC = dc.SelectObject(GetFont());
  106. CSize size = dc.GetTextExtent(str);
  107. dc.SelectObject(pFontDC);
  108. // Get client rect
  109. CRect ParentRect;
  110. GetParent()->GetClientRect(&ParentRect);
  111. // Check whether control needs to be resized
  112. // and whether there is space to grow
  113. if (size.cx > m_Rect.Width())
  114. {
  115. if (size.cx + m_Rect.left < ParentRect.right)
  116. m_Rect.right = m_Rect.left + size.cx;
  117. else
  118. m_Rect.right = ParentRect.right;
  119. MoveWindow(&m_Rect);
  120. }
  121. }
  122. UINT CInPlaceEdit::OnGetDlgCode()
  123. {
  124. return DLGC_WANTALLKEYS;
  125. }
  126. ////////////////////////////////////////////////////////////////////////////
  127. // CInPlaceEdit overrides
  128. // Stoopid win95 accelerator key problem workaround - Matt Weagle.
  129. BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg)
  130. {
  131. // Catch the Alt key so we don't choke if focus is going to an owner drawn button
  132. if (pMsg->message == WM_SYSCHAR)
  133. return TRUE;
  134. return CWnd::PreTranslateMessage(pMsg);
  135. }
  136. // Auto delete
  137. void CInPlaceEdit::PostNcDestroy()
  138. {
  139. CEdit::PostNcDestroy();
  140. delete this;
  141. }
  142. ////////////////////////////////////////////////////////////////////////////
  143. // CInPlaceEdit implementation
  144. void CInPlaceEdit::EndEdit()
  145. {
  146. CString str;
  147. // EFW - BUG FIX - Clicking on a grid scroll bar in a derived class
  148. // that validates input can cause this to get called multiple times
  149. // causing assertions because the edit control goes away the first time.
  150. static BOOL bAlreadyEnding = FALSE;
  151. if (bAlreadyEnding)
  152. return;
  153. bAlreadyEnding = TRUE;
  154. GetWindowText(str);
  155. // Send Notification to parent
  156. GV_DISPINFO dispinfo;
  157. dispinfo.hdr.hwndFrom = GetSafeHwnd();
  158. dispinfo.hdr.idFrom = GetDlgCtrlID();
  159. dispinfo.hdr.code = GVN_ENDLABELEDIT;
  160. dispinfo.item.mask = LVIF_TEXT | LVIF_PARAM;
  161. dispinfo.item.row = m_nRow;
  162. dispinfo.item.col = m_nColumn;
  163. dispinfo.item.strText = str;
  164. dispinfo.item.lParam = (LPARAM)m_nLastChar;
  165. CWnd* pOwner = GetOwner();
  166. if (pOwner)
  167. pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo);
  168. // Close this window (PostNcDestroy will delete this)
  169. if (IsWindow(GetSafeHwnd()))
  170. SendMessage(WM_CLOSE, 0, 0);
  171. bAlreadyEnding = FALSE;
  172. }