四. 文字程式設計--Windows程式設計課程學習筆記

weixin_34320159發表於2018-08-23

原文地址: https://blog.csdn.net/ling_xiao007/article/details/51721035

4.1 插入符

4.1.1 建立文字插入符

在視類建立響應WM_CREATE訊息的訊息函式。為根據字型資訊來調整大小,呼叫CreateSolidCaret函式,基線(base line)h以上最高的為升序高度,g最低的為降序高度,之差為字型高度(tmHeight),字型沒有一個具體寬度值,只有一個平均寬度(tmAveCharWidth),以及最大寬度(tmMaxCharWidth)。


12730381-764cd6a4afab8224.png
1.png
    CClientC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
    ShowCaret();

4.1.2 建立圖形插入符

同建立文字插入符一樣,在視類建立響應WM_CREATE訊息的訊息函式。呼叫CreateCaret()函式建立圖形插入符。因為bmp為區域性變數,當OnCreate執行完後,bmp被析構,故插入符不能夠顯示。可以將bmp宣告為視類的私有變數或者Detach分離bmp與點陣圖資源實現。

    CBitmap bmp;
    bmp.LoadBitmap(IDB_BITMAP2);
    CreateCaret(&bmp);
    bmp.Detach();
    ShowCaret();

4.2 視窗重繪

4.2.1 OnDraw函式

MFC中專門為視類提供了響應WM_PAINT訊息的響應函式OnDraw(CDC* pDC)。如果要防止視窗重繪時顯示的文字或圖形被重新整理,文字輸出和圖形繪製的操作都應該在OnDraw函式裡完成。

接下來,要實現一個文字輸出功能,可以用TextOut函式實現。MFC提供CString類,該類沒有基類。CString提供多種建構函式。

Cstring();
CString(constCstring & stringSrc);
CString(TCHARch, int nRepeat = 1);
CString(LPCTSTRlpch, int nLength);
CString (constunsigned char * psz);
CString(LPCWSTRlpsz);
CString(LPCSTRlpsz);

所以可以在視類新增以下程式碼。

    CString str("第四講 文字程式設計");
    pDC->TextOut(100, 100, str);

4.2.2 建立字串資源

CString類提供一個LoadString,可以裝載一個字串資源。在資源的String Table中新增字串資源,在視類新增以下程式碼。

    CString str2;
    str2.LoadStringA(IDS_STRING312);
    pDC->TextOutA(100, 200, str2);

4.3 路徑

裝置描述表有路徑層,MFC中建立路徑層利用了CDC類提供的BeginPath和EndPath實現,前者在裝置描述表開啟一個路徑層,然後利用圖形裝置介面(GDI)提供的繪圖功能繪圖,後者關閉。

CDC類提供一個過的字串寬度和高度的函式GetTextExtent。返回一個CSize類,該結構體有x,y兩個私有變數。(區分GetTextMetrics)。實現一個給特定字串加

    CStringstr("第四講文字程式設計");
    pDC->TextOut(100, 100, str);
 
    CSize sz = pDC->GetTextExtent(str);
 
    str.LoadStringA(IDS_STRING312);
    pDC->TextOutA(100, 200, str);
 
    pDC->BeginPath();
    pDC->Rectangle(100, 100, 100 + sz.cx, 100 + sz.cy);
    pDC->EndPath();

執行程式沒有變化,但是註釋BeginPath和EndPath,一個白色矩形覆蓋文字。新增以下程式碼繪製網格線。

    for (int i = 0; i < 300; i+=10)
    {
        pDC->MoveTo(0,i);
        pDC->LineTo(300,i);
        pDC->MoveTo(i,0);
        pDC->LineTo(i,300);
    }

接下來介紹裁剪區域。EndPath後新增以下程式碼。RGN_DIFF引數時,可以看到線條到路徑層斷開了。它使新的裁剪區域包含了當前的裁剪區域,但把當前路徑層的範圍排除在外。可以在試一下RGN_AND,只有路徑層顯示。所以,如果希望整個圖形中有區域性不同則可踹放置在一個路徑層中,利用SelectClipPath函式設定一種模式。

    pDC->SelectClipPath(RGN_DIFF);     pDC->SelectClipPath(RGN_AND);

4.4 字元輸入

設計思路是,把每次輸入的字元都儲存在一個字串中,在程式中,每當按下新的字元時,都在當前視窗插入符位置重新輸入一遍字串。

1)讓視類捕捉WM_CHAR訊息,定義一個m_strLine,並在視類建構函式初始化為空。

2)確定當前插入符位置。為此捕獲WM_LBUTTONDOWN訊息,在訊息響應函式中,把插入符位置移動到點選位置。可以利用SetCaretPos函式實現。

    SetCaretPos(point);

3)字串成員變數取值變化問題。左鍵按下,字串清空。

    m_strLine.Empty();

4)字串應該顯示在插入符位置。為此,視類新增私有變數m_lMouseP,儲存左鍵單擊時的座標,建構函式為0。

    m_lMouseP = point;

5)回車字元(0x0d)處理。回車換行,清空字串,通過GEtTExtMetrics函式計算下一行位置。

6)退格鍵(0x08)處理。用背景顏色重繪最後一個字元,字串刪除最後一個字元。CDC類提供GetBkColor函式獲得背景色。Cstring類Left函式可以刪除。

7)插入符調整。利用SetCaretPos以及GetTextExtend函式獲得字串寬度。

void CMyMFCAppView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    //TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
    CClientDC dc(this);
 
    // Enter鍵處理
    if (0x0d == nChar)
    {
        TEXTMETRIC tm;
        dc.GetTextMetrics(&tm);
        m_strLine.Empty();
        m_lMouseP.y += tm.tmHeight;
    }
    // 退格鍵處理
    else if (0x08 == nChar)
    {
        COLORREF clr= dc.SetTextColor(dc.GetBkColor());
        dc.TextOut(m_lMouseP.x,m_lMouseP.y, m_strLine);
        m_strLine =m_strLine.Left(m_strLine.GetLength() - 1);
        dc.SetTextColor(clr);
    }
    else
        m_strLine += (unsigned char) nChar;
 
    dc.TextOut(m_lMouseP.x, m_lMouseP.y, m_strLine);
    CView::OnChar(nChar, nRepCnt, nFlags);
}

4.4.1 設定字型

MFC提供一個CFont類設定字型,該類派生於CGdiObject類,封裝了一個Windows圖形裝置介面(GDI)的字型。初始化函式有: CreateFont、CreateFontIndirect、CreatePointFont、CreatePontFontIndirect。作用主要是將其C++物件和字型資源關聯起來。同其他GDI物件一樣,建立初始化之後,需要將它選入裝置描述表,用完再恢復。

       BOOLCreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC * pDC = NULL) 
        //   nPointSize為字型高度。lpszFaceName字型名稱。
// 4.4.1 設定字型
    CFont font;
    font.CreatePointFont(200, "華文琥珀");
    CFont* pOldFont = dc.SelectObject(&font);
    …
    dc.SelectObject(pOldFont);

4.4.2字幕變色功能

為實現該功能使用DrawText來實現。Int DrawText(const CString &str, LPRSRCT lpRect, UINT nFormat); str為輸出字串,lpRect為輸出矩形區域,nFormat為輸出格式。當字串超過矩形區域自動截斷。為使其不斷變化、自動進行,要不斷呼叫,同時增加矩形寬度,需要用到定時器。UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT *lpfnTimer)(HWND, UINT, UINT, DWORD));呼叫成功,返回新定時器的標識。nIDEvent標識,nElapse多長時間傳送一個WM_TIMER,單位是毫秒。lpfnTimer函式指標,NULL則將WM_TIMER放置到應用程式的訊息佇列中。

為了使舉行範圍不斷增加,在視類新增私有變數m_nWidth,建構函式初始化為0。視類響應WM_TIMER訊息,m_nWidth按3個畫素點增加,也就是DrawText矩形區域按3畫素增加。新增字串資源IDS_MYSTRING。第三個引數設定為DT_LEFT左對齊。

void CMyMFCAppView::OnTimer(UINT_PTR nIDEvent)
{
    //TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
    //4.4.2 字幕變色功能OnTimer
    m_nWidth += 3;
    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    CRect rect;
    rect.left = 0;
    rect.top = 150;
    rect.right = rect.left + m_nWidth;
    rect.bottom = rect.top + tm.tmHeight;
 
    dc.SetTextColor(RGB(255,0, 0));
    CString str;
    str.LoadString(IDS_MYSTRING);
    dc.DrawText(str, rect, DT_LEFT);
    CView::OnTimer(nIDEvent);
}

另外,字幕隨時間平滑變色,在OnDraw新增一下源顏色顯示程式碼。OnTimer新增超過字串尺寸,矩形寬度置0函式。

void CMyMFCAppView::OnDraw(CDC* pDC)
{
    …
    COLORREF clr = pDC->SetTextColor(RGB(0,0, 255));
    str.LoadStringA(IDS_MYSTRING);
    pDC->TextOutA(0, 150, str);
    pDC->SetTextColor(clr);
    …
}
void CMyMFCAppView::OnDraw(CDC* pDC)
{
    …
    // 平滑變色
    CSize sz = dc.GetTextExtent(str);
    if (m_nWidth > sz.cx)
    {
        m_nWidth = 0;
        dc.SetTextColor(RGB(0,0, 255));
        dc.TextOut(rect.left,rect.top, str);
    }
    CView::OnTimer(nIDEvent);
}

相關文章