1. 如何創建光標顯示在view類中
1.1 創建OnCreate函數,在view類上右鍵>>屬性,然後在選擇WM消息中的OnCreate
1.2, 在Oncreate中添加如下代碼(詳細見代碼及註釋,取消代碼中的註釋以打開功能即可)
int CxxxxView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
/*一般字體的插入符 的創建
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);//獲取字信息
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);//創建插入符,除8是調試值,使得寬度符合視覺要求,讀者可以更改看效果。
ShowCaret();//顯示插入符
*/
/*創建圖形插入符
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
bitmap.LoadBitmapW(IDB_BITMAP1);//位圖的創建:在資源視圖/Bitmap下,右鍵創建即可。
CreateCaret(&bitmap);
ShowCaret();
*/
return 0;
}
2. 向View窗口輸出文字,當移動窗口的時候需要重新顯示文字,所以要用到OnDraw消息處理函數。每次窗體的改變都會調OnDraw,添加如下代碼
void CxxxxView::OnDraw(CDC* pDC)
{
CSunXinjiaocheng05Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處爲本機數據添加繪製代碼
//CString str("DengYou");//直接用字符串去構造也可以
CString str;
str = "xxxxxyyyyy";//因爲其重載了=號.
pDC->TextOutW(50,50,str);
str.LoadStringW(IDS_DDDYYY);//使用資源視圖>>String Table 裏面的字符串,讀者自己可以去創建
pDC->TextOutW(200,200,str);
}
3.路徑層和剪切區域,實現某部分文字不被其他(線條,顏色等)覆蓋,讓某部分文字顯示不一樣。查看如下代碼註釋。
void CxxxxView::OnDraw(CDC* pDC)
{
CSunXinjiaocheng05Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處爲本機數據添加繪製代碼
//CString str("DengYou");//直接用字符串去構造也可以
CString str;
str = "xxxxxyyyyy";//因爲其重載了=號.
pDC->TextOutW(50,50,str);
str.LoadStringW(IDS_DDDYYY);//使用資源視圖>>String Table 裏面的字符串,讀者自己可以去創建
pDC->TextOutW(200,200,str);
//路勁層 類似選定區域
CSize cz = pDC->GetTextExtent(str);//獲取字符的寬度和高度
pDC->BeginPath();//註釋掉這個對成句,則可以看到矩形框
pDC->Rectangle(0,50,50+cz.cx,50+cz.cy);
pDC->EndPath();
//pDC->SelectClipPath(RGN_DIFF);//文字部分無網格線條
pDC->SelectClipPath(RGN_AND);//只有文字上有網格線條
for (int i = 0; i < 300; i += 10)//畫網格 造中間留10個像素的網格,發現文字都在網格里
{
pDC->MoveTo(0,i);
pDC->LineTo(300,i);
pDC->MoveTo(i,0);
pDC->LineTo(i,300);
}
}
4.字符輸入的功能,鍵盤輸入字符顯示到窗口上,刪除,換行,字體,光標移動 模擬KALAOK字幕變色,創建定時器 等 。
4.1 首先要捕獲鍵盤按下的消息WM_CHAR消息。增加一個WM_CHAR消息,選擇後會自動生成OnChar處理函數
void CxxxxView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
CClientDC dc(this);
CFont font;//字體類
font.CreatePointFont(300, L"華文行楷", NULL);//創建了字體"華文行楷"
CFont * pOldFont = dc.SelectObject(&font);//選擇字體,並返回之前字體。
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);//獲取字符高度
if (0x0d == nChar)//判斷回車鍵,
{
m_strLine.Empty();//換行了,從新開始新的字符串,清空之前的。
m_ptOrigin.y += tm.tmHeight;//回車之後光標x軸不變,y軸增加一個字符高度
}
else if (0x8 == nChar)//處理退格(刪除)鍵
{
COLORREF clr = dc.SetTextColor(dc.GetBkColor());//把文字變成背景色,
dc.TextOutW(m_ptOrigin.x, m_ptOrigin.y, m_strLine);//輸出與背景色一樣的文字以產生刪除效果
m_strLine = m_strLine.Left(m_strLine.GetLength()-1);//留左邊length-1的字符個數。
dc.SetTextColor(clr);
//刪除後的文字放在最後輸出
}
else
{
m_strLine += (char)nChar;//接收字符組成字符串。
}
CSize sz = dc.GetTextExtent(m_strLine);
CPoint pt;
pt.x = m_ptOrigin.x + sz.cx;//x軸,光標跟隨文字輸入而移動
pt.y = m_ptOrigin.y; //y軸不變
SetCaretPos(pt);//設置新光標
dc.TextOutW(m_ptOrigin.x, m_ptOrigin.y, m_strLine);
dc.SelectObject(pOldFont);//撤回到之前字體
CView::OnChar(nChar, nRepCnt, nFlags);
}
4.2 爲View類增加CString,CPoint和一個int類型的寬度值。成員並在View類構造函數裏初始化爲空和0;
4.3 字符應該從插入符處插入的,所以需要一個鼠標左鍵的消息WM_LBUTTONDOWN。會自動生成OnLButtonDown函數。函數內容見代碼和註釋;
void CxxxxView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
SetCaretPos(point);//設置光標到左鍵按下的點,鼠標左鍵在哪裏按下光標就到哪裏。
m_strLine.Empty();//當鼠標按下,光標到新地方時,元字符串清空,以便新字符串的開始。
m_ptOrigin = point; //當鼠標左鍵按下時,保留左鍵按下的位置
CView::OnLButtonDown(nFlags, point);
}
4.4 定時器 用來實現KALAOK字幕 移動定時,看註釋。設置了定時器,那麼定時器消息就會送到windows消息隊列。
4.4.1 定時器加了,當然要增加捕獲此消息的函數。給view類增加WM_TIMER消息處理
void CxxxxView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
//只設置了1個定時器100ms,即每隔100ms,此函數就會被調用
//nIDEvent 表示來自多個定時器的消息,可以用來判斷選擇定時器消息。本例只有一個定時器所以不用判斷。
m_nWith += 5;//每次每5個像素的加
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CRect rect; //矩形框
rect.left = 0;
rect.top = 200;
rect.right = m_nWith;
rect.bottom = rect.top + tm.tmHeight;
dc.SetTextColor(RGB(355,0,0));//紅色
CString str;//接下來輸出文字
str.LoadStringW(IDS_DDDYYY);//獲取string資源字符。
dc.DrawText(str, rect, DT_LEFT); //DT_LEFT 左對齊形式。從左邊開始顯示出字符
//dc.DrawText(str,rect,DT_RIGHT);
//dc.DrawText(str,rect,DT_CENTER);
CSize sz = dc.GetTextExtent(str);
if (m_nWith > sz.cx)//超過了字符串寬度
{
m_nWith = 0;//寬度清零
dc.SetTextColor(RGB(0,255, 0));//設施文本顏色
dc.TextOutW(0,200,str);//要以新的顏色輸出纔有效果
}
CView::OnTimer(nIDEvent);
}
注意:實例中用到的相關類和類成員請查看MSDN或其他地方搜索,提供MSDN如下:
鏈接:https://pan.baidu.com/s/1UPpu61qQMQGk4kLjYl5WbQ
提取碼:a620
類
// SunXin_jiaocheng05View.h: CSunXinjiaocheng05View 類的接口
//
#pragma once
class CSunXinjiaocheng05View : public CView
{
protected: // 僅從序列化創建
CSunXinjiaocheng05View() noexcept;
DECLARE_DYNCREATE(CSunXinjiaocheng05View)
// 特性
public:
CSunXinjiaocheng05Doc* GetDocument() const;
// 操作
public:
// 重寫
public:
virtual void OnDraw(CDC* pDC); // 重寫以繪製該視圖
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// 實現
public:
virtual ~CSunXinjiaocheng05View();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函數
protected:
afx_msg void OnFilePrintPreview();
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
private:
CBitmap bitmap;
CString m_strLine;//用來保存字符串
CPoint m_ptOrigin;//用來保存鼠標點座標
int m_nWith;//用來保存寬度信息,KALAOK字幕功能使用。
public:
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
#ifndef _DEBUG // SunXin_jiaocheng05View.cpp 中的調試版本
inline CSunXinjiaocheng05Doc* CSunXinjiaocheng05View::GetDocument() const
{ return reinterpret_cast<CSunXinjiaocheng05Doc*>(m_pDocument); }
#endif
CPP
// SunXin_jiaocheng05View.cpp: CSunXinjiaocheng05View 類的實現
//
#include "pch.h"
#include "framework.h"
// SHARED_HANDLERS 可以在實現預覽、縮略圖和搜索篩選器句柄的
// ATL 項目中進行定義,並允許與該項目共享文檔代碼。
#ifndef SHARED_HANDLERS
#include "SunXin_jiaocheng05.h"
#endif
#include "SunXin_jiaocheng05Doc.h"
#include "SunXin_jiaocheng05View.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSunXinjiaocheng05View
IMPLEMENT_DYNCREATE(CSunXinjiaocheng05View, CView)
BEGIN_MESSAGE_MAP(CSunXinjiaocheng05View, CView)
// 標準打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CSunXinjiaocheng05View::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP()
ON_WM_CREATE()
ON_WM_CHAR()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
END_MESSAGE_MAP()
// CSunXinjiaocheng05View 構造/析構
CSunXinjiaocheng05View::CSunXinjiaocheng05View() noexcept
{
// TODO: 在此處添加構造代碼
m_strLine = "";
m_ptOrigin = 0;
m_nWith = 0;
}
CSunXinjiaocheng05View::~CSunXinjiaocheng05View()
{
}
BOOL CSunXinjiaocheng05View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此處通過修改
// CREATESTRUCT cs 來修改窗口類或樣式
return CView::PreCreateWindow(cs);
}
// CSunXinjiaocheng05View 繪圖
void CSunXinjiaocheng05View::OnDraw(CDC* pDC)
{
CSunXinjiaocheng05Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處爲本機數據添加繪製代碼
//CString str("DengYou");//直接用字符串去構造也可以
CString str;
str = "xxxxxyyyyy";//因爲其重載了=號.
pDC->TextOutW(50,50,str);
str.LoadStringW(IDS_DDDYYY);//使用資源視圖>>String Table 裏面的字符串,讀者自己可以去創建
pDC->TextOutW(200,200,str);
//路勁層 類似選定區域
CSize cz = pDC->GetTextExtent(str);//獲取字符的寬度和高度
pDC->BeginPath();//註釋掉這個對成句,則可以看到矩形框
pDC->Rectangle(0,50,50+cz.cx,50+cz.cy);
pDC->EndPath();
//pDC->SelectClipPath(RGN_DIFF);//文字部分無網格線條
pDC->SelectClipPath(RGN_AND);//只有文字上有網格線條
for (int i = 0; i < 300; i += 10)//畫網格 造中間留10個像素的網格,發現文字都在網格里
{
pDC->MoveTo(0,i);
pDC->LineTo(300,i);
pDC->MoveTo(i,0);
pDC->LineTo(i,300);
}
}
// CSunXinjiaocheng05View 打印
void CSunXinjiaocheng05View::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
AFXPrintPreview(this);
#endif
}
BOOL CSunXinjiaocheng05View::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默認準備
return DoPreparePrinting(pInfo);
}
void CSunXinjiaocheng05View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加額外的打印前進行的初始化過程
}
void CSunXinjiaocheng05View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印後進行的清理過程
}
void CSunXinjiaocheng05View::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
ClientToScreen(&point);
OnContextMenu(this, point);
}
void CSunXinjiaocheng05View::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}
// CSunXinjiaocheng05View 診斷
#ifdef _DEBUG
void CSunXinjiaocheng05View::AssertValid() const
{
CView::AssertValid();
}
void CSunXinjiaocheng05View::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSunXinjiaocheng05Doc* CSunXinjiaocheng05View::GetDocument() const // 非調試版本是內聯的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSunXinjiaocheng05Doc)));
return (CSunXinjiaocheng05Doc*)m_pDocument;
}
#endif //_DEBUG
// CSunXinjiaocheng05View 消息處理程序
int CSunXinjiaocheng05View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
/*一般字體的插入符 的創建
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);//獲取字信息
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);//創建插入符,除8是調試值,使得寬度符合視覺要求,讀者可以更改看效果。
ShowCaret();//顯示插入符
*/
//創建圖形插入符
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
bitmap.LoadBitmapW(IDB_BITMAP1);//位圖的創建:在資源視圖/Bitmap下,右鍵創建即可。
CreateCaret(&bitmap);
ShowCaret();
SetTimer(1,100,NULL);//可以放到其他地方,但是要保證能被執行到,設置100ms,那麼這樣WM_TIMER 消息就會放到windows消息隊列中。
return 0;
}
void CSunXinjiaocheng05View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
CClientDC dc(this);
CFont font;//字體類
font.CreatePointFont(300, L"華文行楷", NULL);//創建了字體"華文行楷"
CFont * pOldFont = dc.SelectObject(&font);//選擇字體,並返回之前字體。
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);//獲取字符高度
if (0x0d == nChar)//判斷回車鍵,
{
m_strLine.Empty();//換行了,從新開始新的字符串,清空之前的。
m_ptOrigin.y += tm.tmHeight;//回車之後光標x軸不變,y軸增加一個字符高度
}
else if (0x8 == nChar)//處理退格(刪除)鍵
{
COLORREF clr = dc.SetTextColor(dc.GetBkColor());//把文字變成背景色,
dc.TextOutW(m_ptOrigin.x, m_ptOrigin.y, m_strLine);//輸出與背景色一樣的文字以產生刪除效果
m_strLine = m_strLine.Left(m_strLine.GetLength()-1);//留左邊length-1的字符個數。
dc.SetTextColor(clr);
//刪除後的文字放在最後輸出
}
else
{
m_strLine += (char)nChar;//接收字符組成字符串。
}
CSize sz = dc.GetTextExtent(m_strLine);
CPoint pt;
pt.x = m_ptOrigin.x + sz.cx;//x軸,光標跟隨文字輸入而移動
pt.y = m_ptOrigin.y; //y軸不變
SetCaretPos(pt);//設置新光標
dc.TextOutW(m_ptOrigin.x, m_ptOrigin.y, m_strLine);
dc.SelectObject(pOldFont);//撤回到之前字體
CView::OnChar(nChar, nRepCnt, nFlags);
}
void CSunXinjiaocheng05View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
SetCaretPos(point);//設置光標到左鍵按下的點,鼠標左鍵在哪裏按下光標就到哪裏。
m_strLine.Empty();//當鼠標按下,光標到新地方時,元字符串清空,以便新字符串的開始。
m_ptOrigin = point; //當鼠標左鍵按下時,保留左鍵按下的位置
CView::OnLButtonDown(nFlags, point);
}
void CSunXinjiaocheng05View::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
//只設置了1個定時器100ms,即每隔100ms,此函數就會被調用
//nIDEvent 表示來自多個定時器的消息,可以用來判斷選擇定時器消息。本例只有一個定時器所以不用判斷。
m_nWith += 5;//每次每5個像素的加
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CRect rect; //矩形框
rect.left = 0;
rect.top = 200;
rect.right = m_nWith;
rect.bottom = rect.top + tm.tmHeight;
dc.SetTextColor(RGB(355,0,0));//紅色
CString str;//接下來輸出文字
str.LoadStringW(IDS_DDDYYY);//獲取string資源字符。
dc.DrawText(str, rect, DT_LEFT); //DT_LEFT 左對齊形式。從左邊開始顯示出字符
//dc.DrawText(str,rect,DT_RIGHT);
//dc.DrawText(str,rect,DT_CENTER);
CSize sz = dc.GetTextExtent(str);
if (m_nWith > sz.cx)//超過了字符串寬度
{
m_nWith = 0;//寬度清零
dc.SetTextColor(RGB(0,255, 0));//設施文本顏色
dc.TextOutW(0,200,str);//要以新的顏色輸出纔有效果
}
CView::OnTimer(nIDEvent);
}