// InPlaceEdit.cpp : implementation file // #include "stdafx.h" #include "IPEdit.h" #include "TerrCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CInPlaceEdit CInPlaceEdit::CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, float* pHeight, CString sInitText, UINT nFirstChar) { m_sInitText = sInitText; m_pHeight = pHeight; m_nLastChar = 0; // If mouse click brought us here, // then no exit on arrows m_bExitOnArrows = (nFirstChar != VK_LBUTTON); DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE| ES_AUTOHSCROLL //|ES_MULTILINE | dwStyle; if (!Create(dwEditStyle, rect, pParent, nID)) return; SetFont(pParent->GetFont()); SetWindowText(sInitText); SetFocus(); ResizeControl(); switch (nFirstChar) { case VK_LBUTTON: case VK_RETURN: SetSel((int)_tcslen(m_sInitText), -1); return; case VK_BACK: SetSel((int)_tcslen(m_sInitText), -1); break; case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT: case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_SPACE: case VK_END: SetSel(0,-1); return; default: SetSel(0,-1); } SendMessage(WM_CHAR, nFirstChar); } CInPlaceEdit::~CInPlaceEdit() { } BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit) //{{AFX_MSG_MAP(CInPlaceEdit) ON_WM_KILLFOCUS() ON_WM_CHAR() ON_WM_KEYDOWN() ON_WM_KEYUP() ON_WM_CREATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() //////////////////////////////////////////////////////////////////////////// // CInPlaceEdit message handlers // If an arrow key (or associated) is pressed, then exit if // a) The Ctrl key was down, or // b) m_bExitOnArrows == TRUE void CInPlaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if ((nChar == VK_PRIOR || nChar == VK_NEXT || nChar == VK_DOWN || nChar == VK_UP || nChar == VK_RIGHT || nChar == VK_LEFT) && (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) { m_nLastChar = nChar; GetParent()->SetFocus(); return; } if (nChar == VK_ESCAPE) { SetWindowText(m_sInitText); // restore previous text m_nLastChar = nChar; GetParent()->SetFocus(); return; } CEdit::OnKeyDown(nChar, nRepCnt, nFlags); } // Need to keep a lookout for Tabs, Esc and Returns. These send a // "KeyUp" message, but no "KeyDown". That's why I didn't put their // code in OnKeyDown. (I will never understand windows...) void CInPlaceEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) { m_nLastChar = nChar; GetParent()->SetFocus(); // This will destroy this window return; } CEdit::OnKeyUp(nChar, nRepCnt, nFlags); } // As soon as this edit loses focus, kill it. void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd) { CEdit::OnKillFocus(pNewWnd); EndEdit(); } void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // Prevent beeping if (nChar != VK_TAB && nChar != VK_RETURN && nChar != VK_ESCAPE) { CEdit::OnChar(nChar, nRepCnt, nFlags); // Resize edit control if needed ResizeControl(); } } //////////////////////////////////////////////////////////////////////////// // CInPlaceEdit overrides // Stoopid win95 accelerator key problem workaround - Matt Weagle. BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg) { // Make sure that the keystrokes continue to the appropriate handlers if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) { ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); return TRUE; } // Catch the Alt key so we don't choke if focus is going to an owner drawn button if (pMsg->message == WM_SYSCHAR) return TRUE; return CWnd::PreTranslateMessage(pMsg); } // Auto delete void CInPlaceEdit::PostNcDestroy() { CEdit::PostNcDestroy(); delete this; } //////////////////////////////////////////////////////////////////////////// // CInPlaceEdit implementation void CInPlaceEdit::EndEdit() { CString str; GetWindowText(str); BOOL bModified = FALSE; float f; if (sscanf(str, "%f", &f)) { if (*m_pHeight != f) { *m_pHeight = f; bModified = TRUE; } } CWnd* pOwner = GetOwner(); if (pOwner) pOwner->SendMessage(WM_LC_EDIT_CLOSED, m_nLastChar, bModified); // Close this window (PostNcDestroy will delete this) PostMessage(WM_CLOSE, 0, 0); } void CInPlaceEdit::ResizeControl() { // Get text extent CString str; GetWindowText(str); str += "0"; CWindowDC dc(this); CFont *pFontDC = dc.SelectObject(GetFont()); CSize size = dc.GetTextExtent(str); dc.SelectObject(pFontDC); size.cx += 5; // add some extra buffer // Get client rect CRect rect, parentrect; GetClientRect(&rect); GetParent()->GetClientRect(&parentrect); // Transform rect to parent coordinates ClientToScreen(&rect); GetParent()->ScreenToClient(&rect); // Check whether control needs to be resized // and whether there is space to grow if (size.cx > rect.Width()) { if (size.cx + rect.left < parentrect.right) rect.right = rect.left + size.cx; else rect.right = parentrect.right; rect.bottom = rect.top + size.cy + 4; MoveWindow(&rect); } }