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

📄 caret.cpp

📁 《Visual C++ Bible》或者说是《Visual C++ 宝典》的对应的源码文件
💻 CPP
字号:
// caret.cpp : Caret handling helper functions.
//

#include "stdafx.h"
#include "gettext.h"

#include "mainfrm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

//-----------------------------------------------------------------------------
// [GETTEXT] MoveCaret moves the caret to a particular line and character.
void DMainFrame::MoveCaret(int iLine, int iChar)
{
    // Ignore if we don't have any lines of text
    if (d_cLines == 0)
        return;

    // Check that line and character indices are in range.
    ASSERT (iLine >= 0 && iLine <= d_cLines);
    ASSERT (iChar >= 0 && iChar <= (d_saTextInfo[iLine].ccLen));

    // Get pointer to text string and count of characters.
    LPTSTR lp = d_saTextInfo[iLine].pText;
    int    cc = d_saTextInfo[iLine].ccLen;

    // Figuring which line is simple math.
    CPoint ptCaret;
    ptCaret.y = (iLine - d_iTopLine) * d_cyLineHeight;

    // Figuring which character requires a loop and some simple math.
    ptCaret.x = d_cxLeftMargin;
    for (int ich = 0; ich < iChar; ich++)
    {
        // If a tab character...
        if (lp[ich] == '\t')
        {
            // Tabs enabled...
            if (d_bTabs)
            {
                ptCaret.x += d_cxTabStop;
            }
            else // ... Tabs disabled.
            {
                ptCaret.x += d_cxAveCharWidth;
            }
        }
        else // ...not a tab character.
        {
            ptCaret.x += d_piCharWidth[lp[ich] - d_bchFirstChar];
        }
    }

    SetCaretPos(ptCaret);
    d_ptCaret = ptCaret;
}

//-----------------------------------------------------------------------------
// [GETTEXT] MoveCaretChar moves caret by a relative amount.
void DMainFrame::MoveCaretChar(int nCharCount)
{
    // We're not equipped to handle moves greater than ABS(1).
    ASSERT ((nCharCount == -1) || (nCharCount == 1));

    // Handle empty buffer situation.
    if (d_cLines == 0)
        return;

    // Query caret indices: (line offset, character offset)
    int iLine = QueryClickLine(d_ptCaret);
    int iChar = QueryClickChar(iLine, d_ptCaret);

    // Query length of current line.
    int ccLine = d_saTextInfo[iLine].ccLen;

    // [LeftArrow] at start of line.
    if ((nCharCount <= 0) && (iChar == 0))
    {
        // Cannot move before first line.
        if (iLine == 0)
        {
            ::MessageBeep(0);
            return;
        }

        iLine -= 1;
        iChar = d_saTextInfo[iLine].ccLen;

        // Scroll if we need to.
        if (iLine < d_iTopLine)
            OnVScroll(SB_LINEUP, 0, 0);
    }

    // [RightArrow] at end of line.
    else if ((nCharCount >= 0) && (iChar == ccLine))
    {
        // Cannot move beyond last line
        if (iLine == (d_cLines-1))
        {
            ::MessageBeep(0);
            return;
        }

        iLine += 1;
        iChar = 0;

        // Scroll if we need to.
        int yCaretBottom = d_ptCaret.y + (d_cyLineHeight * 2);
        CRect rClient;
        GetClientRect(&rClient);
        if (rClient.bottom < yCaretBottom)
            OnVScroll(SB_LINEDOWN, 0, 0);
    }

    // Adjust caret character index.
    else
    {
        iChar += nCharCount;
    }

    MoveCaret(iLine, iChar);
}

//-----------------------------------------------------------------------------
// [GETTEXT] MoveCaretClick simulates a mouse click to move the caret.
void DMainFrame::MoveCaretClick(CPoint ptHit)
{
    CRect rClient;
    GetClientRect(&rClient);

    // Scroll UP if top of caret is above top of client area.
    if (ptHit.y < 0)
    {
        // Prevent scrolling above top line.
        if (d_iTopLine <= 0)
        {
            ::MessageBeep(0);
            return;
        }

        // Scroll requested line into view.
        OnVScroll(SB_LINEUP, 0, 0);

        // Adjust hit point to take scrolling into account.
        ptHit.y += d_cyLineHeight;
    }

    // Scroll DOWN if bottom of caret is below bottom of client area.
    if ((ptHit.y + d_cyLineHeight) > rClient.bottom)
    {
        // Prevent scrolling below last line.
        if (d_iTopLine >= (d_cLines - d_clHeight))
        {
            ::MessageBeep(0);
            return;
        }

        // Scroll requested line into view.
        OnVScroll(SB_LINEDOWN, 0, 0);

        // Adjust hit point to take scrolling into account.
        ptHit.y -= d_cyLineHeight;
    }

    // Give ourselves a mouse click.
    OnLButtonDown(0, ptHit);
}

//-----------------------------------------------------------------------------
// [GETTEXT] QueryClickChar fetches index to character where caret goes.
int DMainFrame::QueryClickChar(int iLine, CPoint point)
{
    // Easy special case: left margin click means start of line.
    if (point.x <= d_cxLeftMargin || d_cLines == 0)
        return 0;

    // Get pointer to text string and count of characters.
    LPTSTR lp = d_saTextInfo[iLine].pText;
    int    cc = d_saTextInfo[iLine].ccLen;

    // Loop until a hit.
    int ich;
    int x = d_cxLeftMargin;
    int xPrev = x;
    for (ich = 0; ich <= cc; ich++)
    {
        // Check for passing the character cell.
        if (x >= point.x)
        {
            // Compare point to middle of previous character cell.
            if ((xPrev + x) / 2 >= point.x)
            {
                ich--;
            }

            // Character to right of caret location.
            return ich;
        }

        // Store previous char cell for 1/2 cell calculation.
        xPrev = x;

        // If a tab character...
        if (lp[ich] == '\t')
        {
            // Tabs enabled?
            int xTabWidth = (d_bTabs) ? d_cxTabStop : d_cxAveCharWidth;
            x += xTabWidth;
        }
        else // ...not a tab character.
        {
            // Avoid reading past end of array.
            if (ich < cc)
            {
                // Increment x-value by last character width.
                x += d_piCharWidth[lp[ich] - d_bchFirstChar];
            }
        }
    }

    // Beyond end of line means caret goes after last character.
    return cc;
}

//-----------------------------------------------------------------------------
// [GETTEXT] QueryClickLine converts client area point to line number.
int DMainFrame::QueryClickLine(CPoint point)
{
    // Figure out range of lines to check.
    int iLine = d_iTopLine;
    int cLastLine = d_iTopLine + d_clHeight + 1;
    cLastLine = min (cLastLine, d_cLines);

    // Initialize hit test rectangle to client area size.
    CRect rTextLine;
    GetClientRect(&rTextLine);
    // Can't deal outside client area.
    ASSERT(rTextLine.PtInRect(point));  
    rTextLine.bottom = d_cyLineHeight;

    // Loop through lines in window doing hit testing.
    // NOTE: Since every line is the same height,
    //       we could easily optimize this loop.
    for (int i=iLine; i < cLastLine; i++)
    {
        // Test for a hit.
        if (rTextLine.PtInRect(point))
        {
            return i;
        }

        // If no hit, increment test rectangle and try again.
        rTextLine.top    += d_cyLineHeight;
        rTextLine.bottom += d_cyLineHeight;
    }

    // User clicked below bottom line. Set pick to last line.
    return cLastLine - 1;
}

⌨️ 快捷键说明

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