📄 host.cpp
字号:
if( (_fKeyMaskSet && (msg >= WM_KEYFIRST && msg <= WM_KEYLAST)) ||
(_fMouseMaskSet && ((msg >= WM_MOUSEFIRST &&
msg <= WM_MOUSELAST) || msg == WM_MOUSEACTIVATE)) ||
(_fScrollMaskSet &&((msg == WM_HSCROLL) || (msg == WM_VSCROLL))))
{
ZeroMemory(&msgfltr, sizeof(MSGFILTER));
msgfltr.msg = msg;
msgfltr.wParam = wparam;
msgfltr.lParam = lparam;
//
// The MSDN document on MSGFILTER is wrong, if the
// send message returns 0 (NOERROR via TxNotify in this
// case), it means process the event. Otherwise, return.
//
// The documentation states the reverse.
//
if( TxNotify(EN_MSGFILTER, &msgfltr) == NOERROR)
{
// Since client is allowed to modify the contents of
// msgfltr, we must use the returned values.
msg = msgfltr.msg;
wparam = msgfltr.wParam;
lparam = msgfltr.lParam;
}
else
{
lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
goto Exit;
}
}
}
if (IsAccumulateDBCMode() && (msg != WM_GETDLGCODE
&& msg != WM_PAINT && msg != WM_ERASEBKGND && msg != WM_IME_NOTIFY
&& msg != WM_SETFONT && msg != WM_GETFONT)
&& (msg < WM_KEYFIRST || msg > WM_KEYLAST)
&& (msg < EM_GETSEL || msg > EM_CHARFROMPOS) // edit control messages
&& (msg < EM_CANPASTE || msg > EM_GETIMECOMPMODE)) // private Richedit messages
{
// turn off accumulate mode
SetAccumulateDBCMode ( FALSE );
_chLeadByte = 0;
}
switch(msg)
{
case EM_SETEVENTMASK:
_fKeyMaskSet = !!(lparam & ENM_KEYEVENTS);
_fMouseMaskSet = !!(lparam & ENM_MOUSEEVENTS);
_fScrollMaskSet = !!(lparam & ENM_SCROLLEVENTS);
goto serv;
break;
case EM_SETSEL:
// When we are in a dialog box that is empty, EM_SETSEL will not select
// the final always existing EOP if the control is rich.
if (_fUseSpecialSetSel
&& (((CTxtEdit *)_pserv)->GetAdjustedTextLength() == 0)
&& (wparam != (WPARAM) -1))
{
lparam = 0;
if (wparam != 0)
{
wparam = 0;
}
}
goto serv;
case WM_CREATE:
lres = OnCreate((CREATESTRUCT*)lparam);
break;
case WM_KEYDOWN:
if ( (WORD) wparam == VK_PROCESSKEY )
{
_chLeadByte = 0;
if ((GetKeyState(VK_KANA) & 0x1))
{
SetAccumulateDBCMode ( FALSE );
}
else
{
// get ready to cumulate the DBC coming via 2 WM_CHAR messages
SetAccumulateDBCMode ( TRUE );
goto serv;
}
}
lres = OnKeyDown((WORD) wparam, (DWORD) lparam);
if(lres) // Didn't process code:
goto serv; // give it to text services
break;
case WM_CHAR:
// check if we are waiting for 2 consecutive WM_CHAR messages
if ( IsAccumulateDBCMode() )
{
if ( (GetKeyState(VK_KANA) & 0x1) )
{
// turn off accumulate mode
SetAccumulateDBCMode ( FALSE );
_chLeadByte = 0;
}
else
{
if ( !_chLeadByte )
{
// This is the first WM_CHAR message,
// accumulate it if this is a LeadByte. Otherwise, fall thru to
// regular WM_CHAR processing.
if ( IsDBCSLeadByte ( (WORD)wparam ) )
{
// save the Lead Byte and don't process this message
_chLeadByte = (WORD)wparam << 8 ;
goto Exit;
}
}
else
{
// This is the second WM_CHAR message,
// combine the current byte with previous byte.
// This DBC will be handled as WM_IME_CHAR.
wparam |= _chLeadByte;
msg = WM_IME_CHAR;
// setup to accumulate more WM_CHAR
_chLeadByte = 0;
goto serv; // give it to text services
}
}
}
lres = OnChar((WORD) wparam, (DWORD) lparam);
if(lres) // Didn't process code:
goto serv; // give it to text services
break;
case WM_ENABLE:
if ((wparam == 0) != (_fDisabled != 0))
{
// Stated of window changed so invalidate it so it will
// get redrawn.
InvalidateRect(_hwnd, NULL, TRUE);
SetScrollBarsForWmEnable(wparam);
}
// Set the disabled flag
_fDisabled = (0 == wparam);
// Return value for message
lres = 0;
case WM_SYSCOLORCHANGE:
OnSysColorChange();
goto serv; // Notify text services that
// system colors have changed
case WM_GETDLGCODE:
lres = OnGetDlgCode(wparam, lparam);
break;
case EM_GETOPTIONS:
lres = OnGetOptions();
break;
case EM_GETPASSWORDCHAR:
lres = _chPassword;
break;
case EM_GETRECT:
OnGetRect((LPRECT)lparam);
break;
case EM_HIDESELECTION:
if((BOOL)lparam)
{
DWORD dwPropertyBits = 0;
if((BOOL)wparam)
{
_dwStyle &= ~(DWORD) ES_NOHIDESEL;
dwPropertyBits = TXTBIT_HIDESELECTION;
}
else
_dwStyle |= ES_NOHIDESEL;
// Notify text services of change in status.
_pserv->OnTxPropertyBitsChange(TXTBIT_HIDESELECTION,
dwPropertyBits);
}
goto serv;
case EM_SETBKGNDCOLOR:
lres = (LRESULT) _crBackground;
_fNotSysBkgnd = !wparam;
_crBackground = (COLORREF) lparam;
if(wparam)
_crBackground = GetSysColor(COLOR_WINDOW);
if(lres != (LRESULT) _crBackground)
{
// Notify text services that color has changed
LRESULT lres1 = 0;
_pserv->TxSendMessage(WM_SYSCOLORCHANGE, 0, 0, &lres1);
TxInvalidateRect(NULL, TRUE);
}
break;
case WM_STYLECHANGING:
// Just pass this one to the default window proc
lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
break;
case WM_STYLECHANGED:
//
// For now, we only interested in GWL_EXSTYLE Transparent mode changed.
// This is to fix Bug 753 since Window95 is not passing us
// the WS_EX_TRANSPARENT.
//
lres = 1;
if (GWL_EXSTYLE == wparam)
{
LPSTYLESTRUCT lpss = (LPSTYLESTRUCT) lparam;
if ( IsTransparentMode() != (BOOL)(lpss->styleNew & WS_EX_TRANSPARENT) )
{
_dwExStyle = lpss->styleNew;
((CTxtEdit *)_pserv)->OnTxBackStyleChange(TRUE);
// return 0 to indicate we have handled this
// message
lres = 0;
}
}
break;
case EM_SHOWSCROLLBAR:
{
Assert(wparam == SB_VERT || wparam == SB_HORZ);
DWORD dwBit = wparam == SB_VERT ? WS_VSCROLL : WS_HSCROLL;
if (!lparam)
{
_dwStyle &= ~dwBit;
}
else
{
_dwStyle |= dwBit;
}
TxShowScrollBar( (int) wparam, lparam );
}
break;
case EM_SETOPTIONS:
OnSetOptions((WORD) wparam, (DWORD) lparam);
lres = (_dwStyle & ECO_STYLES);
if(_fEnableAutoWordSel)
lres |= ECO_AUTOWORDSELECTION;
break;
case EM_SETPASSWORDCHAR:
if(_chPassword != (TCHAR)wparam)
{
_chPassword = (TCHAR)wparam;
_pserv->OnTxPropertyBitsChange(TXTBIT_USEPASSWORD,
_chPassword ? TXTBIT_USEPASSWORD : 0);
}
break;
case EM_SETREADONLY:
ImmAssociateNULLContext (BOOL(wparam) || (_usIMEMode == ES_NOIME));
OnSetReadOnly(BOOL(wparam));
lres = 1;
break;
case EM_SETRECTNP: // Can implement: identical to
break; // EM_SETRECT, except that edit
// control window isn't redrawn
case EM_SETRECT:
OnSetRect((LPRECT)lparam, wparam == 1);
break;
case WM_SIZE:
_pserv->TxSendMessage(msg, wparam, lparam, &lres);
lres = OnSize(hwnd, wparam, LOWORD(lparam), HIWORD(lparam));
break;
case WM_WINDOWPOSCHANGING:
lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
if(TxGetEffects() == TXTEFFECT_SUNKEN)
OnSunkenWindowPosChanging(hwnd, (WINDOWPOS *) lparam);
break;
case WM_SETCURSOR:
// Only set cursor when over us rather than a child; this
// helps prevent us from fighting it out with an inplace child
if((HWND)wparam == hwnd)
{
if(!(lres = ::DefWindowProc(hwnd, msg, wparam, lparam)))
{
POINT pt;
GetCursorPos(&pt);
::ScreenToClient(hwnd, &pt);
_pserv->OnTxSetCursor(
DVASPECT_CONTENT,
-1,
NULL,
NULL,
NULL,
NULL,
NULL, // Client rect - no redraw
pt.x,
pt.y);
lres = TRUE;
}
}
break;
case WM_SHOWWINDOW:
hr = OnTxVisibleChange((BOOL)wparam);
break;
case WM_NCPAINT:
lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
if ((TxGetEffects() == TXTEFFECT_SUNKEN)
&& (dwMajorVersion < VERS4))
{
HDC hdc = GetDC(hwnd);
if(hdc)
{
DrawSunkenBorder(hwnd, hdc);
ReleaseDC(hwnd, hdc);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HPALETTE hpalOld = NULL;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rcClient;
#ifdef DEBUG
// We only want to paint if we are not asserting because
// the assert might be in the paint code itself.
if (!fInAssert)
{
#endif // DEBUG
// Set up the palette for drawing our data
if (_hpal != NULL)
{
hpalOld = SelectPalette(hdc, _hpal, TRUE);
RealizePalette(hdc);
}
// Since we are using the CS_PARENTDC style, make sure
// the clip region is limited to our client window.
GetClientRect(hwnd, &rcClient);
SaveDC(hdc);
IntersectClipRect(hdc, rcClient.left, rcClient.top, rcClient.right,
rcClient.bottom);
#if 0 // Useful for debugging
TCHAR rgch[512];
wsprintf(rgch, TEXT("Paint : (%d, %d, %d, %d)\n"),
rcClient.left,
rcClient.top,
rcClient.right,
rcClient.bottom);
OutputDebugString(rgch);
#endif
_pserv->TxDraw(
DVASPECT_CONTENT, // Draw Aspect
-1, // Lindex
NULL, // Info for drawing optimazation
NULL, // target device information
hdc, // Draw device HDC
NULL, // Target device HDC
(const RECTL *) &rcClient,// Bounding client rectangle
NULL, // Clipping rectangle for metafiles
&ps.rcPaint, // Update rectangle
NULL, // Call back function
NULL, // Call back parameter
TXTVIEW_ACTIVE); // What view - the active one!
// Restore the palette if there is one.
if (hpalOld != NULL)
{
#ifndef PEGASUS
SelectPalette(hdc, hpalOld, TRUE);
#endif
}
if ((TxGetEffects() == TXTEFFECT_SUNKEN)
&& (dwMajorVersion < VERS4))
DrawSunkenBorder(hwnd, hdc);
#ifdef DEBUG
// See above comment
}
#endif // DEBUG
RestoreDC(hdc, -1);
EndPaint(hwnd, &ps);
}
break;
case EM_SETMARGINS:
OnSetMargins(wparam, LOWORD(lparam), HIWORD(lparam));
break;
case EM_SETPALETTE:
// Application is setting a palette for us to use.
_hpal = (HPALETTE) wparam;
// Invalidate the window & repaint to reflect the new palette.
InvalidateRect(hwnd, NULL, FALSE);
break;
case WM_SETFOCUS:
// turn off IME mode if necessary
if (!_oldhimc && ((_dwStyle & ES_READONLY) || (_usIMEMode == ES_NOIME)))
{
ImmAssociateNULLContext (TRUE);
}
goto serv;
default:
serv:
{
if (_usIMEMode == ES_SELFIME)
{
// host is doing IME, ignore IME related messages.
switch(msg)
{
case WM_IME_STARTCOMPOSITION: // IME has begun interpreting user input
case WM_IME_COMPOSITION: // State of user's input has changed
case WM_IME_ENDCOMPOSITION: // User has OK'd IME conversions
case WM_IME_NOTIFY: // Candidate window state change info, etc.
case WM_IME_COMPOSITIONFULL: // Level 2 comp string about to overflow.
lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
goto Exit;
}
}
hr = _pserv->TxSendMessage(msg, wparam, lparam, &lres);
if (hr == S_FALSE)
{
// handle special case for WM_IME_COMPOSITION.
// Turn off Result string bit to avoid WM_IME_CHAR message.
if ( WM_IME_COMPOSITION == msg )
lparam &= ~GCS_RESULTSTR;
// Message was not processed by text services so send it
// to the default window proc.
lres = ::DefWindowProc(hwnd, msg, wparam, lparam);
}
}
}
// Special border processing. The inset changes based on the size of the
// defautl character set. So if we got a message that changes the default
// character set, we need to update the inset.
if (_fBorder && ((msg == WM_SETFONT)
|| ((msg == EM_SETCHARFORMAT) && (wparam == 0))))
{
ResizeInset();
}
Exit:
Release();
return lres;
}
/////////////////////////////// Keyboard Messages //////////////////////////////////
/*
* CTxtWinHost::OnKeyDown (vkey, dwFlags)
*
* @mfunc
* Handle WM_KEYDOWN messages that need to send a message to the parent
* window (may happen when control is in a dialog box)
*
* #rdesc
* LRESULT = (code processed) ? 0 : 1
*/
LRESULT CTxtWinHost::OnKeyDown(
WORD vkey, //@parm WM_KEYDOWN wparam (virtual key code)
DWORD dwFlags) //@parm WM_KEYDOWN flags
{
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "CTxtWinHost::OnKeyDown");
if(!_fInDialogBox) // Not in a dialog box
return 1; // Signal key-down msg not processed
switch(vkey)
{
case VK_ESCAPE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -