第五章 文本编程

插入符

文本插入符

创建文本插入符是利用了CreateSolidCaret函数
以下为例

//创建设备描述表
CClientDC dc(this);
//定义文本信息结构体变量
TEXTMETRIC tm;
//定义设备描述表中的文本信息
dc.GetTextMetrics(&tm);
//根据字体大小,创建合适的插入符
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
//显示插入符
ShowCaret();

图形插入符

int CText2View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP2);
    CreateCaret(&bitmap);
    ShowCaret();
    return 0;
}

这么写发现没反应,因为函数完成之后bitmap对象就被析构了
所以改成这样

int CText2View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码
    //CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP2);
    CreateCaret(&bitmap);
    ShowCaret()
    return 0;
}

//在类中定义
private:
    CBitmap bitmap;

窗口重绘

Windows程序运行是,只要程序窗口大小发生变化,窗口会发生重绘,窗中内容会被清除,如果想要它们保留下来,就要用到WM_PAINT消息响应函数的OnDraw函数

void CProject3View::OnDraw(CDC* pDC)
{
    CProject3Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here
    CString str("hjfhjf");
    pDC->TextOut(50,50,str);
}

添加字符串资源

在资源视图的String Table文件中可以定义字符串资源
在代码中使用LoadString函数加载字符串资源

void CText2View::OnDraw(CDC* pDC)
{
    CText2Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;
    CString str("hjfhjf");
    pDC->TextOut(50,50,str);

    str.LoadString(IDS_STRINGVC);
    pDC->TextOut(0,200,str);
    // TODO: 在此处为本机数据添加绘制代码
}

路径

在设备描述表中有一个路径层的概念,路径层概念就是划分区域,别人不能侵犯
在MFC中,创建路径层是利用CDC类提供的BeginPath和EndPath这两个函数实现的,首先调用前者,BeginPath函数的作用是在设备描述层中打开一个路径层,然后利用图形设备接口(GDI)提供的绘图函数进行绘图操作,最后调用EndPath函数关闭这个路径层

void CText2View::OnDraw(CDC* pDC)
{
    //函数自带
    CText2Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    CString str;
    str = "hjf";
    pDC->TextOut(50,50,str);

    CSize sz = pDC->GetTextExtent(str);
    pDC->BeginPath();
    pDC->Rectangle(50,50,50+sz.cx,50+sz.cy);
    pDC->EndPath();
    //pDC->SelectClipPath(RGN_AND);

    //利用循环打印网格
    for (int i = 0;i<300;i+=10)
    {
        pDC->MoveTo(0,i);
        pDC->LineTo(300,i);
        pDC->MoveTo(i,0);
        pDC->LineTo(i,300);
    }
    // TODO: 在此处为本机数据添加绘制代码
}

字符输入

字符的输入功能,即是当我们按下一个字符键,该字符就会输出到窗口,首先我们要解决的是插入符位置的问题,当程序运行时,我们希望插入符能跟着我们的鼠标走,这时,通过OnLButtonDown响应函数,利用CWnd类的SetCaretPos()来实现
我们定义一个CString类型的成员变量m_strLine

void CText2View::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    SetCaretPos(point);

    CView::OnLButtonDown(nFlags, point);
}

第二个要注意的是用来储存字符串变量的成员变量m_strLine的取值变化问题
当鼠标左键单击窗口另一个地方的时候,插入符就会移动到新的位置,那么新的字符就要从新的地方输入,以前的要被清空。这里利用CString类的成员函数Empty来实现

void CText2View::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    SetCaretPos(point);
    m_strLine.Empty();

    CView::OnLButtonDown(nFlags, point);
}

第三个问题是每次输入的字符串都应当在当前插入符位置,即鼠标左键点击处显示,为此我们再次新增一个CPoint类型的成员变量m_ptOrigin来保存这个坐标

void CText2View::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    SetCaretPos(point);
    m_strLine.Empty();
    m_ptOrigin= point;

    CView::OnLButtonDown(nFlags, point);
}

最后还得考虑到回车字符,以及退格键的问题,这个我们在实际使用中比较频繁
hui

TEXTMETRIC,GetTextMetrics和之前一样,获得当前设备描述表中字体的高度信息,回车操作即是改变鼠标插入符位置,将纵坐标加上高度即可;

而退格键实际上是先将文本的颜色设置为背景色,输出它;然后在m_strLine中删除,然后将文本的颜色改回来,最后输出它;

void CText2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    if (0x0d==nChar)
    {
        m_strLine.Empty();
        m_ptOrigin.y+=tm.tmHeight;

    }else if (0x08==nChar)
    {
        COLORREF clr = dc.SetTextColor(dc.GetBkColor());
        dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
        m_strLine = m_strLine.Left(m_strLine.GetLength()-1);
        dc.SetTextColor(clr);
    }
    else{
        m_strLine+=(char)nChar;
    }

    dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

    CView::OnChar(nChar, nRepCnt, nFlags);
}

但是还是不行,输出字符后插入符没变,这时候使用GetTextExtent函数

void CText2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    if (0x0d==nChar)
    {
        m_strLine.Empty();
        m_ptOrigin.y+=tm.tmHeight;

    }else if (0x08==nChar)
    {
        COLORREF clr = dc.SetTextColor(dc.GetBkColor());
        dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
        m_strLine = m_strLine.Left(m_strLine.GetLength()-1);
        dc.SetTextColor(clr);
    }
    else{
        m_strLine+=(char)nChar;
    }

    // 新增的
    CSize sz =dc.GetTextExtent(m_strLine);
    CPoint pt;
    pt.x  =  m_ptOrigin.x+sz.cx;
    pt.y = m_ptOrigin.y;
    SetCaretPos(pt);
    dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

    CView::OnChar(nChar, nRepCnt, nFlags);
}

设置字体

MFC提供一个CFont类专门用来设置字体,该类派生于CGdiObject类,封装了一个Windows图形设备接口(GDI)的字体

void CText2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CClientDC dc(this);
    //定义使用什么字体
    CFont font;
    font.CreatePointFont(300,"华文行楷",NULL);
    CFont *pOldFont = dc.SelectObject(&font);




    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    if (0x0d==nChar)
    {
        m_strLine.Empty();
        m_ptOrigin.y+=tm.tmHeight;

    }else if (0x08==nChar)
    {
        COLORREF clr = dc.SetTextColor(dc.GetBkColor());
        dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
        m_strLine = m_strLine.Left(m_strLine.GetLength()-1);
        dc.SetTextColor(clr);
    }
    else{
        m_strLine+=(char)nChar;
    }

    CSize sz =dc.GetTextExtent(m_strLine);
    CPoint pt;
    pt.x  =  m_ptOrigin.x+sz.cx;
    pt.y = m_ptOrigin.y;
    SetCaretPos(pt);



    dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

    dc.SelectObject(pOldFont);

    CView::OnChar(nChar, nRepCnt, nFlags);
}

字幕变色功能的实现、

在一些歌曲播放的时候,我们会发现字母的颜色是一点一点的改变的;

这样,我们会使用到CDC类的另外一个函数,DrawText,它是用来在一定的区域内输出文字;

int DrawText( const CString&str, LPRECT lpRect, UINT nFormat );

其中str指的是需要输出的字符串,lpRect是指定文字显示范围的矩形,nFormat是文本的输出格式;

这样,我们通过定时器即可一点一点的将文字显示出来;

UINT SetTimer( UINTnIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer)(HWND, UINT, UINT, DWORD) );

所以,在OnCreate函数中设置定时器;

另外,因为通过定时器会一直改变矩形的宽度,所以创建一个int型的m_nWidth数据用来记录矩形宽度;

void CText2View::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    m_nWidth+=5;

    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    CRect rect;
    rect.left = 0;
    rect.top = 200;
    rect.right = m_nWidth;
    rect.bottom = rect.top + tm.tmHeight;


    dc.SetTextColor(RGB(255,0,0));
    CString str;
    str.LoadString(IDS_STRINGVC);
    dc.DrawText(str,rect,DT_LEFT);

    rect.top = 150;
    rect.bottom = rect.top + tm.tmHeight;
    dc.DrawText(str,rect,DT_RIGHT);

    CSize sz = dc.GetTextExtent(str);
    if (m_nWidth > sz.cx)
    {
        m_nWidth = 0;
        dc.SetTextColor(RGB(255,0,0));
        dc.TextOut(0,200,str);
    }

    CView::OnTimer(nIDEvent);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值