⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 host.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
 *	@doc INTERNAL
 *
 *	@module	HOST.C	-- Text Host for CreateWindow() Rich Edit Control |
 *		Implements CTxtWinHost message and ITextHost interfaces
 *		
 *	Original Author: <nl>
 *		Original RichEdit code: David R. Fulmer
 *		Christian Fortini
 *		Murray Sargent
 *
 *	History: <nl>
 *		8/1/95   ricksa  Documented and brought to new ITextHost definition
 *		10/28/95 murrays cleaned up and moved default char/paraformat cache
 *						 cache code into text services
 *
 *	Set tabs every four (4) columns
 */
#include "_common.h"
#include "_host.h"
#include "imm.h"
#include "_format.h"
#include "_edit.h"
#include "_cfpf.h"
#include "_ime.h"
ASSERTDATA

												 
LONG CTxtWinHost::_xWidthSys = 0;			// Average char width of system font
LONG CTxtWinHost::_yHeightSys = 0;			// Height of system font

LOCAL BOOL GetIconic(
	HWND hwnd) 
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "GetIconic");

	while(hwnd)
	{
		if(IsIconic(hwnd))
			return TRUE;
		hwnd = GetParent(hwnd);
	}
	return FALSE;
}

//////////////// CTxtWinHost Creation/Initialization/Destruction ///////////////////////

/*
 *	CTxtWinHost::OnNCCreate (hwnd, pcs)
 *
 *	@mfunc
 *		Static global method to handle WM_NCCREATE message (see remain.c)
 */
LRESULT CTxtWinHost::OnNCCreate(
	HWND hwnd,
	const CREATESTRUCT *pcs)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnNCCreate");

#if defined DEBUG && !defined(PEGASUS) 
	GdiSetBatchLimit(1);
#endif

	CTxtWinHost *phost = new CTxtWinHost();
	if(!phost)
		return 0;
	
	if (!phost->Init(hwnd, pcs))				// Stores phost in associated
	{											//  window data
		phost->Shutdown();
		delete phost;
		return 0;
	}

	return TRUE;
}

/*
 *	CTxtWinHost::OnNCDestroy (phost)
 *
 *	@mfunc
 *		Static global method to handle WM_CREATE message
 *
 *	@devnote
 *		phost ptr is stored in window data (GetWindowLong())
 */
void CTxtWinHost::OnNCDestroy(
	CTxtWinHost *phost)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnNCDestroy");

	phost->Shutdown();
	phost->Release();
}

/*
 *	CTxtWinHost::CTxtWinHost()
 *
 *	@mfunc
 *		constructor
 */
CTxtWinHost::CTxtWinHost() :
	_fBorder(0),
	_fInBottomless(0),
	_fInDialogBox(0),
	_fEnableAutoWordSel(1),
	_fIconic(0),
	_fHidden(0),
	_fNotSysBkgnd(0),
	_fWindowLocked(0),
	_fRegisteredForDrop(1),
	_fVisible(1),
	_fResized(0),
	_fDisabled(0),
	_fKeyMaskSet(1),
	_fMouseMaskSet(1),
	_fScrollMaskSet(1),
	_fUseSpecialSetSel(1),
	_fEmSetRectCalled(1),
	_fAccumulateDBC(0)

{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::CTxtWinHost");

	_fRegisteredForDrop = FALSE;
	_crefs = 1;	
	if ( !_fNotSysBkgnd)
		_crBackground = GetSysColor(COLOR_WINDOW);
}

/*
 *	CTxtWinHost::~CTxtWinHost()
 *
 *	@mfunc
 *		destructor
 */
CTxtWinHost::~CTxtWinHost()
{
	if( _pserv )
	{
		Shutdown();
	}
}

/*
 *	CTxtWinHost::Shutdown()
 *
 *	@mfunc	shuts down this object, but doesn't delete memory
 */
void CTxtWinHost::Shutdown()
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::Shutdown");
	
	RevokeDragDrop();						// Revoke our drop target

	if( _pserv )
	{
		_pserv->OnTxInPlaceDeactivate();
		_pserv->Release();
		_pserv = NULL;
	}

	ImmTerminate();					// terminate only useful on Mac.

	if(_hwnd)
		SetWindowLong(_hwnd, ibPed, 0);
}

/*
 *	CTxtWinHost::Init (hwnd, pcs)
 *
 *	@mfunc
 *		Initialize this CTxtWinHost
 */
BOOL CTxtWinHost::Init(
	HWND hwnd,					//@parm Window handle for this control
	const CREATESTRUCT *pcs)	//@parm Corresponding CREATESTRUCT
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::Init");

	HDC			hdc;
	HFONT		hfontOld;
	HRESULT		hr;
	IUnknown *	pUnk;
	TEXTMETRIC	tm;

	if( pcs->lpszClass == NULL )
		return FALSE;

	// Set pointer back to CTxtWinHost from the window
	if(hwnd)
		SetWindowLong(hwnd, ibPed, (LONG)this);
		
	_hwnd = hwnd;

 	// Edit controls created without a window are multiline by default
	// so that paragraph formats can be
	_dwStyle = ES_MULTILINE;
	_fHidden = TRUE;
	
	if(pcs)
	{
		_hwndParent = pcs->hwndParent;
		_dwExStyle	= pcs->dwExStyle;
		_dwStyle	= pcs->style;

		// According to the edit control documentation WS_HSCROLL implies that
		// ES_AUTOSCROLL is set and WS_VSCROLL implies that ES_AUTOVSCROLL is
		// set. Here, we make this so.
		if(_dwStyle & WS_HSCROLL)
			_dwStyle |= ES_AUTOHSCROLL;

		if(_dwStyle & WS_VSCROLL)
			_dwStyle |= ES_AUTOVSCROLL;

		_fBorder = !!(_dwStyle & WS_BORDER);

		if((_dwStyle & ES_SUNKEN) || (_dwExStyle & WS_EX_CLIENTEDGE))
			_fBorder = TRUE;

		// handle default passwords
		if(_dwStyle & ES_PASSWORD)
			_chPassword = TEXT('*');

		// handle default disabled
		if(_dwStyle & WS_DISABLED)
			_fDisabled = TRUE;

		// On Win95 ES_SUNKEN and WS_BORDER get mapped to WS_EX_CLIENTEDGE
		if(_fBorder && (dwMajorVersion >= VERS4))
        {
			_dwExStyle |= WS_EX_CLIENTEDGE;
			SetWindowLong(_hwnd, GWL_EXSTYLE, _dwExStyle);
        }
	}

	if (0 == _xWidthSys)
	{
		// Init system metrics
		hdc = GetDC(hwnd);
		if(!hdc)
			return FALSE;

   		hfontOld = (HFONT)SelectObject(hdc, GetStockObject(SYSTEM_FONT));
		if(!hfontOld)
			return FALSE;

		W32->GetTextMetrics(hdc, &tm);
		SelectObject(hdc, hfontOld);

		_xWidthSys = (INT) tm.tmAveCharWidth;
		_yHeightSys = (INT) tm.tmHeight;

		ReleaseDC(hwnd, hdc);
	}

	_xInset = _xWidthSys / 2;
	_yInset = _yHeightSys / 4;

	// At this point the border flag is set and so is the pixels per inch
	// so we can initalize the inset.
	SetDefaultInset();

	// Create Text Services component
	if(FAILED(CreateTextServices(NULL, this, &pUnk)))
		return FALSE;

	// Get text services interface
	hr = pUnk->QueryInterface(IID_ITextServices, (void **)&_pserv);

	// Regardless of whether the previous call succeeded or failed, we are
	// done with the private interface.
	pUnk->Release();

	if(FAILED(hr))
		return FALSE;

	// If the class name is "RichEdit", then we need to turn on the
	// RichEdit 1.0 compatibility bit.  Otherwise, we can use the normal
	// version.
	
#if 0 // Need to figure out how to test for atoms.
	if( IsAtom wcsicmp(pcs->lpszClass, L"RICHEDIT") == 0 )
	{
		 ((CTxtEdit *)_pserv)->Set10Mode();
	}
#endif

	// Set window text
	if(pcs && pcs->lpszName)
	{
		if(FAILED(_pserv->TxSetText((TCHAR *)pcs->lpszName)))
		{
			SafeReleaseAndNULL((IUnknown **)&_pserv);
			return FALSE;
		}
	}

	PARAFORMAT PF;							// If center or right alignment,
	if(_dwStyle & (ES_CENTER | ES_RIGHT))	//  tell text services
	{
		PF.cbSize = sizeof(PARAFORMAT);
		PF.dwMask = PFM_ALIGNMENT;
		PF.wAlignment = (_dwStyle & ES_RIGHT) ? PFA_RIGHT : PFA_CENTER;
		_pserv->TxSendMessage(EM_SETPARAFORMAT, SPF_SETDEFAULT, (LPARAM)&PF, NULL);
	}

	if( !ImmInitialize() )			// Mac Only
	{
		#if defined(DEBUG) && defined(MACPORT)
		OutputDebugString(TEXT("Could not register Imm ImmInitializeForMac.\r\n"));
		#endif	// DEBUG
	}

	return TRUE;
}

/*
 *	CTxtWinHost::OnCreate (pcs)
 *
 *	@mfunc
 *		Handle WM_CREATE message
 *
 *	@rdesc
 *		LRESULT = -1 if failed to in-place activate; else 0
 */
LRESULT CTxtWinHost::OnCreate(
	const CREATESTRUCT *pcs)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnCreate");

	RECT rcClient;

	// sometimes, these values are -1 (from windows itself); just treat them
	// as zero in that case
	LONG cy = ( pcs->cy < 0 ) ? 0 : pcs->cy;
	LONG cx = ( pcs->cx < 0 ) ? 0 : pcs->cx;


	rcClient.top = pcs->y;
	rcClient.bottom = rcClient.top + cy;
	rcClient.left = pcs->x;
	rcClient.right = rcClient.left + cx;
	
	// Notify Text Services that we are in place active
	if(FAILED(_pserv->OnTxInPlaceActivate(&rcClient)))
		return -1;

	DWORD dwStyle = GetWindowLong(_hwnd, GWL_STYLE);
	
	// Hide all scrollbars to start
	if(_hwnd && !(_dwStyle & ES_DISABLENOSCROLL))
	{
		SetScrollRange(_hwnd, SB_VERT, 0, 0, TRUE);
		SetScrollRange(_hwnd, SB_HORZ, 0, 0, TRUE);

		dwStyle &= ~(WS_VSCROLL | WS_HSCROLL);
		SetWindowLong(_hwnd, GWL_STYLE, dwStyle);
	}

	if (!(dwStyle & (ES_READONLY | ES_NOOLEDRAGDROP)) )
	{
		// This isn't a read only window or a no drop window,
		// so we need a drop target.
		RegisterDragDrop();
	}

	_usIMEMode = 0;	
	if (dwStyle & ES_NOIME)
		_usIMEMode = ES_NOIME;
	else if (dwStyle & ES_SELFIME)
		_usIMEMode = ES_SELFIME;

	return 0;
}


/////////////////////////////////  IUnknown ////////////////////////////////

HRESULT CTxtWinHost::QueryInterface(REFIID riid, void **ppv)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::QueryInterface");
  
  	if( IsEqualIID(riid, IID_IUnknown) )
	{
		*ppv = (IUnknown *)this;
	}
	else if( IsEqualIID(riid, IID_ITextHost) )
	{
		*ppv = (ITextHost *)this;
	}
	else if( IsEqualIID(riid, IID_ITextHost2) )
	{
		*ppv = (ITextHost2 *)this;
	}
	else
	{
		*ppv = NULL;
	}

	if( *ppv )
	{
		AddRef();
		return NOERROR;
	}

	return E_NOINTERFACE;
}

ULONG CTxtWinHost::AddRef(void)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::AddRef");

	return ++_crefs;
}

ULONG CTxtWinHost::Release(void)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::Release");

	--_crefs;

	if( _crefs == 0 )
	{
		delete this;
		return 0;
	}

	return _crefs;
}


//////////////////////////////// Activation ////////////////////////////////

//////////////////////////////// Properties ////////////////////////////////


TXTEFFECT CTxtWinHost::TxGetEffects() const
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxGetEffects");

	if( (_dwStyle & ES_SUNKEN) || (_dwExStyle & WS_EX_CLIENTEDGE) )
	{
		return TXTEFFECT_SUNKEN;
	}
	else
	{
		return TXTEFFECT_NONE;
	}
}



//////////////////////////// System API wrapper ////////////////////////////



///////////////////////  Windows message dispatch methods  ///////////////////////////////

/*
 *	CTxtWinHost::TxWindowProc (hwnd, msg, wparam, lparam)
 *
 *	@mfunc
 *		Handle window messages pertinent to the host and pass others on to
 *		text services. Called by RichEditWndProc() in remain.c.
 *
 *	#rdesc
 *		LRESULT = (code processed) ? 0 : 1
 */
LRESULT CTxtWinHost::TxWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxWindowProc");

	LRESULT	lres = 0;
	HRESULT hr;

	// in certain out-of-memory situations, clients may try to re-enter us 
	// with calls.  Just bail on the call if we don't have a text services
	// pointer.
	if( !_pserv )
	{
		return 0;
	}

	// stabilize ourselves
	AddRef();

	// Handle mouse/keyboard message filter notifications
	if( _fKeyMaskSet || _fMouseMaskSet || _fScrollMaskSet )
	{
		// We may need to fire a MSGFILTER notification.  In
		// the tests below, we check to see if either mouse
		// or key events are hit.  If so, then we fire the msgfilter
		// notification.  The list of events was generated from
		// RichEdit 1.0 sources.

		MSGFILTER msgfltr;

		/* RichEdit Compatibility issue: The following code gets all
		 * keyboard and mouse actions, but the RichEdit 1.0 code only got
		 * WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
		 * WM_MOUSEACTIVATE, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE,
		 * WM_RBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP
		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -