📄 host.cpp
字号:
* @comm
* Called from the message loop to handle EM_SETREADONLY
* or when the style ES_NOIME is changed.
*
*/
void CTxtWinHost::ImmAssociateNULLContext(BOOL fReadOnly)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::ImmAssociateNULLContext");
if ( !fHaveIMMProcs )
return;
Assert( _hwnd );
if ( fReadOnly && !_oldhimc )
{
// terminate IME Composition and save old himc
_oldhimc = pImmAssociateContext( _hwnd, (HIMC) NULL );
}
else if ( fReadOnly == FALSE && _oldhimc )
{
HIMC prevhime;
// restore previous himc and enable IME Composition
prevhime = pImmAssociateContext( _hwnd, _oldhimc );
Assert( !prevhime );
_oldhimc = (HIMC) NULL;
}
return;
}
LOCAL void DrawRectFn(
HDC hdc,
RECT *prc,
INT icrTL,
INT icrBR,
BOOL fBot,
BOOL fRght)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "DrawRectFn");
COLORREF cr;
COLORREF crSave;
RECT rc;
cr = GetSysColor(icrTL);
crSave = SetBkColor(hdc, cr);
// top
rc = *prc;
rc.bottom = rc.top + 1;
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
// left
rc.bottom = prc->bottom;
rc.right = rc.left + 1;
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
if(icrTL != icrBR)
{
cr = GetSysColor(icrBR);
SetBkColor(hdc, cr);
}
// right
rc.right = prc->right;
rc.left = rc.right - 1;
if(!fBot)
rc.bottom -= sysparam.GetCyHScroll();
if(fRght)
{
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
}
// bottom
if(fBot)
{
rc.left = prc->left;
rc.top = rc.bottom - 1;
if(!fRght)
rc.right -= sysparam.GetCxVScroll();
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
}
SetBkColor(hdc, crSave);
}
#define cmultBorder 1
void CTxtWinHost::OnSunkenWindowPosChanging(
HWND hwnd,
WINDOWPOS *pwndpos)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSunkenWindowPosChanging");
if( IsWindowVisible(hwnd) )
{
RECT rc;
HWND hwndParent;
GetWindowRect(hwnd, &rc);
InflateRect(&rc, sysparam.GetCxBorder() * cmultBorder, sysparam.GetCyBorder() * cmultBorder);
hwndParent = GetParent(hwnd);
MapWindowPoints(HWND_DESKTOP, hwndParent, (POINT *) &rc, 2);
InvalidateRect(hwndParent, &rc, FALSE);
}
}
void CTxtWinHost::DrawSunkenBorder(
HWND hwnd,
HDC hdc)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::DrawSunkenBorder");
BOOL fVScroll = (_dwStyle & WS_VSCROLL);
BOOL fHScroll = (_dwStyle & WS_HSCROLL);
RECT rc;
RECT rcParent;
HWND hwndParent;
// if we're not visible, don't do anything.
if( !IsWindowVisible(hwnd) )
{
return;
}
GetWindowRect(hwnd, &rc);
hwndParent = GetParent(hwnd);
rcParent = rc;
MapWindowPoints(HWND_DESKTOP, hwndParent, (POINT *)&rcParent, 2);
InflateRect(&rcParent, sysparam.GetCxBorder(), sysparam.GetCyBorder());
OffsetRect(&rc, -rc.left, -rc.top);
if (_pserv)
{
// If we have a text control then get whether it thinks there are
// scroll bars.
_pserv->TxGetHScroll(NULL, NULL, NULL, NULL, &fHScroll);
_pserv->TxGetVScroll(NULL, NULL, NULL, NULL, &fVScroll);
}
// draw inner rect
DrawRectFn(hdc, &rc, icr3DDarkShadow, COLOR_BTNFACE,
!fHScroll, !fVScroll);
// draw outer rect
hwndParent = GetParent(hwnd);
hdc = GetDC(hwndParent);
DrawRectFn(hdc, &rcParent, COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT,
TRUE, TRUE);
ReleaseDC(hwndParent, hdc);
}
LRESULT CTxtWinHost::OnSize(
HWND hwnd,
WORD fwSizeType,
int nWidth,
int nHeight)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSize");
RECT rc;
TxGetClientRect(&rc);
if(!_fVisible)
{
_fIconic = GetIconic(hwnd);
if(!_fIconic)
_fResized = TRUE;
}
else
{
if(GetIconic(hwnd))
{
TRACEINFOSZ("Iconicizing");
_fIconic = TRUE;
}
else
{
// We use this property because this will force a recalc.
// We don't actually recalc on a client rect change because
// most of the time it is pointless. We force one here because
// some applications use size changes to calculate the optimal
// size of the window.
_pserv->OnTxPropertyBitsChange(TXTBIT_EXTENTCHANGE,
TXTBIT_EXTENTCHANGE);
if(_fIconic)
{
TRACEINFOSZ("Restoring from iconic");
InvalidateRect(hwnd, NULL, FALSE);
_fIconic = FALSE;
}
if ((TxGetEffects() == TXTEFFECT_SUNKEN) // Draw borders
&& (dwMajorVersion < VERS4))
DrawSunkenBorder(hwnd, NULL);
}
}
return 0;
}
HRESULT CTxtWinHost::OnTxVisibleChange(
BOOL fVisible)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnTxVisibleChange");
_fVisible = fVisible;
if(!_fVisible && _fResized)
{
RECT rc;
// Control was resized while hidden,
// need to really resize now
TxGetClientRect(&rc);
_fResized = FALSE;
_pserv->OnTxPropertyBitsChange(TXTBIT_CLIENTRECTCHANGE,
TXTBIT_CLIENTRECTCHANGE);
}
return S_OK;
}
//////////////////////////// ITextHost Interface ////////////////////////////
// @doc EXTERNAL
/*
* CTxtWinHost::TxGetDC()
*
* @mfunc
* Abstracts GetDC so Text Services does not need a window handle.
*
* @rdesc
* A DC or NULL in the event of an error.
*
* @comm
* This method is only valid when the control is in-place active;
* calls while inactive may fail.
*/
HDC CTxtWinHost::TxGetDC()
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxGetDC");
Assert(_hwnd);
return ::GetDC(_hwnd);
}
/*
* CTxtWinHost::TxReleaseDC (hdc)
*
* @mfunc
* Release DC gotten by TxGetDC.
*
* @rdesc
* 1 - HDC was released. <nl>
* 0 - HDC was not released. <nl>
*
* @comm
* This method is only valid when the control is in-place active;
* calls while inactive may fail.
*/
int CTxtWinHost::TxReleaseDC(
HDC hdc ) //@parm DC to release
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxReleaseDC");
Assert(_hwnd);
return ::ReleaseDC (_hwnd, hdc);
}
/*
* CTxtWinHost::TxShowScrollBar (fnBar, fShow)
*
* @mfunc
* Shows or Hides scroll bar in Text Host window
*
* @rdesc
* TRUE on success, FALSE otherwise
*
* @comm
* This method is only valid when the control is in-place active;
* calls while inactive may fail.
*/
BOOL CTxtWinHost::TxShowScrollBar(
INT fnBar, //@parm Specifies scroll bar(s) to be shown or hidden
BOOL fShow ) //@parm Specifies whether scroll bar is shown or hidden
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxShowScrollBar");
Assert(_hwnd);
LONG nMax;
if (fnBar == SB_HORZ)
_pserv->TxGetHScroll(NULL, &nMax, NULL, NULL, NULL);
else
_pserv->TxGetVScroll(NULL, &nMax, NULL, NULL, NULL);
return W32->ShowScrollBar(_hwnd, fnBar, fShow, nMax);
}
/*
* CTxtWinHost::TxEnableScrollBar (fuSBFlags, fuArrowflags)
*
* @mfunc
* Enables or disables one or both scroll bar arrows
* in Text Host window.
*
* @rdesc
* If the arrows are enabled or disabled as specified, the return
* value is TRUE. If the arrows are already in the requested state or an
* error occurs, the return value is FALSE.
*
* @comm
* This method is only valid when the control is in-place active;
* calls while inactive may fail.
*/
BOOL CTxtWinHost::TxEnableScrollBar (
INT fuSBFlags, //@parm Specifies scroll bar type
INT fuArrowflags ) //@parm Specifies whether and which scroll bar arrows
// are enabled or disabled
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxEnableScrollBar");
Assert(_hwnd);
return W32->EnableScrollBar(_hwnd, fuSBFlags, fuArrowflags);
}
/*
* CTxtWinHost::TxSetScrollRange (fnBar, nMinPos, nMaxPos, fRedraw)
*
* @mfunc
* Sets the minimum and maximum position values for the specified
* scroll bar in the text host window.
*
* @rdesc
* If the arrows are enabled or disabled as specified, the return value
* is TRUE. If the arrows are already in the requested state or an error
* occurs, the return value is FALSE.
*
* @comm
* This method is only valid when the control is in-place active;
* calls while inactive may fail.
*/
BOOL CTxtWinHost::TxSetScrollRange(
INT fnBar, //@parm Scroll bar flag
LONG nMinPos, //@parm Minimum scrolling position
INT nMaxPos, //@parm Maximum scrolling position
BOOL fRedraw ) //@parm Specifies whether scroll bar should be redrawn
{ // to reflect change
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetScrollRange");
Assert(_hwnd);
if (NULL == _pserv)
{
// We are initializing so do this instead of callback
return ::SetScrollRange(_hwnd, fnBar, nMinPos, nMaxPos, fRedraw);
}
SetScrollInfo(fnBar, fRedraw);
return TRUE;
}
/*
* CTxtWinHost::TxSetScrollPos (fnBar, nPos, fRedraw)
*
* @mfunc
* Tells Text host to set the position of the scroll box (thumb) in the
* specified scroll bar and, if requested, redraws the scroll bar to
* reflect the new position of the scroll box.
*
* @rdesc
* TRUE on success; FALSE otherwise.
*
* @comm
* This method is only valid when the control is in-place active;
* calls while inactive may fail.
*/
BOOL CTxtWinHost::TxSetScrollPos (
INT fnBar, //@parm Scroll bar flag
INT nPos, //@parm New position in scroll box
BOOL fRedraw ) //@parm Redraw flag
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxSetScrollPos");
Assert(_hwnd);
if (NULL == _pserv)
{
// We are initializing so do this instead of callback
return ::SetScrollPos(_hwnd, fnBar, nPos, fRedraw);
}
SetScrollInfo(fnBar, fRedraw);
return TRUE;
}
/*
* CTxtWinHost::TxInvalidateRect (prc, fMode)
*
* @mfunc
* Adds a rectangle to the Text Host window's update region
*
* @comm
* This function may be called while inactive; however the host
* implementation is free to invalidate an area greater than
* the requested rect.
*/
void CTxtWinHost::TxInvalidateRect(
LPCRECT prc, //@parm Address of rectangle coordinates
BOOL fMode ) //@parm Erase background flag
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxInvalidateRect");
Assert(_hwnd);
if (!_fVisible)
{
// There doesn't seem to be a deterministic way to determine whether
// our window is visible or not via message notifications. Therefore,
// we check this each time incase it might have changed.
_fVisible = IsWindowVisible(_hwnd);
if (_fVisible)
{
OnTxVisibleChange(TRUE);
}
}
// Don't bother with invalidating rect if we aren't visible
if (_fVisible)
{
if (IsTransparentMode())
{
RECT rcParent;
HWND hParent = ::GetParent (_hwnd);
Assert(hParent);
// For transparent mode, we need to invalidate the parent
// so it will paint the background.
if (prc)
{
rcParent = *prc;
}
else
{
TxGetClientRect(&rcParent);
}
::MapWindowPoints(_hwnd, hParent, (LPPOINT)&rcParent, 2);
::InvalidateRect(hParent, &rcParent, fMode);
// ::HideCaret(_hwnd);
}
::InvalidateRect(_hwnd, prc, fMode);
}
}
/*
* CTxtWinHost::TxViewChange (fUpdate)
*
* @mfunc
* Notify Text Host that update region should be repainted.
*
* @comm
* It is the responsibility of the text services to call
* TxViewChanged every time it decides that it's visual representation
* has changed, regardless of whether the control is active or
* not. If the control is active, the text services has the additional
* responsibility of making sure the controls window is updated.
* It can do this in a number of ways: 1) get a DC for the control's
* window and start blasting pixels (TxGetDC and TxReleaseDC), 2)
* invalidate the control's window (TxInvalidate), or 3) scroll
* the control's window (TxScrollWindowEx).
*
* Text services can choose to call TxViewChange after it has
* performed any operations to update the active view and pass a
* true along with the call. By passing true, the text host
* calls UpdateWindow to make sure any unpainted areas of the
* active control are repainted.
*/
void CTxtWinHost::TxViewChange(
BOOL fUpdate ) //@parm TRUE = call update window
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEEXTERN, "CTxtWinHost::TxViewChange");
Assert(_hwnd);
// Don't bother with paint since we aren't visible
if (_fVisible)
{
// For updates requests that are FALSE, we will let the next WM_PAINT
// message pick up the draw.
if (fUpdate)
{
if (IsTransparentMode())
{
HWND hParent = GetParent (_hwnd);
Assert(hParent);
// For transparent mode, we need to update the parent first
// before we can update ourself. Otherwise, what we painted will
// be erased by the parent's background later.
::UpdateWindow (hParent);
}
::UpdateWindow (_hwnd);
}
}
}
/*
* CTxtWinHost::TxCreateCaret (hbmp, xWidth, yHeight)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -