Click here to Skip to main content
14,176,951 members
Click here to Skip to main content

Stats

299.3K views
79.1K downloads
227 bookmarked
Posted 30 Dec 2005
Licenced CPOL

Form Designer

, 1 Aug 2009
Component for adding scriptable forms capabilities to an application.
MFCDemo.exe
CSDemo
App.ico
Bmp
ABottom.bmp
About.bmp
ALeft.bmp
ARight.bmp
ATop.bmp
AX.bmp
BringFront.bmp
Button.bmp
Center.bmp
Check.bmp
Combo.bmp
Copy.bmp
Cut.bmp
Delete.bmp
Down.bmp
Edit.bmp
Frame.bmp
Grid.bmp
GridSettings.bmp
HCenter.bmp
HScroll.bmp
HSL.bmp
HSpace.bmp
HSS.bmp
Left.bmp
List.bmp
New.bmp
Open.bmp
Paste.bmp
Picture.bmp
Preview.bmp
Progress.bmp
Props.bmp
Radio.bmp
Rectangle.bmp
Redo.bmp
Right.bmp
Save.bmp
SelAll.bmp
SelNone.bmp
SendBack.bmp
SL.bmp
Slider.bmp
Spin.bmp
SS.bmp
Tab.bmp
Text.bmp
Undo.bmp
Up.bmp
Validate.bmp
VCenter.bmp
VScroll.bmp
VSL.bmp
VSpace.bmp
VSS.bmp
Wand.bmp
CSDemo.suo
DaeDoe.bmp
MFCDemo
MFCDemo.dsp
MFCDemo.odl
MFCDemo.reg
res
DaeDoe.bmp
MFCDemo.ico
MFCDemoDoc.ico
Toolbar1.bmp
Toolbar2.bmp
Toolbar3.bmp
Wand.bmp
VBDemo
Bmp
ABottom.bmp
About.bmp
ALeft.bmp
ARight.bmp
ATop.bmp
AX.bmp
BringFront.bmp
Button.bmp
Center.bmp
Check.bmp
Combo.bmp
Copy.bmp
Cut.bmp
Delete.bmp
Down.bmp
Edit.bmp
Frame.bmp
Grid.bmp
GridSettings.bmp
HCenter.bmp
HScroll.bmp
HSL.bmp
HSpace.bmp
HSS.bmp
Left.bmp
List.bmp
New.bmp
Open.bmp
Paste.bmp
Picture.bmp
Preview.bmp
Progress.bmp
Props.bmp
Radio.bmp
Rectangle.bmp
Redo.bmp
Right.bmp
Save.bmp
SelAll.bmp
SelNone.bmp
SendBack.bmp
SL.bmp
Slider.bmp
Spin.bmp
SS.bmp
Tab.bmp
Text.bmp
Undo.bmp
Up.bmp
Validate.bmp
VCenter.bmp
VScroll.bmp
VSL.bmp
VSpace.bmp
VSS.bmp
Wand.bmp
DaeDoe.bmp
VBDemo.vbp
DDForms.chm
DDForms
Archive
FormEditorItems.rgs
vssver.scc
Constants.scr
DaeDoe.bmp
DDForms.def
DDForms.vcproj
DDForms.vcproj.vspscc
EventSinkPassThrough.rgs
FormEditor.bmp
FormEditor.rgs
FormEditorItemCollection.rgs
FormEditorItemDetails.rgs
FormViewer.bmp
FormViewer.rgs
FormViewerItemCollection.rgs
FormViewerItemDetails.rgs
mssccprj.scc
PropPageExtended.rgs
PropPageFormEditor.rgs
PropPageFormViewer.rgs
PropPageSimpleScriptEditor.rgs
SimpleScriptEditor.bmp
SimpleScriptEditor.rgs
vssver.scc
DDFormsTools
CodeMaxDriver
CodeMaxDriver.rgs
CodeMaxDriver.vcproj
CodeMaxDriver.vcproj.vspscc
CodeMaxDriverps.def
CodeMaxDriverPS.vcproj
CodeMaxDriverPS.vcproj.vspscc
mssccprj.scc
vssver.scc
CodeSenseDriver
CodeSenseDriver.rgs
CodeSenseDriver.vcproj
CodeSenseDriver.vcproj.vspscc
CodeSenseDriverps.def
CodeSenseDriverPS.vcproj
CodeSenseDriverPS.vcproj.vspscc
mssccprj.scc
vssver.scc
DDPropPageAll
DDPropPageAll.def
DDPropPageAll.vcproj
DDPropPageAll.vcproj.vspscc
mssccprj.scc
PropPageAll.rgs
vssver.scc
DDUnlock
DDUnlock.vcproj
DDUnlock.vcproj.vspscc
mssccprj.scc
vssver.scc
DDControlPack
DDButton.bmp
DDCheckBox.bmp
DDComboBox.bmp
DDControlPack.rgs
DDControlPack.vcproj
DDControlPack.vcproj.vspscc
DDHorzScrollBar.bmp
DDLabel.bmp
DDListBox.bmp
DDPicture.bmp
DDRadioButton.bmp
DDTextBox.bmp
DDVertScrollBar.bmp
mssccprj.scc
vssver.scc
Redistributables
Ansi
CodeMaxDriver.dll
CodeSenseDriver.dll
DDControlPack.dll
DDForms.dll
DDPropPageAll.dll
Unicode
CodeMaxDriver.dll
CodeSenseDriver.dll
DDControlPack.dll
DDForms.dll
DDPropPageAll.dll
// SimpleScriptEditor.cpp : Implementation of CSimpleScriptEditor
//
// Author : David Shepherd
//			Copyright (c) 2002, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DDForms.h"
#include "SimpleScriptEditor.h"

// default font name
// the most common font is used here as the initial font creation
// must always succeed otherwise object creation fails
#define DEFAULT_FONT_NAME	L"MS Sans Serif"
// default font size
#define DEFAULT_FONT_SIZE	8
// default tab stops
#define DEFAULT_TAB_STOPS	4

namespace AxSimpleScriptEditor {

/////////////////////////////////////////////////////////////////////////////
// CSimpleScriptEditor

CSimpleScriptEditor::CSimpleScriptEditor() :
	m_ContainedEdit(_T("Edit"),this,1)
{
	// initialise everything
	m_bWindowOnly=TRUE;
	m_hAccel=NULL;
	m_LockCount=0;
	m_Modified=FALSE;
	m_BorderVisible=VARIANT_TRUE;
	m_BackColor=MAKE_OLE_COLOR(COLOR_WINDOW);
	m_ForeColor=MAKE_OLE_COLOR(COLOR_WINDOWTEXT);
	m_BackBrush=NULL;
}

CSimpleScriptEditor::~CSimpleScriptEditor()
{
	// clean up
	if(m_BackBrush!=NULL)
	{
		(void)DeleteObject(m_BackBrush);
		m_BackBrush=NULL;
	}
}

void CSimpleScriptEditor::SetModified(BOOL Modified)
{
	// set the modified flag and fire the modified state changed event
	if(m_Modified!=Modified)
	{
		m_Modified=Modified;
		(void)Fire_ModifiedStateChanged(B2VB(m_Modified));
	}
}

void CSimpleScriptEditor::CreateBackgroundBrush(OLE_COLOR BackColor)
{
	// create the edit control background brush
	COLORREF RGBBackColor=RGB(0,0,0);
	if(!SUCCEEDED(OleTranslateColor(BackColor,NULL,&RGBBackColor)))
	{
		throw std::exception();
	}
	HBRUSH BackBrush=CreateSolidBrush(RGBBackColor);
	if(BackBrush==NULL)
	{
		throw std::exception();
	}
	if(m_BackBrush!=NULL)
	{
		(void)DeleteObject(m_BackBrush);
	}
	m_BackBrush=BackBrush;
}

void CSimpleScriptEditor::SetFont(const CComPtr<IFontDisp> &pFontDisp)
{
	// check parameters
	if(pFontDisp==NULL)
	{
		throw std::exception();
	}
	// set the edit control font
	HFONT hOldFont=m_Edit.GetFont();	// NULL for default
	if(m_Edit.IsWindow()==FALSE)
	{
		throw std::exception();
	}
	CComQIPtr<IFont> spFont(pFontDisp);
	if(spFont==NULL)
	{
		throw std::exception();
	}
	HFONT hFont=0;
	if(!SUCCEEDED(spFont->get_hFont(&hFont)))
	{
		throw std::exception();
	}
	m_Edit.SetFont(hFont);
	// set the edit control tab stops
	int TabStops=DEFAULT_TAB_STOPS*4;	// dialog units
	if(m_Edit.SetTabStops(1,&TabStops)==FALSE)
	{
		m_Edit.SetFont(hOldFont);		// restore the old font
		throw std::exception();
	}
}

DWORD CSimpleScriptEditor::GetLongestLineLength()
{
	// determine the length of the longest line in the edit control
	if(m_Edit.IsWindow()==FALSE)
	{
		throw std::exception();
	}
	DWORD Length=0;
	for(long l=0; l<m_Edit.GetLineCount(); l++)
	{
		Length=max(Length,(DWORD)m_Edit.LineLength(m_Edit.LineIndex(l)));
	}
	return Length;
}

HRESULT CSimpleScriptEditor::FinalConstruct()
{
IMP_BEGIN
	// call the base class
	HRESULT hr=CComObjectRootBase::FinalConstruct();
	if(!SUCCEEDED(hr))
	{
		throw CHResult(hr);
	}
	// create the background brush
	CreateBackgroundBrush(m_BackColor);

	// some containers require us to have a valid IFontDisp available at
	// all times in order to modify the font

	// create the default font
	FONTDESC FontDesc;
	CY cy={ DEFAULT_FONT_SIZE*10000, 0 };
	FontDesc.cbSizeofstruct=sizeof(FONTDESC);
	FontDesc.lpstrName=DEFAULT_FONT_NAME;
	FontDesc.cySize=cy;
	FontDesc.sWeight=FW_NORMAL;
	FontDesc.sCharset=DEFAULT_CHARSET;
	FontDesc.fItalic=FALSE;
	FontDesc.fUnderline=FALSE;
	FontDesc.fStrikethrough=FALSE;
	if(!SUCCEEDED(OleCreateFontIndirect(
		&FontDesc,IID_IFontDisp,(void**)&m_spFontDisp)))
	{
		throw CHResult(E_FAIL);
	}
	if(m_spFontDisp==NULL)
	{
		throw CHResult(E_FAIL);
	}
IMP_END
	return RetVal;
}

HRESULT CSimpleScriptEditor::OnDraw(ATL_DRAWINFO &di)
{
	// ATL wizard generated
IMP_BEGIN
	// some containers will only provide a window for us to draw on using
	// this function - ie the control is not created

	if(IsWindow()==FALSE)	// skip if we are created
	{
		// draw rectangle
		CRect Rect=*(RECT*)di.prcBounds;
		Rectangle(di.hdcDraw,Rect.left,Rect.top,Rect.right,Rect.bottom);
		// show text
		LPCTSTR pszText=_T("SimpleScriptEditor");
		SetTextAlign(di.hdcDraw,TA_CENTER|TA_BASELINE);
		TextOut(di.hdcDraw,
			(Rect.left+Rect.right)/2,(Rect.top+Rect.bottom)/2,
				pszText,lstrlen(pszText));
	}
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::put_BorderVisible(VARIANT_BOOL newVal)
{
IMP_BEGIN
	// refresh the edit control
	if(m_Edit.IsWindow())
	{
		if(newVal)	// show border
		{
			(void)m_Edit.ModifyStyleEx(0,WS_EX_CLIENTEDGE);
		}
		else	// hide border
		{
			(void)m_Edit.ModifyStyleEx(WS_EX_CLIENTEDGE,0);
		}
		(void)m_Edit.SetWindowPos(NULL,0,0,0,0,
			SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);
	}
	// set the border visible flag
	m_BorderVisible=newVal;
	PROPERTY_CHANGED(DISPID_BORDERVISIBLE);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::get_BorderVisible(VARIANT_BOOL *pVal)
{
IMP_BEGIN
	// check parameters
	if(pVal==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// get the border visible flag
	*pVal=m_BorderVisible;
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::put_BackColor(OLE_COLOR newVal)
{
IMP_BEGIN
	// create the background brush
	CreateBackgroundBrush(newVal);
	// refresh the edit control
	if(m_Edit.IsWindow())
	{
		(void)m_Edit.Invalidate();
	}
	// set the background color
	m_BackColor=newVal;
	PROPERTY_CHANGED(DISPID_BACKCOLOR);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::get_BackColor(OLE_COLOR *pVal)
{
IMP_BEGIN
	// check parameters
	if(pVal==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// get the background color
	*pVal=m_BackColor;
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::put_ForeColor(OLE_COLOR newVal)
{
IMP_BEGIN
	// refresh the edit control
	if(m_Edit.IsWindow())
	{
		(void)m_Edit.Invalidate();
	}
	// set the foreground color
	m_ForeColor=newVal;
	PROPERTY_CHANGED(DISPID_FORECOLOR);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::get_ForeColor(OLE_COLOR *pVal)
{
IMP_BEGIN
	// check parameters
	if(pVal==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// get the foreground color
	*pVal=m_ForeColor;
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::putref_Font(IFontDisp *pFontDisp)
{
IMP_BEGIN
	// check parameters
	if(pFontDisp==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// set the edit control font
	if(m_Edit.IsWindow())
	{
		SetFont(pFontDisp);
	}
	m_spFontDisp=pFontDisp;
	PROPERTY_CHANGED(DISPID_FONT);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::put_Font(IFontDisp *pFontDisp)
{
IMP_BEGIN
	// check parameters
	if(pFontDisp==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// take a clone of the font
	CComQIPtr<IFont> spFont(pFontDisp);
	if(spFont==NULL)
	{
		throw CHResult(E_FAIL);
	}
	CComPtr<IFont> spFontClone;
	if(!SUCCEEDED(spFont->Clone(&spFontClone)))
	{
		throw CHResult(E_FAIL);
	}
	if(spFontClone==NULL)
	{
		throw CHResult(E_FAIL);
	}
	CComQIPtr<IFontDisp> spFontCloneDisp(spFontClone);
	if(spFontCloneDisp==NULL)
	{
		throw CHResult(E_FAIL);
	}
	// set the edit control font
	if(m_Edit.IsWindow())
	{
		SetFont(spFontCloneDisp.p);
	}
	m_spFontDisp=spFontCloneDisp;
	PROPERTY_CHANGED(DISPID_FONT);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::get_Font(IFontDisp **ppFontDisp)
{
IMP_BEGIN
	// check parameters
	if(ppFontDisp==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// get the edit control font
	*ppFontDisp=m_spFontDisp;
	if(*ppFontDisp!=NULL)	// add ref it
	{
		(void)(*ppFontDisp)->AddRef();
	}
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::InitNew()
{
IMP_BEGIN
	// call the base class
	HRESULT hr=IPersistStreamInitImpl<CSimpleScriptEditor>::InitNew();
	if(!SUCCEEDED(hr))
	{
		throw CHResult(hr);
	}
	// todo : populate this when required
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::OnAmbientPropertyChange(DISPID dispid)
{
IMP_BEGIN
	// call the base class
	HRESULT hr=IOleControlImpl<CSimpleScriptEditor>::OnAmbientPropertyChange(dispid);
	ATLASSERT(hr==S_OK);	// S_OK is the only valid return value
	// disable the edit control in design mode
	// since the user mode ambient property may not be supported by
	// the container we assume run mode if this fails
	if((dispid==DISPID_AMBIENT_USERMODE or dispid==DISPID_UNKNOWN) and
		// the edit control may not have been created by the container if it
		// prefers to create a window only for us to draw on in design mode
		m_Edit.IsWindow())
	{
		BOOL RunMode=TRUE;
		(void)GetAmbientUserMode(RunMode);
		if(RunMode==FALSE)
		{
			(void)m_Edit.EnableWindow(FALSE);
		}
		else
		{
			(void)m_Edit.EnableWindow(TRUE);
		}
	}
IMP_END
	return S_OK;	// must always return S_OK
}

STDMETHODIMP CSimpleScriptEditor::SetObjectRects(LPCRECT prcPos, LPCRECT prcClip)
{
	// ATL wizard generated
IMP_BEGIN
	// call the base class
	IOleInPlaceObjectWindowlessImpl<CSimpleScriptEditor>::SetObjectRects(prcPos,prcClip);
	// size the edit control to fill the full client area
	long cx=prcPos->right-prcPos->left;
	long cy=prcPos->bottom-prcPos->top;
	::SetWindowPos(m_Edit,NULL,0,0,cx,cy,SWP_NOZORDER|SWP_NOACTIVATE);
IMP_END
	return RetVal;
}

BOOL CSimpleScriptEditor::PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet)
{
	// this will be set TRUE if the key press was handled
	BOOL Handled=FALSE;
	// if the edit control has focus
	if(GetFocus()==m_Edit and
		// and this is a key down message
		pMsg->message==WM_KEYDOWN)
	{
		// get shift key modifiers
		BOOL Ctrl  = (GetKeyState(VK_CONTROL) & 0x80000000) ? TRUE : FALSE;
		BOOL Shift = (GetKeyState(VK_SHIFT  ) & 0x80000000) ? TRUE : FALSE;
		BOOL Alt   = (GetKeyState(VK_MENU   ) & 0x80000000) ? TRUE : FALSE;

		// tab key
		if(pMsg->wParam==VK_TAB)
		{
			m_Edit.ReplaceSel(_T("\t"),TRUE);
			Handled=TRUE;
		}
		// arrow key
		if(	pMsg->wParam==VK_LEFT  or
			pMsg->wParam==VK_RIGHT or
			pMsg->wParam==VK_UP	   or
			pMsg->wParam==VK_DOWN  or
			// other navigation
			pMsg->wParam==VK_HOME  or
			pMsg->wParam==VK_END   or
			pMsg->wParam==VK_PRIOR or
			pMsg->wParam==VK_NEXT  or
			// del
			pMsg->wParam==VK_DELETE)
		{
			(void)m_Edit.SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
			Handled=TRUE;
		}
		// cut / copy / paste / undo
		if(Handled==FALSE)
		{
			if(::TranslateAccelerator(*this,m_hAccel,pMsg)!=0)
			{
				Handled=TRUE;
			}
		}
	}
	// if the key press was handled
	if(Handled)
	{
		// signal success
		hRet=S_OK;
	}
	return Handled;
}

LRESULT CSimpleScriptEditor::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	// ATL wizard generated

	// call the base class
	LRESULT lRes=CComControl<CSimpleScriptEditor>::OnSetFocus(uMsg,wParam,lParam,bHandled);
	// give focus to the edit control
	if(m_bInPlaceActive)
	{
		DoVerbUIActivate(&m_rcPos,NULL);
		if(!IsChild(::GetFocus()))
		{
			m_Edit.SetFocus();
		}
	}
	return lRes;
}

LRESULT CSimpleScriptEditor::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	// modify the style
	(void)ModifyStyleEx(0,WS_EX_CONTROLPARENT);
	// create the edit control
	CRect ClientRect(0,0,0,0);
	if(m_ContainedEdit.Create(*this,ClientRect,_T(""),
		// standard window styles
		WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|
		// edit control styles
		ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE|ES_WANTRETURN,
		// extended styles
		(m_BorderVisible) ? WS_EX_CLIENTEDGE : 0,
		// id
		IDC_EDIT)==NULL)
	{
		return -1;
	}
	// wrap the edit control
	m_Edit.m_hWnd=NULL;	// allow reuse
	m_Edit.Attach(m_ContainedEdit);
	// set the edit control font
	try { SetFont(m_spFontDisp); }
	catch(std::exception &)
	{
		return -1;
	}
	// disable the edit control in design mode
	// since the user mode ambient property may not be supported by
	// the container we assume run mode if this fails
	BOOL RunMode=TRUE;
	(void)GetAmbientUserMode(RunMode);
	if(RunMode==FALSE)
	{
		(void)m_Edit.EnableWindow(FALSE);
	}
	// load the edit control accelerators
	m_hAccel=LoadAccelerators(_Module.GetResourceInstance(),
		MAKEINTRESOURCE(IDA_SIMPLESCRIPTEDITOR));
	if(m_hAccel==NULL)
	{
		return -1;
	}
	return 0;
}

LRESULT CSimpleScriptEditor::OnCtlColorEdit(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	// the edit control should be our only child
	ATLASSERT((HWND)lParam==m_Edit);
	// assume the worst
	bHandled=FALSE;
	if(m_BackBrush==NULL)	// todo : remove this redundant check
	{
		return NULL;
	}
	// convert OLE colors to RGB
	COLORREF RGBBackColor=RGB(0,0,0);
	if(!SUCCEEDED(OleTranslateColor(m_BackColor,NULL,&RGBBackColor)))
	{
		return NULL;
	}
	COLORREF RGBForeColor=RGB(0,0,0);
	if(!SUCCEEDED(OleTranslateColor(m_ForeColor,NULL,&RGBForeColor)))
	{
		return NULL;
	}
	// modify the dc
	HDC hdc=(HDC)wParam;
	if(SetTextColor(hdc,RGBForeColor)==CLR_INVALID)
	{
		return NULL;
	}
	if(SetBkColor(hdc,RGBBackColor)==CLR_INVALID)
	{
		return NULL;
	}
	// we handled this
	bHandled=TRUE;
	// return the background brush
	return (LRESULT)m_BackBrush;
}

LRESULT CSimpleScriptEditor::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	// to prevent flicker do not erase the background
	return TRUE;
}

LRESULT CSimpleScriptEditor::OnEditChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	// set the modified flag
	SetModified(TRUE);
	return 0;
}

LRESULT CSimpleScriptEditor::OnCut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	// delegate to ISimpleScriptEditor
	(void)Cut();
	return 0;
}

LRESULT CSimpleScriptEditor::OnCopy(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	// delegate to ISimpleScriptEditor
	(void)Copy();
	return 0;
}

LRESULT CSimpleScriptEditor::OnPaste(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	// delegate to ISimpleScriptEditor
	(void)Paste();
	return 0;
}

LRESULT CSimpleScriptEditor::OnUndo(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	// delegate to ISimpleScriptEditor
	(void)Undo();
	return 0;
}

STDMETHODIMP CSimpleScriptEditor::About()
{
IMP_BEGIN
	// show the about box
	CSimpleDialog<IDD_ABOUT_SIMPLESCRIPTEDITOR> AboutDlg;
	(void)AboutDlg.DoModal();
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::Cut()
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// cut
	(void)m_Edit.SendMessage(WM_CUT,0,0);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::Copy()
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// copy
	(void)m_Edit.SendMessage(WM_COPY,0,0);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::Paste()
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// paste
	(void)m_Edit.SendMessage(WM_PASTE,0,0);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::Undo()
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// undo
	(void)m_Edit.SendMessage(WM_UNDO,0,0);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::RefreshModifiedState()
{
IMP_BEGIN
	// fire the modified state changed event
	(void)Fire_ModifiedStateChanged(B2VB(m_Modified));
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::get_Modified(VARIANT_BOOL *pVal)
{
IMP_BEGIN
	// check parameters
	if(pVal==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// return the modified flag
	*pVal=B2VB(m_Modified);
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::put_Modified(VARIANT_BOOL newVal)
{
IMP_BEGIN
	// set the modified flag
	SetModified(VB2B(newVal));
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::LockExternal(BOOL Lock)
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// update the lock count
	Lock ? m_LockCount++ : m_LockCount--;
	// update the edit control state
	if(m_LockCount > 0)
	{
		// reduce flicker
		m_Edit.SetRedraw(FALSE);
		// read only
		if(m_Edit.SetReadOnly(TRUE)==FALSE)
		{
			throw CHResult(E_FAIL);
		}
	}
	else
	{
		// read writable
		if(m_Edit.SetReadOnly(FALSE)==FALSE)
		{
			throw CHResult(E_FAIL);
		}
		// prevent flicker
		m_Edit.SetRedraw(TRUE);
		(void)m_Edit.InvalidateRect(NULL,FALSE);
	}
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::GetLineCount(DWORD *pCount)
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// check parameters
	if(pCount==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// return the number of lines in the edit control
	*pCount=m_Edit.GetLineCount();
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::FindText(
	DWORD Start, LPCOLESTR pText, BOOL *pFound, DWORD *pLine)
{
	USES_CONVERSION;
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// check parameters
	if(Start >= (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	if(pText==NULL)
	{
		throw CHResult(E_POINTER);
	}
	if(wcslen(pText)==0)
	{
		throw CHResult(E_INVALIDARG);
	}
	if(pFound==NULL)
	{
		throw CHResult(E_POINTER);
	}
	if(pLine==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// create a buffer large enough to hold any line of text
	// due to the way edit controls work this buffer must be at
	// least 2 bytes wide since the actual buffer size is placed
	// in the first WORD when calling EM_GETLINE
	DWORD LongestLineLength=GetLongestLineLength();
	auto_array_ptr<TCHAR> Buf(new TCHAR [max(2,LongestLineLength+1)]);
	// look for the text in each line
	*pFound=FALSE;
	for(long l=Start; l<m_Edit.GetLineCount(); l++)
	{
		// get the next line
		DWORD Count=m_Edit.GetLine(l,Buf.get(),LongestLineLength);
		Buf.get()[Count]=_T('\0');
		// look for an exact substring match
		std::wstring str(T2CW(Buf.get()));
		if(str.find(pText)!=std::wstring::npos)
		{
			*pLine=l;
			*pFound=TRUE;
			break;	// finished
		}
	}
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::InsertLines(
	DWORD Start, DWORD Count, LPCOLESTR *pLines)
{
	USES_CONVERSION;
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// check parameters
	if(Start > (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	if(pLines==NULL)
	{
		throw CHResult(E_POINTER);
	}
	if(Count==0)	// special case
	{
		throw CHResult(S_OK);
	}
	// create CRLF tokenised lines
	std::list<std::wstring> Lines;
	ComServerStringArrayFromClient(Count,pLines,Lines);
	std::wstring TokenisedLines;
	if(Start==m_Edit.GetLineCount())
	{
		TokenisedLines=L"\r\n";	// required to create a new line
	}
	std::list<std::wstring>::const_iterator iter=Lines.begin();
	while(iter!=Lines.end())
	{
		TokenisedLines+=iter->c_str();
		iter++;
		if(iter!=Lines.end())	// if more lines follow
		{
			TokenisedLines+=L"\r\n";
		}
	}
	// begin following lines on a new line
	if(Start!=m_Edit.GetLineCount())
	{
		TokenisedLines+=L"\r\n";
	}
	// get the insertion point
	DWORD StartChar=0;
	if(Start==m_Edit.GetLineCount())
	{
		StartChar=m_Edit.LineIndex(Start-1);
		StartChar+=m_Edit.LineLength(StartChar);	// end of last line
	}
	else
	{
		StartChar=m_Edit.LineIndex(Start);
	}
	// move to the insertion point
	m_Edit.SetSel(StartChar,StartChar,TRUE);
	// insert the line
	m_Edit.ReplaceSel(W2CT(TokenisedLines.c_str()));
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::GetLines(
	DWORD Start, DWORD Count, LPOLESTR **ppLines)
{
	USES_CONVERSION;
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// check parameters
	if(Start >= (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	if(Start+Count > (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	if(ppLines==NULL)
	{
		throw CHResult(E_POINTER);
	}
	// create a buffer large enough to hold any line of text
	// due to the way edit controls work this buffer must be at
	// least 2 bytes wide since the actual buffer size is placed
	// in the first WORD when calling EM_GETLINE
	DWORD LongestLineLength=GetLongestLineLength();
	auto_array_ptr<TCHAR> Buf(new TCHAR [max(2,LongestLineLength+1)]);
	// get the required lines
	std::list<std::wstring> Lines;
	for(long l=Start; l<(long)(Start+Count); l++)
	{
		// get the next line
		DWORD Count=m_Edit.GetLine(l,Buf.get(),LongestLineLength);
		Buf.get()[Count]=_T('\0');
		// add it to the array
		Lines.push_back(T2CW(Buf.get()));
	}
	*ppLines=const_cast<LPOLESTR*>(ComServerStringArrayToClient(Lines));
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::DeleteLines(DWORD Start, DWORD Count)
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// check parameters
	if(Start >= (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	if(Start+Count > (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	if(Count==0)	// special case
	{
		throw CHResult(S_OK);
	}
	// get the last line to delete
	DWORD End=Start+Count-1;
	// deletion start point
	DWORD StartChar=0;
	// deletion end point
	DWORD EndChar=0;

	// case (a)
	// there are no preceding or following lines
	if(Start==0 and End==m_Edit.GetLineCount()-1)
	{
		// deletion start point
		StartChar=m_Edit.LineIndex(Start);
		// deletion end point
		EndChar=m_Edit.LineIndex(End);
		EndChar+=m_Edit.LineLength(EndChar);
	}
	// case (b)
	// there are no preceding lines
	else if(Start==0)
	{
		// deletion start point
		StartChar=m_Edit.LineIndex(Start);
		// deletion end point
		EndChar=m_Edit.LineIndex(End+1);
	}
	// case (c)
	// there are no following lines
	else if(End==m_Edit.GetLineCount()-1)
	{
		// deletion start point
		StartChar=m_Edit.LineIndex(Start-1);
		StartChar+=m_Edit.LineLength(StartChar);
		// deletion end point
		EndChar=m_Edit.LineIndex(End);
		EndChar+=m_Edit.LineLength(EndChar);
	}

	// select the lines to delete
	m_Edit.SetSel(StartChar,EndChar,TRUE);
	// delete the lines
	m_Edit.ReplaceSel(_T(""));
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::ModifyLines(
	DWORD Start, DWORD End, DWORD Count, LPCOLESTR *pLines)
{
IMP_BEGIN
	// todo : add this when required
	throw CHResult(E_NOTIMPL);
	// todo : ensure the modified flag is correct
IMP_END
	return RetVal;
}

STDMETHODIMP CSimpleScriptEditor::GoToLine(DWORD Line)
{
IMP_BEGIN
	// check the edit control exists
	if(m_Edit.IsWindow()==FALSE)
	{
		throw CHResult(E_FAIL);
	}
	// check parameters
	if(Line >= (DWORD)m_Edit.GetLineCount())
	{
		throw CHResult(E_INVALIDARG);
	}
	// move the cursor to the requested line
	if(m_LockCount > 0)
	{
		m_Edit.SetRedraw(TRUE);
	}
	long StartChar=m_Edit.LineIndex(Line);
	m_Edit.SetSel(StartChar,StartChar);
	if(m_LockCount > 0)
	{
		m_Edit.SetRedraw(FALSE);
	}
	// indirectly give focus to the edit control
	(void)SetFocus();
IMP_END
	return RetVal;
}

} // namespace AxSimpleScriptEditor

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

DaveShep
Web Developer
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190526.1 | Last Updated 1 Aug 2009
Article Copyright 2005 by DaveShep
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid