www.pudn.com > print_preview000.rar > InPlaceList.cpp


// InPlaceList.cpp : implementation file 
// 
// Written by Chris Maunder (chrismaunder@codeguru.com) 
// Copyright (c) 1998. 
// 
// The code contained in this file is based on the original 
// CInPlaceList from http://www.codeguru.com/listview 
// 
// This code may be used in compiled form in any way you desire. This 
// file may be redistributed unmodified by any means PROVIDING it is  
// not sold for profit without the authors written consent, and  
// providing that this notice and the authors name is included. If  
// the source code in  this file is used in any commercial application  
// then acknowledgement must be made to the author of this file  
// (in whatever form you wish). 
// 
// This file is provided "as is" with no expressed or implied warranty. 
// The author accepts no liability for any damage/loss of business that 
// this product may cause. 
// 
// Expect bugs! 
//  
// Please use and enjoy. Please let me know of any bugs/mods/improvements  
// that you have found/implemented and I will fix/incorporate them into this 
// file.  
// 
// 6 Aug 1998 - Added CComboEdit to subclass the edit control - code provided by  
//              Roelf Werkman . Added nID to the constructor param list. 
// 29 Nov 1998 - bug fix in onkeydown (Markus Irtenkauf) 
// 
///////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "InPlaceList.h" 
 
#include "GridCtrl.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CComboEdit 
 
CComboEdit::CComboEdit() 
{ 
} 
 
CComboEdit::~CComboEdit() 
{ 
} 
 
// Stoopid win95 accelerator key problem workaround - Matt Weagle. 
BOOL CComboEdit::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 CEdit::PreTranslateMessage(pMsg); 
} 
 
BEGIN_MESSAGE_MAP(CComboEdit, CEdit) 
	//{{AFX_MSG_MAP(CComboEdit) 
	ON_WM_KILLFOCUS() 
	ON_WM_KEYDOWN() 
	ON_WM_KEYUP() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CComboEdit message handlers 
 
void CComboEdit::OnKillFocus(CWnd* pNewWnd)  
{ 
	CEdit::OnKillFocus(pNewWnd); 
	 
    CInPlaceList* pOwner = (CInPlaceList*) GetOwner();  // This MUST be a CInPlaceList 
    if (pOwner) 
        pOwner->EndEdit();	 
} 
 
void CComboEdit::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) && 
		(GetKeyState(VK_CONTROL) < 0 && GetDlgCtrlID() == IDC_COMBOEDIT)) 
    { 
        CWnd* pOwner = GetOwner(); 
        if (pOwner) 
            pOwner->SendMessage(WM_KEYDOWN, nChar, nRepCnt+ (((DWORD)nFlags)<<16)); 
        return; 
    } 
 
	CEdit::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
void CComboEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	if (nChar == VK_ESCAPE)  
	{ 
        CWnd* pOwner = GetOwner(); 
        if (pOwner) 
            pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16)); 
        return; 
    } 
 
	if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) 
    { 
        CWnd* pOwner = GetOwner(); 
        if (pOwner) 
            pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16)); 
        return; 
    } 
 
	CEdit::OnKeyUp(nChar, nRepCnt, nFlags); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CInPlaceList 
 
CInPlaceList::CInPlaceList(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, 
                           int nRow, int nColumn,  
						   CStringArray& Items, CString sInitText,  
						   UINT nFirstChar) 
{ 
	m_nNumLines = 4; 
	m_sInitText = sInitText; 
 	m_nRow		= nRow; 
 	m_nCol      = nColumn; 
 	m_nLastChar = 0;  
	m_bExitOnArrows = FALSE; //(nFirstChar != VK_LBUTTON);	// If mouse click brought us here, 
 
	// Create the combobox 
 	DWORD dwComboStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL| 
 					     CBS_AUTOHSCROLL | dwStyle; 
	int nHeight = rect.Height(); 
	rect.bottom = rect.bottom + m_nNumLines*nHeight + ::GetSystemMetrics(SM_CYHSCROLL); 
	if (!Create(dwComboStyle, rect, pParent, nID)) return; 
 
	// Add the strings 
	for (int i = 0; i < Items.GetSize(); i++)  
		AddString(Items[i]); 
 
	// Get the maximum width of the text strings 
	int nMaxLength = 0; 
	CClientDC dc(GetParent()); 
	CFont* pOldFont = dc.SelectObject(pParent->GetFont()); 
 
	for (i = 0; i < Items.GetSize(); i++)  
		nMaxLength = max(nMaxLength, dc.GetTextExtent(Items[i]).cx); 
 
	nMaxLength += (::GetSystemMetrics(SM_CXVSCROLL) + dc.GetTextExtent(_T(" ")).cx*2); 
	dc.SelectObject(pOldFont); 
 
    if (nMaxLength > rect.Width()) 
	    rect.right = rect.left + nMaxLength; 
 
	// Resize the edit window and the drop down window 
	MoveWindow(rect); 
 
	SetFont(pParent->GetFont()); 
	SetItemHeight(-1, nHeight); 
 
	SetDroppedWidth(nMaxLength); 
	SetHorizontalExtent(0); // no horz scrolling 
 
	// Set the initial text to m_sInitText 
	if (SelectString(-1, m_sInitText) == CB_ERR)  
		SetWindowText(m_sInitText);		// No text selected, so restore what was there before 
 
    // Subclass the combobox edit control if style includes CBS_DROPDOWN 
    if ((dwStyle & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST) 
    { 
        m_edit.SubclassDlgItem(IDC_COMBOEDIT, this); 
 	    SetFocus(); 
        switch (nFirstChar) 
        { 
            case VK_LBUTTON:  
            case VK_RETURN:   m_edit.SetSel((int)_tcslen(m_sInitText), -1); return; 
            case VK_BACK:     m_edit.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_END:      m_edit.SetSel(0,-1); return; 
            default:          m_edit.SetSel(0,-1); 
        } 
        SendMessage(WM_CHAR, nFirstChar); 
    } 
    else 
 	    SetFocus(); 
} 
 
CInPlaceList::~CInPlaceList() 
{ 
} 
 
void CInPlaceList::EndEdit() 
{ 
    CString str; 
    GetWindowText(str); 
  
    // Send Notification to parent 
    GV_DISPINFO dispinfo; 
 
    dispinfo.hdr.hwndFrom = GetSafeHwnd(); 
    dispinfo.hdr.idFrom   = GetDlgCtrlID(); 
    dispinfo.hdr.code     = GVN_ENDLABELEDIT; 
  
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM; 
    dispinfo.item.row     = m_nRow; 
    dispinfo.item.col     = m_nCol; 
    dispinfo.item.szText  = str; 
    dispinfo.item.lParam  = (LPARAM) m_nLastChar;  
  
    CWnd* pOwner = GetOwner(); 
    if (IsWindow(pOwner->GetSafeHwnd())) 
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo ); 
  
    // Close this window (PostNcDestroy will delete this) 
    PostMessage(WM_CLOSE, 0, 0); 
} 
 
void CInPlaceList::PostNcDestroy()  
{ 
	CComboBox::PostNcDestroy(); 
 
	delete this; 
} 
 
BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox) 
	//{{AFX_MSG_MAP(CInPlaceList) 
	ON_WM_KILLFOCUS() 
	ON_WM_KEYDOWN() 
	ON_WM_KEYUP() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CInPlaceList message handlers 
 
void CInPlaceList::OnKillFocus(CWnd* pNewWnd)  
{ 
	CComboBox::OnKillFocus(pNewWnd); 
 
	if (GetSafeHwnd() == pNewWnd->GetSafeHwnd()) 
        return; 
 
    // Only end editing on change of focus if we're using the CBS_DROPDOWNLIST style 
    if ((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST) 
        EndEdit(); 
} 
 
// If an arrow key (or associated) is pressed, then exit if 
//  a) The Ctrl key was down, or 
//  b) m_bExitOnArrows == TRUE 
void CInPlaceList::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; 
	} 
 
	CComboBox::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
// Need to keep a lookout for Tabs, Esc and Returns. 
void CInPlaceList::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	if (nChar == VK_ESCAPE)  
		SetWindowText(m_sInitText);	// restore previous text 
 
	if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) 
	{ 
		m_nLastChar = nChar; 
		GetParent()->SetFocus();	// This will destroy this window 
		return; 
	} 
 
	CComboBox::OnKeyUp(nChar, nRepCnt, nFlags); 
}