textctrl.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,166 行 · 第 1/5 页
CPP
2,166 行
{
if ( wxTextCtrlBase::LoadFile(file) )
{
// update the size limit if needed
AdjustSpaceLimit();
return true;
}
return false;
}
// ----------------------------------------------------------------------------
// Editing
// ----------------------------------------------------------------------------
void wxTextCtrl::Replace(long from, long to, const wxString& value)
{
// Set selection and remove it
DoSetSelection(from, to, false /* don't scroll caret into view */);
DoWriteText(value, true /* selection only */);
}
void wxTextCtrl::Remove(long from, long to)
{
Replace(from, to, wxEmptyString);
}
bool wxTextCtrl::IsModified() const
{
return ::SendMessage(GetHwnd(), EM_GETMODIFY, 0, 0) != 0;
}
void wxTextCtrl::MarkDirty()
{
::SendMessage(GetHwnd(), EM_SETMODIFY, TRUE, 0L);
}
void wxTextCtrl::DiscardEdits()
{
::SendMessage(GetHwnd(), EM_SETMODIFY, FALSE, 0L);
}
int wxTextCtrl::GetNumberOfLines() const
{
return (int)::SendMessage(GetHwnd(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0);
}
// ----------------------------------------------------------------------------
// Positions <-> coords
// ----------------------------------------------------------------------------
long wxTextCtrl::XYToPosition(long x, long y) const
{
// This gets the char index for the _beginning_ of this line
long charIndex = ::SendMessage(GetHwnd(), EM_LINEINDEX, (WPARAM)y, (LPARAM)0);
return charIndex + x;
}
bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
{
HWND hWnd = GetHwnd();
// This gets the line number containing the character
long lineNo;
#if wxUSE_RICHEDIT
if ( IsRich() )
{
lineNo = ::SendMessage(hWnd, EM_EXLINEFROMCHAR, 0, (LPARAM)pos);
}
else
#endif // wxUSE_RICHEDIT
{
lineNo = ::SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, 0);
}
if ( lineNo == -1 )
{
// no such line
return false;
}
// This gets the char index for the _beginning_ of this line
long charIndex = ::SendMessage(hWnd, EM_LINEINDEX, (WPARAM)lineNo, (LPARAM)0);
if ( charIndex == -1 )
{
return false;
}
// The X position must therefore be the different between pos and charIndex
if ( x )
*x = pos - charIndex;
if ( y )
*y = lineNo;
return true;
}
wxTextCtrlHitTestResult
wxTextCtrl::HitTest(const wxPoint& pt, long *posOut) const
{
// first get the position from Windows
LPARAM lParam;
#if wxUSE_RICHEDIT
POINTL ptl;
if ( IsRich() )
{
// for rich edit controls the position is passed iva the struct fields
ptl.x = pt.x;
ptl.y = pt.y;
lParam = (LPARAM)&ptl;
}
else
#endif // wxUSE_RICHEDIT
{
// for the plain ones, we are limited to 16 bit positions which are
// combined in a single 32 bit value
lParam = MAKELPARAM(pt.x, pt.y);
}
LRESULT pos = ::SendMessage(GetHwnd(), EM_CHARFROMPOS, 0, lParam);
if ( pos == -1 )
{
// this seems to indicate an error...
return wxTE_HT_UNKNOWN;
}
#if wxUSE_RICHEDIT
if ( !IsRich() )
#endif // wxUSE_RICHEDIT
{
// for plain EDIT controls the higher word contains something else
pos = LOWORD(pos);
}
// next determine where it is relatively to our point: EM_CHARFROMPOS
// always returns the closest character but we need to be more precise, so
// double check that we really are where it pretends
POINTL ptReal;
#if wxUSE_RICHEDIT
// FIXME: we need to distinguish between richedit 2 and 3 here somehow but
// we don't know how to do it
if ( IsRich() )
{
::SendMessage(GetHwnd(), EM_POSFROMCHAR, (WPARAM)&ptReal, pos);
}
else
#endif // wxUSE_RICHEDIT
{
LRESULT lRc = ::SendMessage(GetHwnd(), EM_POSFROMCHAR, pos, 0);
if ( lRc == -1 )
{
// this is apparently returned when pos corresponds to the last
// position
ptReal.x =
ptReal.y = 0;
}
else
{
ptReal.x = LOWORD(lRc);
ptReal.y = HIWORD(lRc);
}
}
wxTextCtrlHitTestResult rc;
if ( pt.y > ptReal.y + GetCharHeight() )
rc = wxTE_HT_BELOW;
else if ( pt.x > ptReal.x + GetCharWidth() )
rc = wxTE_HT_BEYOND;
else
rc = wxTE_HT_ON_TEXT;
if ( posOut )
*posOut = pos;
return rc;
}
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
void wxTextCtrl::ShowPosition(long pos)
{
HWND hWnd = GetHwnd();
// To scroll to a position, we pass the number of lines and characters
// to scroll *by*. This means that we need to:
// (1) Find the line position of the current line.
// (2) Find the line position of pos.
// (3) Scroll by (pos - current).
// For now, ignore the horizontal scrolling.
// Is this where scrolling is relative to - the line containing the caret?
// Or is the first visible line??? Try first visible line.
// int currentLineLineNo1 = (int)::SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)-1, (LPARAM)0L);
int currentLineLineNo = (int)::SendMessage(hWnd, EM_GETFIRSTVISIBLELINE, (WPARAM)0, (LPARAM)0L);
int specifiedLineLineNo = (int)::SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, (LPARAM)0L);
int linesToScroll = specifiedLineLineNo - currentLineLineNo;
if (linesToScroll != 0)
(void)::SendMessage(hWnd, EM_LINESCROLL, (WPARAM)0, (LPARAM)linesToScroll);
}
long wxTextCtrl::GetLengthOfLineContainingPos(long pos) const
{
return ::SendMessage(GetHwnd(), EM_LINELENGTH, (WPARAM)pos, 0);
}
int wxTextCtrl::GetLineLength(long lineNo) const
{
long pos = XYToPosition(0, lineNo);
return GetLengthOfLineContainingPos(pos);
}
wxString wxTextCtrl::GetLineText(long lineNo) const
{
size_t len = (size_t)GetLineLength(lineNo) + 1;
// there must be at least enough place for the length WORD in the
// buffer
len += sizeof(WORD);
wxString str;
{
wxStringBufferLength tmp(str, len);
wxChar *buf = tmp;
*(WORD *)buf = (WORD)len;
len = (size_t)::SendMessage(GetHwnd(), EM_GETLINE, lineNo, (LPARAM)buf);
#if wxUSE_RICHEDIT
if ( IsRich() )
{
// remove the '\r' returned by the rich edit control, the user code
// should never see it
if ( buf[len - 2] == _T('\r') && buf[len - 1] == _T('\n') )
{
buf[len - 2] = _T('\n');
len--;
}
}
#endif // wxUSE_RICHEDIT
// remove the '\n' at the end, if any (this is how this function is
// supposed to work according to the docs)
if ( buf[len - 1] == _T('\n') )
{
len--;
}
buf[len] = 0;
tmp.SetLength(len);
}
return str;
}
void wxTextCtrl::SetMaxLength(unsigned long len)
{
#if wxUSE_RICHEDIT
if ( IsRich() )
{
::SendMessage(GetHwnd(), EM_EXLIMITTEXT, 0, len ? len : 0x7fffffff);
}
else
#endif // wxUSE_RICHEDIT
{
if ( len >= 0xffff )
{
// this will set it to a platform-dependent maximum (much more
// than 64Kb under NT)
len = 0;
}
::SendMessage(GetHwnd(), EM_LIMITTEXT, len, 0);
}
}
// ----------------------------------------------------------------------------
// Undo/redo
// ----------------------------------------------------------------------------
void wxTextCtrl::Undo()
{
if (CanUndo())
{
::SendMessage(GetHwnd(), EM_UNDO, 0, 0);
}
}
void wxTextCtrl::Redo()
{
if (CanRedo())
{
#if wxUSE_RICHEDIT
if (GetRichVersion() > 1)
::SendMessage(GetHwnd(), EM_REDO, 0, 0);
else
#endif
// Same as Undo, since Undo undoes the undo, i.e. a redo.
::SendMessage(GetHwnd(), EM_UNDO, 0, 0);
}
}
bool wxTextCtrl::CanUndo() const
{
return ::SendMessage(GetHwnd(), EM_CANUNDO, 0, 0) != 0;
}
bool wxTextCtrl::CanRedo() const
{
#if wxUSE_RICHEDIT
if (GetRichVersion() > 1)
return ::SendMessage(GetHwnd(), EM_CANREDO, 0, 0) != 0;
else
#endif
return ::SendMessage(GetHwnd(), EM_CANUNDO, 0, 0) != 0;
}
// ----------------------------------------------------------------------------
// caret handling (Windows only)
// ----------------------------------------------------------------------------
bool wxTextCtrl::ShowNativeCaret(bool show)
{
if ( show != m_isNativeCaretShown )
{
if ( !(show ? ::ShowCaret(GetHwnd()) : ::HideCaret(GetHwnd())) )
{
// not an error, may simply indicate that it's not shown/hidden
// yet (i.e. it had been hidden/showh 2 times before)
return false;
}
m_isNativeCaretShown = show;
}
return true;
}
// ----------------------------------------------------------------------------
// implemenation details
// ----------------------------------------------------------------------------
void wxTextCtrl::Command(wxCommandEvent & event)
{
SetValue(event.GetString());
ProcessCommand (event);
}
void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
{
// By default, load the first file into the text window.
if (event.GetNumberOfFiles() > 0)
{
LoadFile(event.GetFiles()[0]);
}
}
// ----------------------------------------------------------------------------
// kbd input processing
// ----------------------------------------------------------------------------
bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg)
{
MSG *msg = (MSG *)pMsg;
// check for our special keys here: if we don't do it and the parent frame
// uses them as accelerators, they wouldn't work at all, so we disable
// usual preprocessing for them
if ( msg->message == WM_KEYDOWN )
{
WORD vkey = (WORD) msg->wParam;
if ( (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN )
{
if ( vkey == VK_BACK )
return false;
}
else // no Alt
{
// we want to process some Ctrl-foo and Shift-bar but no key
// combinations without either Ctrl or Shift nor with both of them
// pressed
const int ctrl = wxIsCtrlDown(),
shift = wxIsShiftDown();
switch ( ctrl + shift )
{
default:
wxFAIL_MSG( _T("how many modifiers have we got?") );
// fall through
case 0:
case 2:
break;
case 1:
// either Ctrl or Shift pressed
if ( ctrl )
{
switch ( vkey )
{
case 'C':
case 'V':
case 'X':
case VK_INSERT:
case VK_DELETE:
case VK_HOME:
case VK_END:
return false;
}
}
else // Shift is pressed
{
if ( vkey == VK_INSERT || vkey == VK_DELETE )
return false;
}
}
}
}
return wxControl::MSWShouldPreProcessMessage(pMsg);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?