Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

The Ultimate Toolbox - Updates and User Contributions

, 12 Feb 2013
Updates and User Contributions for the Ultimate Toolbox Libraries
OutlookDemoUpdate.zip
Ultimate Grid
Demos
OutlookStyle
OutlookStyle.aps
OutlookStyle.dsp
OutlookStyle.dsw
OutlookStyle.suo
res
bitmap1.bmp
bmattach.bmp
bmp00001.bmp
bmp00002.bmp
bmp00003.bmp
Flags.bmp
OutlookStyle.ico
OutlookStyleDoc.ico
Toolbar.bmp
toolbar1.bmp
toolbar2.bmp
toolbarf.bmp
UltimateGrid72_Src_Update01.zip
CellTypes
Include
Source
UltimateGrid72_Src_Update02.zip
DataSources
ODBC
OleDB
EditControls
UltimateGrid72_Src_Update03.zip
UltimateGrid72_Src_Update04.zip
UltimateGrid73_src.zip
BuildDLL
Build DLL.dsp
Build DLL.dsw
res
BuildLib
ugmfclib.dsp
ugmfclib.dsw
Lib
Skel
UltimateTCP-IP42_Src_Update01.zip
Ultimate TCP-IP
Include
Security
Include
Source
source
UltimateTCP-IP42_Src_Update02.zip
Examples
Client
Mail
icon1.ico
icon2.ico
MailClientS.suo
test.dsp
test.dsw
UltimateTCP-IP42_Src_Update03.zip
ultimatetoolbox93_src_update01.zip
Ultimate Toolbox
include
source
UltimateToolbox93_Src_Update02.zip
lib
Build DLLs
Build Libs
UltimateToolbox93_Src_Update03.zip
UltimateToolbox93_Src_Update04.zip
UltimateToolbox93_Src_Update05.zip
/*************************************************************************
				Class Implementation : CUGEditBase
**************************************************************************
	Source file : UGEditBase.cpp
// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
*************************************************************************/

#include "stdafx.h"
#include <ATLConv.h>
#include "ugctrl.h"
//#include "UGEditBase.h"

#include "UGXPThemes.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/***************************************************
CUGEditBase - Constructor
****************************************************/
CUGEditBase::CUGEditBase() :
	m_continueCol(0),
	m_continueRow(0),
	m_continueFlag(0),
	m_cancel(0),
	m_lastKey(0),
	m_ctrl(NULL)
{
	m_Brush.CreateStockObject(HOLLOW_BRUSH);
}

/***************************************************
~CUGEditBase - Destructor
****************************************************/
CUGEditBase::~CUGEditBase()
{
	m_Brush.DeleteObject();
}

/***************************************************
MessageMap
****************************************************/
BEGIN_MESSAGE_MAP(CUGEditBase, CEdit)
	//{{AFX_MSG_MAP(CUGEditBase)
	ON_WM_CTLCOLOR_REFLECT()
    ON_WM_LBUTTONDOWN()
    ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillfocus)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/***************************************************
WindowProc
	Provides all of the default functionality that
	any CEdit based Ultimate Grid edit control must
	have. 
	
	Most CEdit derived edit controls can be easily
	used in Ultimate Grid by just changing the base 
	class. There is generally no need to change any
	functions calls from CEdit::xxx to CUGEditBase::xxx
	
	All of the messages are put here instead of 
	in a Message Map, so that the so that they are 
	properly called, without having to switch any 
	CEdit::xxx calls over to CUGEditBase::xxx calls

	The only stipulation is that the CEdit derived
	class cannot override the WindowsProc. If it
	does, then the base funtionality will be rendered
	useless. In this case, the code below may be copied
	into the controls WindowsProc (also the member 
	variables will need to be copied over and initialized
	as well).
Params
	See CWnd::WindowsProc
Return
	See CWnd::WindowsProc
****************************************************/
LRESULT CUGEditBase::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch(message)
	{
		//***** WMCREATE *****
		case WM_CREATE:{
			
			if(m_ctrl == NULL)
				m_ctrl = (CUGCtrl*)GetParent();
			
			break;
		}
		//***** WM_SETFOCUS *****
		case WM_SETFOCUS:{
			
			if(m_ctrl == NULL)
				m_ctrl = (CUGCtrl*)GetParent();

			CEdit::WindowProc(message, wParam, lParam);

			m_lastKey = 0;
			m_cancel = FALSE;
			m_continueFlag = FALSE;

			SetSel(GetWindowTextLength(),0);

			if(m_ctrl->m_editCell.GetReadOnly())
				SetReadOnly(TRUE);

			return 0;
		}
		//***** WM_KILLFOCUS *****
		case WM_KILLFOCUS:{
			
			SetReadOnly(FALSE);
			
			CEdit::WindowProc(message, wParam, lParam);
			
			CWnd* pNewWnd = CWnd::FromHandle((HWND)wParam);

			CEdit::OnKillFocus(pNewWnd);

			if( m_ctrl->m_GI->m_bCancelMode != FALSE )
			{
				if(pNewWnd->GetSafeHwnd() != NULL)
				{
					if(pNewWnd != m_ctrl && pNewWnd->GetParent() != m_ctrl)
						m_cancel = TRUE;
				}
				else
					m_cancel = TRUE;
			}

			if( pNewWnd != m_ctrl )
				m_ctrl->OnKillFocus( UG_GRID, pNewWnd );

			if(pNewWnd->GetSafeHwnd() != NULL)
			{
				if( pNewWnd == m_ctrl )
					::SetFocus( m_ctrl->m_CUGGrid->GetSafeHwnd());
			}

			CString string;
			GetWindowText(string);

			if(m_ctrl->EditCtrlFinished(string,m_cancel,m_continueFlag,m_continueCol,m_continueRow) == FALSE)
			{
				m_ctrl->GotoCell(m_ctrl->m_editCol,m_ctrl->m_editRow);
				SetCapture();
				ReleaseCapture();
				SetFocus();
			}
			return 0;
		}
			// We need this to stop the control from drawing itself outside WM_PAINT when selecting text.
		case WM_MOUSEMOVE:
			{
				UpdateCtrl();
			}
			break;
		//***** WM_KEYDOWN *****
		case WM_KEYDOWN:{

			m_lastKey = (UINT)wParam;

			switch(wParam){
				case VK_TAB:{

					if(GetKeyState(VK_SHIFT)<0){
						m_continueCol = m_ctrl->m_editCol -1;
						m_continueRow = m_ctrl->m_editRow;
					}
					else{
						m_continueCol = m_ctrl->m_editCol +1;
						m_continueRow = m_ctrl->m_editRow;
					}

					m_continueFlag = TRUE;
					m_ctrl->SetFocus();
					return 0;
				}
				case VK_RETURN:{

					if( GetKeyState(VK_CONTROL) < 0 &&
						m_ctrl->m_editCell.GetCellTypeEx() & UGCT_NORMALMULTILINE )
					{	// in mulitiline cells allow CTRL-RETURN to advance to a new line
						return 0;
					}

					m_continueCol = m_ctrl->m_editCol;
					m_continueRow = m_ctrl->m_editRow +1;
					m_continueFlag = TRUE;
					m_ctrl->SetFocus();

					if (UGXPThemes::IsThemed())
						UpdateCtrl();

					return 0;
				}

				case VK_ESCAPE:{
					m_cancel = TRUE;
					m_continueFlag = FALSE;
					m_ctrl->SetFocus();
					return 0;
				}

				case VK_UP:{
					m_continueCol = m_ctrl->m_editCol;
					m_continueRow = m_ctrl->m_editRow-1;
					m_continueFlag = TRUE;
					m_ctrl->SetFocus();

					if (UGXPThemes::IsThemed())
						UpdateCtrl();

					return 0;
				}

				case VK_DOWN:{
					m_continueCol = m_ctrl->m_editCol;
					m_continueRow = m_ctrl->m_editRow+1;
					m_continueFlag = TRUE;
					m_ctrl->SetFocus();

					if (UGXPThemes::IsThemed())
						UpdateCtrl();

					return 0;
				}
				
				case VK_RIGHT:{
					CString cellText;
					int cellTextLength;
					int nStartChar;
					int nStopChar;

					// Get edited text and current selection information
					CEdit::GetWindowText(cellText);
					cellTextLength = cellText.GetLength();
					CEdit::GetSel(nStartChar, nStopChar);

					// Allow edit to jump to the next cell if the user hits the
					// right key and:
					// - the cursor reached the end of the cell
					if( nStartChar == nStopChar && nStopChar == cellTextLength )
					{
						m_continueCol = m_ctrl->m_editCol + 1;
						m_continueRow = m_ctrl->m_editRow;
						m_continueFlag = TRUE;
						m_ctrl->SetFocus();

						if (UGXPThemes::IsThemed())
							UpdateCtrl();

						return 0;
					}
					// - or the entire cell's text content is selected
					else if (nStartChar == 0 && nStopChar == cellTextLength)
					{
						m_continueCol = m_ctrl->m_editCol + 1;
						m_continueRow = m_ctrl->m_editRow;
						m_continueFlag = TRUE;
						m_ctrl->SetFocus();

						if (UGXPThemes::IsThemed())
							UpdateCtrl();

						return 0;
					}

					if (UGXPThemes::IsThemed())
						Invalidate();

					break;
				}

				case VK_LEFT:{
					CString cellText;
					int cellTextLength;
					int nStartChar;
					int nStopChar;

					// Get edited text and current selection information
					CEdit::GetWindowText(cellText);
					cellTextLength = cellText.GetLength();
					CEdit::GetSel(nStartChar, nStopChar);

					// If the user hit the Left key and the cursor position is at
					// the beginning of the edit strin without any selection
					// then allow the edit to jump to the previous cell.
					if( nStartChar == nStopChar && nStartChar == 0 )
					{
						m_continueCol = m_ctrl->m_editCol - 1;
						m_continueRow = m_ctrl->m_editRow;
						m_continueFlag = TRUE;
						m_ctrl->SetFocus();


						if (UGXPThemes::IsThemed())
							UpdateCtrl();

						return 0;
					}

					if (UGXPThemes::IsThemed())
						Invalidate();


					break;
				}

				case VK_DELETE:{
					// The OnEditVerify should also called when user enters
					// the DELETE key.  ASCII representation of the DEL key is decimal 127
					UINT nChar = 127;
					int col = m_ctrl->GetCurrentCol();
					long row = m_ctrl->GetCurrentRow();

					// First the datasource has a look ...
					if(m_ctrl->m_GI->m_defDataSource->OnEditVerify(col,row,this,&nChar) == FALSE)
						return 0;
					// then the ctrl class
					if(m_ctrl->OnEditVerify(col,row,this,&nChar) == FALSE)
						return 0;
				}
			}

			break;
		}
		//***** WM_CHAR *****
		case WM_CHAR:{

			UINT nChar = (UINT)wParam;
			m_lastKey = nChar;

			if(nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
				return 0;

			// allow OnEditVerify a look at the char...
			int col = m_ctrl->GetCurrentCol();
			long row = m_ctrl->GetCurrentRow();
			
			// First the datasource has a look ...
			if(m_ctrl->m_GI->m_defDataSource->OnEditVerify(col,row,this,&nChar) == FALSE)
				return 0;

			// then the ctrl class
			if(m_ctrl->OnEditVerify(col,row,this,&nChar) == FALSE)
				return 0;

			// if the characted is allowed by both datasource and ctrl class
			// than set back any changes to the character that user could make
			wParam = (WPARAM)nChar;
			// and allow the edit control to process the new char.

			return CEdit::WindowProc(message, wParam, lParam);
		}
		//***** WM_GETDLGCODE *****
		case WM_GETDLGCODE:{

			return DLGC_WANTALLKEYS | DLGC_WANTARROWS;
		}
		//***** WM_MOUSEACTIVATE *****
		case WM_MOUSEACTIVATE:
			
			return MA_ACTIVATE;	

//		case WM_ERASEBKGND:
		case WM_PAINT:
		{
			if(!UGXPThemes::UseThemes())
				break;
			PAINTSTRUCT ps;
			CDC* cdc = BeginPaint(&ps);
			RECT rc;
			GetWindowRect(&rc);
			ScreenToClient(&rc);

			if (UGXPThemes::DrawBackground(m_hWnd, *cdc, XPCellTypeData, (UGXPThemeState)( ThemeStateSelected | ThemeStateCurrent), &rc, NULL))
			{
				CString text;

				GetWindowText(text);
				// Use the font in the edit box, not the themed font
				// this is because although we're doing our own drawing,
				// the edit box is still telling us how to lay out the text,
				// what is selected, etc.  Changing fonts will make a mess of all of this.
				CFont * pOld = cdc->SelectObject(this->GetFont());
				cdc->SetBkMode(TRANSPARENT);
				RECT rcText(rc);
				rcText.left += 2;
				rcText.top += 2;

				// Work out the part of the string that's selected.
				int nFirstChar = LOWORD(CharFromPos(CPoint(rcText.left, rcText.top)));
				int nBegin, nEnd;
				GetSel(nBegin, nEnd);
				bool bSelected = (nBegin != nEnd);

				nBegin -= nFirstChar;
				nEnd -= nFirstChar;

				RECT rcDraw;
				CopyRect(&rcDraw, &rcText);

				int nRowCount = GetLineCount();

				TCHAR nChar[1024];

				int nCharCount = nFirstChar;

				COLORREF backCol = cdc->GetBkColor();

				// Step through each line of the text.  By letting the
				// edit control tell us what's on each line, we make sure
				// we draw it as the underlying code expects it to be.
				for(int i = this->GetFirstVisibleLine(); i < nRowCount; ++i)
				{
					int nRowChars = GetLine(i, &nChar[0], 1024);

					if (GetStyle() & ES_PASSWORD)
					{
						::memset(&nChar[0], '*', nRowChars);
					}

					nChar[nRowChars] = 0;
					
					cdc->DrawText(&nChar[0], &rcText, DT_LEFT);
					CSize szText = cdc->GetTextExtent(&nChar[0]);
					CString row(&nChar[0]);
					::memset(&nChar[0], 0, 1024);

					rcText.top += szText.cy;

					if (nCharCount + nRowChars >= nBegin && bSelected)
					{
						cdc->SetBkMode(OPAQUE);
						cdc->SetBkColor(0xD00000);

						CString beforeSel = row.Left(nBegin - nCharCount);// text.Mid(nCharCount, nBegin-nCharCount);

						CSize size = cdc->GetTextExtent(beforeSel);

						CString inSel = row.Mid(nBegin - nCharCount, nEnd - nBegin);// text.Mid(nBegin, min(nEnd - nBegin, nRowChars + nCharCount - nBegin));
 
						rcDraw.left += size.cx;
						cdc->DrawText(inSel, &rcDraw, DT_LEFT);
						rcDraw.left = rcText.left;

						// If we selected the entire line, then we need the size of the drawn text for the height
						if (size.cy == 0)
							size = cdc->GetTextExtent(inSel);
	
						rcDraw.top += size.cy;

						cdc->SetBkMode(TRANSPARENT);
						cdc->SetBkColor(backCol);

						// This is to deal with /r/n appearing in the selection text.
						nEnd -= 2;
					}
					else
					{
						CString inSel = text.Mid(nCharCount, nRowChars);
						CSize size = cdc->GetTextExtent(inSel);
						rcDraw.top += size.cy;
					}

					nCharCount += nRowChars;

					if (nBegin < nCharCount) nBegin = nCharCount;

					// This is to deal with /r/n appearing in the selection text.
					nBegin -= 2;
					nEnd -= 2;
				}

				cdc->SelectObject(pOld);

				EndPaint(&ps);
				return true;
			}

			EndPaint(&ps);
		}
		break;
	}

	return CEdit::WindowProc(message, wParam, lParam);
}

/***************************************************
GetLastKey
	GetLastKey is handy if you need to know if
	ESC cancelled the edit.  Key state is not 
	saved (shift, ctrl etc)
Params:
	<none>
Returns:
	last key pressed
*****************************************************/
UINT CUGEditBase::GetLastKey()
{
	return m_lastKey;
}


void CUGEditBase::UpdateCtrl()
{
	if (UGXPThemes::IsThemed())
	{		
		CWnd* pParent = GetParent();
		CRect rect;
	    
		GetWindowRect(rect);
		pParent->ScreenToClient(rect);
		pParent->InvalidateRect(rect, TRUE);

		Invalidate(FALSE);
	}
}


void CUGEditBase::OnKillfocus() 
{
	if (UGXPThemes::IsThemed())
	    UpdateCtrl();

	CEdit::OnKillFocus(this);
}

void CUGEditBase::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if (UGXPThemes::IsThemed())
	    UpdateCtrl();
    
    CEdit::OnLButtonDown(nFlags, point);
}


HBRUSH CUGEditBase::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	if (UGXPThemes::IsThemed())
	{
		pDC->SetBkMode(TRANSPARENT);	
		return (HBRUSH) m_Brush;
	}
	else
	{
		return CEdit::OnCtlColor(pDC, this, nCtlColor);
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

The Ultimate Toolbox
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.
 
Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
Group type: Organisation

387 members


| Advertise | Privacy | Mobile
Web02 | 2.8.140926.1 | Last Updated 13 Feb 2013
Article Copyright 2008 by The Ultimate Toolbox
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid