📄 host.cpp
字号:
PostMessage(_hwndParent, WM_CLOSE, 0, 0);
return 0;
case VK_RETURN:
if(!(GetKeyState(VK_CONTROL) & 0x8000) && !(_dwStyle & ES_WANTRETURN))
{
// Send to default button
HWND hwndT;
LRESULT id = SendMessage(_hwndParent, DM_GETDEFID, 0, 0);
if(LOWORD(id) &&
(hwndT = GetDlgItem(_hwndParent, LOWORD(id))))
{
SendMessage(_hwndParent, WM_NEXTDLGCTL, (WPARAM) hwndT, (LPARAM) 1);
if(GetFocus() != _hwnd)
PostMessage(hwndT, WM_KEYDOWN, (WPARAM) VK_RETURN, 0);
}
return 0;
}
break;
case VK_TAB:
if( !(GetKeyState(VK_CONTROL) & 0x8000) )
{
SendMessage(_hwndParent, WM_NEXTDLGCTL,
!!(GetKeyState(VK_SHIFT) & 0x8000), 0);
return 0;
}
break;
}
return 1;
}
/*
* CTxtWinHost::OnChar (vkey, dwFlags)
*
* @mfunc
* Eat some WM_CHAR messages for a control in a dialog box
*
* #rdesc
* LRESULT = (code processed) ? 0 : 1
*/
LRESULT CTxtWinHost::OnChar(
WORD vkey, //@parm WM_CHAR wparam (translated key code)
DWORD dwFlags) //@parm WM_CHAR flags
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnChar");
if(!_fInDialogBox || (GetKeyState(VK_CONTROL) & 0x8000))
return 1;
switch(vkey)
{
case 'J' - 0x40: // Ctrl-Return generates Ctrl-J (LF):
case VK_RETURN: // treat it as an ordinary return
if(!(_dwStyle & ES_WANTRETURN))
return 0; // Signal char processed (eaten)
break;
case VK_TAB:
return 0;
}
return 1; // Signal char not processed
}
///////////////////////////////// View rectangle //////////////////////////////////////
void CTxtWinHost::OnGetRect(
LPRECT prc)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnGetRect");
RECT rcInset;
LONG lSelBarWidth = 0;
if (_fEmSetRectCalled)
{
// Get the selection bar width and add it back to the view inset so
// we return the rectangle that the application set.
TxGetSelectionBarWidth(&lSelBarWidth);
}
// Get view inset (in HIMETRIC)
TxGetViewInset(&rcInset);
// Get client rect in pixels
TxGetClientRect(prc);
// Modify the client rect by the inset converted to pixels
prc->left += W32->HimetricXtoDX(rcInset.left + lSelBarWidth, sysparam.GetXPerInchScreenDC());
prc->top += W32->HimetricYtoDY(rcInset.top, sysparam.GetYPerInchScreenDC());
prc->right -= W32->HimetricXtoDX(rcInset.right, sysparam.GetXPerInchScreenDC());
prc->bottom -= W32->HimetricYtoDY(rcInset.bottom, sysparam.GetYPerInchScreenDC());
}
void CTxtWinHost::OnSetRect(
LPRECT prc,
BOOL fNewBehavior)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSetRect");
RECT rcClient;
LONG lSelBarWidth;
// Assuming this is not set to the default, turn on special EM_SETRECT
// processing. The important part of this is that we subtract the selection
// bar from the view inset because the EM_SETRECT rectangle does not
// include the selection bar.
_fEmSetRectCalled = TRUE;
if(!prc)
{
// We are back to the default so turn off special EM_SETRECT procesing.
_fEmSetRectCalled = FALSE;
SetDefaultInset();
}
else
{
// For screen display, the following intersects new view RECT
// with adjusted client area RECT
TxGetClientRect(&rcClient);
// Adjust client rect
// Factors in space for borders
if(_fBorder)
{
rcClient.top += _yInset;
rcClient.bottom -= _yInset - 1;
rcClient.left += _xInset;
rcClient.right -= _xInset;
}
if (!fNewBehavior)
{
// Intersect the new view rectangle with the
// adjusted client area rectangle
if(!IntersectRect(&_rcViewInset, &rcClient, prc))
_rcViewInset = rcClient;
}
else
{
_rcViewInset = *prc;
}
// Get the selection bar width
TxGetSelectionBarWidth(&lSelBarWidth);
// compute inset in pixels and convert to HIMETRIC.
_rcViewInset.left = W32->DXtoHimetricX(_rcViewInset.left - rcClient.left, sysparam.GetXPerInchScreenDC())
- lSelBarWidth;
_rcViewInset.top = W32->DYtoHimetricY(_rcViewInset.top - rcClient.top, sysparam.GetYPerInchScreenDC());
_rcViewInset.right = W32->DXtoHimetricX(rcClient.right
- _rcViewInset.right, sysparam.GetXPerInchScreenDC());
_rcViewInset.bottom = W32->DYtoHimetricY(rcClient.bottom
- _rcViewInset.bottom, sysparam.GetYPerInchScreenDC());
}
_pserv->OnTxPropertyBitsChange(TXTBIT_VIEWINSETCHANGE,
TXTBIT_VIEWINSETCHANGE);
}
/////////////////////////////// System notifications //////////////////////////////////
void CTxtWinHost::OnSysColorChange()
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSysColorChange");
sysparam.SetCrAuto(GetSysColor(COLOR_WINDOWTEXT));
if(!_fNotSysBkgnd)
_crBackground = GetSysColor(COLOR_WINDOW);
TxInvalidateRect(NULL, TRUE);
}
/*
* CTxtWinHost::OnGetDlgCode (wparam, lparam)
*
* @mfunc
* Handle some WM_GETDLGCODE messages
*
* #rdesc
* LRESULT = dialog code
*/
LRESULT CTxtWinHost::OnGetDlgCode(
WPARAM wparam,
LPARAM lparam)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnGetDlgCode");
LRESULT lres = DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_WANTTAB;
if(_dwStyle & ES_MULTILINE)
lres |= DLGC_WANTALLKEYS;
if(!(_dwStyle & ES_SAVESEL))
lres |= DLGC_HASSETSEL;
// HACK: If we get one of these messages then we turn on the special
// EM_SETSEL behavior. The problem is that _fInDialogBox gets turned
// on after the EM_SETSEL has occurred.
_fUseSpecialSetSel = TRUE;
/*
** -------------------------------------------- JEFFBOG HACK ----
** Only set Dialog Box Flag if GETDLGCODE message is generated by
** IsDialogMessage -- if so, the lParam will be a pointer to the
** message structure passed to IsDialogMessage; otherwise, lParam
** will be NULL. Reason for the HACK alert: the wParam & lParam
** for GETDLGCODE is still not clearly defined and may end up
** changing in a way that would throw this off
** -------------------------------------------- JEFFBOG HACK ----
*/
if(lparam)
_fInDialogBox = TRUE;
/*
** If this is a WM_SYSCHAR message generated by the UNDO keystroke
** we want this message so we can EAT IT in remain.c, case WM_SYSCHAR:
*/
if(lparam &&
(((LPMSG) lparam)->message == WM_SYSCHAR) &&
((DWORD) ((LPMSG) lparam)->lParam & SYS_ALTERNATE) &&
((WORD) wparam == VK_BACK))
{
lres |= DLGC_WANTMESSAGE;
}
return lres;
}
///////////////////////////////// Other messages //////////////////////////////////////
LRESULT CTxtWinHost::OnGetOptions() const
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnGetOptions");
LRESULT lres = (_dwStyle & ECO_STYLES);
if(_fEnableAutoWordSel)
lres |= ECO_AUTOWORDSELECTION;
return lres;
}
void CTxtWinHost::OnSetOptions(
WORD wOp,
DWORD eco)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSetOptions");
DWORD dwChangeMask = 0;
DWORD dwProp = 0;
DWORD dwStyle;
DWORD dwStyleNew = _dwStyle;
const BOOL fAutoWordSel = !!(eco & ECO_AUTOWORDSELECTION);
// We keep track of the bits changed and then if any have changed we
// query for all of our property bits and then send them. This simplifies
// the code because we don't have to set all the bits specially. If the
// code is changed to make the properties more in line with the new
// model, we want to look at this code again.
// Single line controls can't have a selection bar or do vertical writing
if(!(_dwStyle & ES_MULTILINE))
{
eco &= ~ECO_SELECTIONBAR;
}
Assert((DWORD)fAutoWordSel <= 1); // Make sure that BOOL is 1/0
dwStyle = (eco & ECO_STYLES);
switch(wOp)
{
case ECOOP_SET:
dwStyleNew = (dwStyleNew & ~ECO_STYLES) | dwStyle;
_fEnableAutoWordSel = fAutoWordSel;
break;
case ECOOP_OR:
dwStyleNew |= dwStyle; // Setting a :1 flag = TRUE
if(fAutoWordSel) // or FALSE is 1 instruction
_fEnableAutoWordSel = TRUE; // Setting it to a BOOL
break; // averages 9 instructions!
case ECOOP_AND:
dwStyleNew &= (dwStyle | ~ECO_STYLES);
if(!fAutoWordSel)
_fEnableAutoWordSel = FALSE;
break;
case ECOOP_XOR:
dwStyleNew ^= dwStyle;
if(fAutoWordSel)
_fEnableAutoWordSel ^= 1;
break;
}
if(_fEnableAutoWordSel != (unsigned)fAutoWordSel)
{
dwChangeMask |= TXTBIT_AUTOWORDSEL;
}
if(dwStyleNew != _dwStyle)
{
DWORD dwChange = dwStyleNew ^ _dwStyle;
AssertSz(!(dwChange & ~ECO_STYLES), "non-eco style changed");
_dwStyle = dwStyleNew;
SetWindowLong(_hwnd, GWL_STYLE, dwStyleNew);
if(dwChange & ES_NOHIDESEL)
{
dwChangeMask |= TXTBIT_HIDESELECTION;
}
// these two local variables to use to keep track of
// previous setting of ES_READONLY
BOOL bNeedToSetIME = FALSE;
BOOL bReadOnly = (_dwStyle & ES_READONLY);
if(dwChange & ES_READONLY)
{
dwChangeMask |= TXTBIT_READONLY;
// Change drop target state as appropriate.
if (dwStyleNew & ES_READONLY)
{
RevokeDragDrop();
}
else
{
RegisterDragDrop();
}
// setup bReadOnly so we will enable/disable IME
// input mode according to the new ES_READONLY style
bNeedToSetIME = TRUE;
bReadOnly = (dwStyleNew & ES_READONLY);
}
if(dwChange & ES_VERTICAL)
{
dwChangeMask |= TXTBIT_VERTICAL;
}
if (dwChange & ES_NOIME)
{
_usIMEMode = (dwStyleNew & ES_NOIME) ? ES_NOIME : 0;
bNeedToSetIME = TRUE;
}
else if (dwChange & ES_SELFIME)
{
_usIMEMode = (dwStyleNew & ES_SELFIME) ? ES_SELFIME : 0;
}
// we want to turn off IME if the new style is ES_READONLY or
// ES_NOIME
if (bNeedToSetIME)
ImmAssociateNULLContext (bReadOnly || (_usIMEMode == ES_NOIME));
// no action require for ES_WANTRETURN
// no action require for ES_SAVESEL
// do this last
if(dwChange & ES_SELECTIONBAR)
{
dwChangeMask |= TXTBIT_SELBARCHANGE;
}
}
if (dwChangeMask)
{
TxGetPropertyBits(dwChangeMask, &dwProp);
_pserv->OnTxPropertyBitsChange(dwChangeMask, dwProp);
}
}
void CTxtWinHost::OnSetReadOnly(
BOOL fReadOnly)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnSetReadOnly");
DWORD dwT = GetWindowLong(_hwnd, GWL_STYLE);
DWORD dwUpdatedBits = 0;
if(fReadOnly)
{
dwT |= ES_READONLY;
_dwStyle |= ES_READONLY;
// Turn off Drag Drop
RevokeDragDrop();
dwUpdatedBits |= TXTBIT_READONLY;
}
else
{
dwT &= ~(DWORD) ES_READONLY;
_dwStyle &= ~(DWORD) ES_READONLY;
// Turn drag drop back on
RegisterDragDrop();
}
_pserv->OnTxPropertyBitsChange(TXTBIT_READONLY, dwUpdatedBits);
SetWindowLong(_hwnd, GWL_STYLE, dwT);
}
//////////////////////////////////// Helpers /////////////////////////////////////////
void CTxtWinHost::SetDefaultInset()
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::SetDefaultInset");
// Generate default view rect from client rect
if(_fBorder)
{
// Factors in space for borders
_rcViewInset.top = W32->DYtoHimetricY(_yInset, sysparam.GetYPerInchScreenDC());
_rcViewInset.bottom = W32->DYtoHimetricY(_yInset - 1, sysparam.GetYPerInchScreenDC());
_rcViewInset.left = W32->DXtoHimetricX(_xInset, sysparam.GetXPerInchScreenDC());
_rcViewInset.right = W32->DXtoHimetricX(_xInset, sysparam.GetXPerInchScreenDC());
}
else
{
// Default the top and bottom inset to 0 and the left and right
// to the size of the border.
_rcViewInset.top = 0;
_rcViewInset.bottom = 0;
_rcViewInset.left = W32->DXtoHimetricX(sysparam.GetCxBorder(), sysparam.GetXPerInchScreenDC());
_rcViewInset.right = W32->DXtoHimetricX(sysparam.GetCxBorder(), sysparam.GetXPerInchScreenDC());
}
}
///////////////////////////////// Far East Support //////////////////////////////////////
//#ifdef WIN95_IME
HIMC CTxtWinHost::TxImmGetContext()
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxImmGetContext");
HIMC himc;
Assert( _hwnd );
himc = pImmGetContext( _hwnd );
return himc;
}
void CTxtWinHost::TxImmReleaseContext(
HIMC himc)
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::TxImmReleaseContext");
Assert( _hwnd );
pImmReleaseContext( _hwnd, himc );
}
//#endif
void CTxtWinHost::RevokeDragDrop()
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::RevokeDragDrop");
if (_fRegisteredForDrop)
{
// Note that if the revoke fails we want to know about this in debug
// builds so we can fix any problems. In retail, we can't really do
// so we just ignore it.
#ifdef DEBUG
HRESULT hr =
#endif // DEBUG
pRevokeDragDrop(_hwnd);
#ifdef DEBUG
TESTANDTRACEHR(hr);
#endif // DEBUG
_fRegisteredForDrop = FALSE;
}
}
void CTxtWinHost::RegisterDragDrop()
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::RegisterDragDrop");
IDropTarget *pdt;
if(!_fRegisteredForDrop && _pserv->TxGetDropTarget(&pdt) == NOERROR)
{
// The most likely reason for RegisterDragDrop to fail is some kind of
// bug in our program.
HRESULT hr = pRegisterDragDrop(_hwnd, pdt);
if(hr == NOERROR)
{
_fRegisteredForDrop = TRUE;
}
#ifndef PEGASUS
pdt->Release();
#endif
}
}
/*
* void IMMAssociateNULLContext ( BOOL fReadOnly )
*
* @func
* Enable/disable the IME Composition
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -