MFC 畫線,畫刷,文字
CPaintDC dc(this);//只能在OnPaint函式中使用
CClientDC dc(this);//在哪裡使用都可以
畫直線
獲得裝置描述表—>MoveTo -->LineTo
CClientDC dc(this);
dc.MoveTo(m_myPoint);
dc.LineTo(point);
畫連續直線
思路: 滑鼠按下時,變數flag為true,記初始點座標;在滑鼠移動訊息處理函式下,當flag為true,獲得裝置描述表 MoveTo LineTo
最重要的是: 滑鼠移動時,訊息終點為下一個的起始點。
滑鼠左鍵按下:
m_myPoint = point; m_bDrawFlag = true;
在滑鼠移動時:OnMouseMove()
if(true == m_bDrawFlag)//畫連續的線,前一段的終點是此段的起點
{
CClientDC dc(this);
dc.MoveTo(m_myPoint);
dc.LineTo(point);
m_myPoint = point;//如果沒有這個,則畫的線起點是一個,終點不同而已,
}
畫刷
- 簡單畫刷 :主要做填充
獲得裝置描述表–> 定義畫刷物件—>填充
CBrush brush(RGB(255,0,0)); CClientDC dc(this); dc.FillRect(CRect(m_myPoint,point),&brush);
- 點陣圖畫刷
思路:獲得裝置描述表—>定義點陣圖物件–>載入點陣圖–>定義畫刷物件–>填充
CClientDC dc(this);
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);//不想有虛線 可以新增標頭檔案 resource.h
CBrush brush(&bitmap);
dc.FillRect(CRect(m_myPoint,point),&brush);
字型 CFont::CreatePointFont
如果在OnDraw中就不需要獲取裝置描述表
思路: 建立物件 -> 選入裝置描述表中 -> 輸出TextOut即可 -> 恢復原來的字型
CFont::CFont font;
font.CreatePointFont(500,_T("楷體"));
CFont *pOldFont = pDC->SelectObject(&font);//將新的font物件選入裝置描述表,該函式返回的 被替代的物件的指標
pDC->TextOutW(200,50,_T("hello"));
pDC->SelectObject(pOldFont);//恢復原來的環境
pDC->TextOutW(200,150,_T("hello"));//為了測試,是不是恢復了預設的字型
輸出:
第一行: 一個很大字型的 hello
第二行 : 一個很小字型的 hello
任意位置的 插入符 CWnd::CreateSolidCaret
建立–》顯示–》移動–》必須要時要隱藏
函式:CWnd::CreateSolidCaret實體
函式:CreateCaret 需要CBitmap
在檢視中,OnCreate中建立,是因為: 在視窗建立之前建立插入符是沒有任何意義的,所以在視窗建立完後在建立插入符,故在OnCreate中
- 一般插入符:
CreateSolidCaret(100,100);//太大啦,不和諧,獲取字型資訊
ShowCaret();
發現建立的插入符太太太大了。。。怎麼辦呢?獲取環境的插入符資訊,然後給新的插入符,按照一定比例來建立。
2. 根據上下文環境設定插入符
//建立視窗後再建立插入符,就可以,沒有視窗,建立插入符也沒啥作用
//獲取字型資訊
CClientDC dc(this);
TEXTMETRIC text;//字型資訊結構體
dc.GetTextMetrics(&text);//之前給text定義的LPTEXTMETRIC 顯示 引數不相容
CreateSolidCaret(text.tmAveCharWidth/8,text.tmHeight);//太大啦,不和諧,獲取字型資訊
ShowCaret();
3. 任意位置插入插入符 SetCaretPos(point);
SetCaretPos(point);//移動插入符
滑鼠左鍵:任意位置 設定游標位置
任意位置點選鍵盤輸入字元
在上面任意 位置 點選 就顯示插入符的基礎上,寫字型:
a. 定義全域性變數 CString m_strCon; CPoint m_point;//TextOut中需要
b. 滑鼠左鍵按下時,
清空m_strCon.Text("");或者 m_strCon.Empty();
m_point = point;//點選位置寫入
作用: 寫入時不會把上一次的內容也顯示上
c. 鍵盤訊息在WM_CHAR中處理:
在文件中顯示輸入字元TextOut
//鍵盤中輸入內容
m_strCon += (TCHAR)nChar;
//寫字型 在CDC中
CClientDC dc(this);
dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);
發現上面游標並沒有跟著走:而且原來寫的前面還有一個游標:
【解決方法】獲取字串的尺寸資訊,在起點座標的基礎上,加上這個尺寸資訊就可以啦
//鍵盤中輸入內容
m_strCon += (TCHAR)nChar;
//寫字型 在CDC中
CClientDC dc(this);
//游標隨著輸入走
CSize size = dc.GetTextExtent(m_strCon);/獲取字串的尺寸資訊
int x = m_myPoint.x + size.cx;//不能是 m_strCon.GetLength();
int y = m_myPoint.y;
SetCaretPos(CPoint(x,y));
//輸出字型//起點座標不能改
dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);//這個必須是原來的位置,就是在按下的時候的位置
任意位置的字元的換行、退格
void CDrawLineView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
//鍵盤中輸入內容
//寫字型 在CDC中
CClientDC dc(this);
if(nChar == VK_RETURN)//換行
{
m_strCon.Empty();
TEXTMETRIC text;//字型資訊結構體
dc.GetTextMetrics(&text);
m_myPoint.y += text.tmHeight;
}
else if(nChar == VK_BACK)//重新寫
{
//先用白色背景重新寫一個全的,然後在寫一個去掉的
COLORREF col = dc.GetBkColor();
COLORREF Old = dc.SetTextColor(col);
dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);
m_strCon = m_strCon.Left(m_strCon.GetLength() - 1);
dc.SetTextColor(Old);
}
else
{
m_strCon += (TCHAR)nChar;;
}
//游標隨著輸入走
CSize size = dc.GetTextExtent(m_strCon);
int x = m_myPoint.x + size.cx;
int y = m_myPoint.y;
SetCaretPos(CPoint(x,y));
//輸出字型
dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);
CView::OnChar(nChar, nRepCnt, nFlags);
}
字型顏色隨時間變化,像歌詞
m_nWidth為全域性 int
if(nIDEvent == 12)
{
m_nWidth += 5;//+= 50時 顯示不全
CString str = _T("hello,hello,show up if you want to have something ,you must do your best !");
CClientDC dc(this);
CSize size = dc.GetTextExtent(str);
if(m_nWidth > size.cx)
{
m_nWidth = 0;
Invalidate(false);//介面重新整理
}
//先獲得原來的顏色
dc.TextOutW(200,50,str);
COLORREF col = dc.GetTextColor();
dc.SetTextColor(RGB(255,0,0));//設定新的顏色
dc.DrawText(str,CRect(200,50,200 + m_nWidth,50 + size.cy),DT_BOTTOM);
dc.SetTextColor(col);//恢復原來顏色
}
函式InValidate()
原型:void Invalidate( BOOL bErase = TRUE );
功能: 該函式的作用是使整個視窗客戶區無效。視窗的客戶區無效意味著需要重繪。
bErase 決定了在傳送WM_PAINT之前是否傳送WM_ERASEBKGND.
Invalidate: 函式: 是重新整理視窗,呼叫這個函式會產生訊息WM_PAINT 程式會相應ONDraw或者OnPaint函式
bErase = false 時 不擦除背景色,直接繪圖;
bErase = true 時 需要擦除背景色,會出現 刷屏的現象
InvalidateRect():
該函式的功能與Invalidate基本一樣,不同的是,它是使指定的某個區域無效,需要輸入一個區域,如果引數為NULL,則設定整個視窗為無效區。
函式UpdateWindow( )
原型:BOOL UpdateWindow(HWND hWnd );// hWnd 要更新的視窗的控制代碼
UpdateWindow函式就傳送一個WM_PAINT訊息來更新指定視窗的客戶區。
UpdateWindow( )的作用是使視窗立即重繪。呼叫Invalidate等函式後窗口不會立即重繪,這是由於WM_PAINT訊息的優先順序很低,它需要等訊息佇列中的其它訊息傳送完後才能被處理。呼叫UpdateWindow函式可使WM_PAINT被直接傳送到目標視窗,從而導致視窗立即重繪。
關於這幾個函式的具體用法,見連結
【總結】
1.新增變數方式:選中所屬類,新增變數 變數型別CPoint 可以自己輸入,這樣子的話可以,新增的變數會有初始化
2.在VS2010中資源時會有曲線,可以新增標頭檔案 resource.h 就沒有曲線啦,這個VS2010就是有點問題哦
3. 有多個LineTo時:
pDC->MoveTo(20,20);
pDC->LineTo(40,40);//
pDC->LineTo(50,87);//這個LineTo的起點 (MoveTo)就是上一個 LineTo的點,所以是一個折線:
線段一 點(20,20)到(40,40)
線段二 點(40,40)到(50,87)
4. 多個MoveTo時:
pDC->MoveTo(20,20);
pDC->MoveTo(40,40);//
pDC->LineTo(50,87);
最後只有一條線段: 點 (40,40)到點(50,87) ,第一個MoveTo的點就被忽略了。
5. SelectObject 函式
功能: 將新的font物件選入裝置描述表,
返回值:該函式返回的 被替代的物件的指標
CFont *pOldFont = pDC->SelectObject(&font);//該函式返回的 被替代的物件的指標
再次使用的時候:pDC->SelectObject(pOldFont); 恢復成原來的,如果在輸出時,字型就變成預設的字型了,而不是自己設定的字型。
所以,在使用CPen CBrush CFont BitMap 時 一定要對SelectObject成對使用
6. 函式CDC::GetTextMetrics 獲得裝置的字型資訊,使用時,必須的CClientDC dc(this); 必須獲得裝置描述表
7. CSize CDC::GetTextExtent(const CString& str) const; //獲取字串的尺寸資訊
8. CDC::GetTextMetrics()//獲取字元的資訊,高度與7中cy大小是一樣子的
9. GetTextColor
COLORREF GetTextColor() const; 獲得當前字型的顏色
virtual COLORREF SetTextColor(COLORREF crColor );設定當前字型顏色