CDC活用術
¶CDC活用術
原文連結: https://darkblack01.blogspot.com/2012/05/cdc.html
移植時的最後更新日期: 2015-12-23T14:16:57.662+08:00
因為,View想要做得複雜又好維護,用起來像網頁語法一樣順暢
就這樣想
最後設計出來的code如下
void CColorEyeIView::OnDraw(CDC* pDC)
{
CColorEyeIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//表格的部份
//設計一個table class用類似HTML的語法來管理表格
//視窗左半邊,導覽區
CPoint ptTemp = ptFix;
CTable tbInfo(pDC, ptTemp);
ptTemp = tbInfo.SetCellNum(2, 4).SetTableBoard(0).SetGridBoard(0).SetFont(afont).SetCellSpace(1)
.Width(0, TextHight10).Width(1, TextHight12).Hight(0, 16).Hight(1, 16).Hight(2, 16)//.Hight(3, 16)
.tr().td().b().text(“Panel ID”).b_().td_() .td().text(pDoc->GetOmdFile().GetPnlID()).td_().tr_()
.tr().td().b().text(“Measurement device”).b_().td_().td().text(pDoc->GetOmdFile().GetMsrDvc()).td_().tr_()
.tr().td().b().text(“Probe”).b_().td_() .td().text(pDoc->GetOmdFile().GetPrb()).td_().tr_()
.tr().td().b().text(“Chanel”).b_().td_() .td().text(pDoc->GetOmdFile().GetCHID()).td_().tr_()
.table_();
…
}
CTable.h
#include <vector>
class CTable
{
//字型
CFont m_defFont;
CFont m_curFont;
CFont* p_OldFont;
LOGFONT m_lft;
//文字顏色
COLORREF m_oldclr;
COLORREF m_clrText;
COLORREF m_clrBackGround;
//畫格線
UINT m_fBoard;
UINT m_gBoard;
CPen m_GridPen;
CPen m_FramPen;
CPen* p_OldPen;
COLORREF m_fbColor;
COLORREF m_gbColor;
//背景色
CBrush m_BkArea;
CBrush* p_OldBrush;
std::vector m_SpanTable; //建一個table,以0開始定址,記錄跳格子的表
std::vector m_PointTable;
CDC* p_DC;
CPoint m_ptOrig;
CPoint m_ptCur;
CPoint m_ptNextXY;
CPoint m_ptEnd;
std::vector::size_type m_xCnt;
std::vector::size_type m_yCnt;
std::vector::size_type m_xCnt_Max;
std::vector::size_type m_yCnt_Max;
CSize m_CellSpace; //內容與格線間距
public:
CTable(CDC*, CPoint&);
virtual ~CTable();
CTable& SetFont(CFont&);
//粗體
CTable& b();
CTable& b_();
//斜體
CTable& i();
CTable& i_();
//底線
CTable& u();
CTable& u_();
//刪除線
CTable& s();
CTable& s_();
CTable& tr();//, CFont& ft
CTable& tr_();
CTable& td(UINT Hspan = 1, UINT Vspan = 1);
CTable& td(COLORREF bkclr, UINT Hspan, UINT Vspan); //設定格子背景
CTable& td(COLORREF bkclr); //設定格子背景
CTable& td(CFont ft, UINT Hspan = 1, UINT Vspan = 1);
CTable& td_();
CTable& text(CString, UINT nFlags = TA_LEFT);
CTable& text(CString, CFont&, UINT nFlags = TA_LEFT);
CTable& text(CString, CFont&, COLORREF, UINT nFlags = TA_LEFT);
CTable& Width(std::vector::size_type n, UINT w); //SetWidth(第幾個Cell, 多寬)
CTable& Hight(std::vector::size_type n, UINT h); //SetHight(第幾個Cell, 多高)
CPoint GetCellNum();
CTable& SetCellNum(UINT, UINT);
CTable& SetTableBoard(UINT tableboard, COLORREF tbclr = RGB(0,0,0));
CTable& SetGridBoard (UINT gridboard , COLORREF gbclr = RGB(0,0,0));
CTable& SetCellSpace(UINT sp = 2);
CPoint table_();
CPoint table_(std::vector& tbPt);
private:
void DrawRect(COLORREF bkclr);
UINT nextX(UINT);
UINT nextY(UINT);
void DrawGridBoard();
void DrawFrameBoard();
//debug
void ViewSpanTableValue(const CString title = “”);
void ViewTableTableValue(const CString title = “”);
};
/*
Spen Table Readme
0 1 2 3 4個
±-------±-------±-------±-------+
o | | h邊長1 | h邊長2 | h邊長3 |
±-------++++
1 | v邊長1 | 跳格子 | | |
±-------++++
2 | v邊長2 | 跳格子 | | |
±-------++++
3 | v邊長3 | | 跳格子 | |
±-------++++
4個
m_vCellWidth.at(m_xCnt) = Wk(k=0~n)
記錄左上角的定位點
0 1 2 3個
++++
0|pt(0,0) |pt(0,0) |pt(0,0) |
++++
1|pt(0,0) |pt(0,0) |pt(0,0) |
++++
2|pt(0,0) |pt(0,0) |pt(0,0) |
++++
3個
m_PointTable.at(m_xCnt) = Wk(k=0~n)
/
CTable.cpp
CTable::CTable(CDC pDC, CPoint& pt):
p_DC(pDC),m_CellSpace(2, 2),
m_ptCur(pt), m_ptOrig(pt), m_ptEnd(pt), m_ptNextXY(pt),
m_xCnt(1), m_yCnt(1),
m_clrText(RGB(0, 0, 0)), m_clrBackGround(RGB(255, 255, 255)),
m_gBoard(1), m_fBoard(1),
m_gbColor(RGB(0,0,0)), m_fbColor(RGB(0,0,0))
{
m_SpanTable.clear();
//Create Font
m_defFont.CreateFont(16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FF_MODERN, “Verdana”);
m_defFont.GetLogFont(&m_lft);
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
//刪掉字型(移動程式無法執行)
m_curFont.DeleteObject();
m_defFont.DeleteObject();
p_DC->SetBkMode(OPAQUE);
// CString strTemp;
// strTemp.Format(“R:%d\nG:%d\nB:%d”, GetRValue(m_gbColor), GetGValue(m_gbColor), GetBValue(m_gbColor));
// AfxMessageBox(strTemp);
}
CTable::~CTable()
{
//刪掉筆
m_GridPen.DeleteObject();
m_FramPen.DeleteObject();
m_SpanTable.clear();
}
CTable& CTable::SetTableBoard(UINT tableboard, COLORREF tbclr)
{
m_fBoard = tableboard;
m_fbColor = tbclr;
return *this;
}
CTable& CTable::SetGridBoard(UINT gridboard, COLORREF gbclr)
{
m_gBoard = gridboard;
m_gbColor = gbclr;
return *this;
}
CTable& CTable::SetCellSpace(UINT sp)
{
m_CellSpace.cx = sp;
m_CellSpace.cy = sp;
return *this;
}
CTable& CTable::SetFont(CFont& ft)
{
ft.GetLogFont(&m_lft);
m_defFont.CreateFontIndirect(&m_lft);
p_DC->SelectObject(&m_defFont);
m_defFont.DeleteObject();
return *this;
}
CTable& CTable::b()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfWeight = FW_BOLD;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return *this;
}
CTable& CTable::b_()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfWeight = FW_MEDIUM;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return *this;
}
CTable& CTable::i()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfItalic = TRUE;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return *this;
}
CTable& CTable::i_()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfItalic = FALSE;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return *this;
}
CTable& CTable::u()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfUnderline = TRUE;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return *this;
}
CTable& CTable::u_()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfUnderline = FALSE;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return *this;
}
CTable& CTable::s()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfStrikeOut = TRUE;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return this;
}
CTable& CTable::s_()
{
p_DC->SelectObject(p_OldFont);
m_lft.lfStrikeOut = FALSE;
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
return this;
}
CTable& CTable::tr()//往下一格
{
return this;
}
CTable& CTable::tr_()//往下一格
{
// CString strTemp;
//加上Cellspace和格線厚度
// if (m_xCnt != 0 && m_yCnt != 0)
m_ptCur.y = m_ptNextXY.y;
m_yCnt = (m_yCnt < m_yCnt_Max) ? m_yCnt + 1 : 1 ;
//設定End點
m_ptEnd.x = m_ptCur.x;
m_ptEnd.y = m_ptCur.y;
m_ptCur.x = m_ptOrig.x;//往下一格,座標x(水平)要回到原點
m_xCnt = 1;
return this;
}
CTable& CTable::td(UINT Hspan, UINT Vspan)//往右一格
{
// CString strTemp;
//紀錄設定儲存格定位點
//注意SpanTable和PointTable的座標位移誤差
//以SpanTable為主的話,PointTable的座標都要-1才會吻合
m_PointTable[(m_xCnt-1) + (m_yCnt-1) * (m_xCnt_Max-1)] = m_ptCur;
p_DC->SetPixel(m_ptCur, RGB(255, 0, 0));
// strTemp.Format("%d, %d", m_xCnt, m_yCnt);
// AfxMessageBox(strTemp);
//defFont和curFont都沒有字型了
//所以,不可以GetLogFont
m_curFont.CreateFontIndirect(&m_lft);
p_OldFont = p_DC->SelectObject(&m_curFont);
m_curFont.DeleteObject();
//設定字的顏色
m_oldclr = p_DC->SetTextColor(m_clrText);
int ii(1), ij(1);
//設定跳格子
if (Hspan != 1 || Vspan != 1)//預設就是1, 1
{
// strTemp.Format("");
for (ii = m_xCnt; ii < Hspan + m_xCnt; ++ii)
for (ij = m_yCnt; ij < Vspan + m_yCnt; ++ij)
{
// 若SpanTble格子裡為1,就是打算合併儲存格的儲存格
// 所以,之後不畫框線
m_SpanTable[ii + ijm_xCnt_Max] = 1;
// strTemp.Format("\nm_xCnt=%d, Hspan=%d/%d, ii=%d\nm_yCnt=%d, Vspan=%d/%d, ij=%d\nm_SpanTable[%d]=%d"<br />// , m_xCnt, Hspan, Hspan + m_xCnt, ii<br />// , m_yCnt, Vspan, Vspan + m_yCnt, ij<br />// , ii + ijVspan, m_SpanTable[ii + ijVspan]);
// ViewSpanTableValue(strTemp);
// ViewSpanTableValue();
}
}
m_ptNextXY.x = nextX(Hspan);
m_ptNextXY.y = nextY(Vspan);
//m_PointTable[m_xCnt].x + m_SpanTable[(m_xCnt-1)] + m_CellSpace.cx2;
// strTemp.Format(“m_ptNextXY.y = %d, m_ptCur.y = %d\n”<br />// , m_ptNextXY.y, m_ptCur.y);
// AfxMessageBox(strTemp);
// AfxMessageBox(“thisx”);
return *this;
}
CTable& CTable::td(COLORREF bkclr, UINT Hspan, UINT Vspan)
{
td(Hspan, Vspan);
DrawRect(bkclr);
return this;
}
CTable& CTable::td(COLORREF bkclr)
{
td();
DrawRect(bkclr);
return this;
}
CTable& CTable::td(CFont fnt, UINT Hspan, UINT Vspan)//往右一格
{
fnt.GetLogFont(&m_lft);
return td(Hspan, Vspan);
}
CTable& CTable::td_()//往右一格
{
p_DC->SelectObject(p_OldFont);
p_DC->SetTextColor(m_oldclr);
//設定跳格子,格子內為1,則跳格子
//讓xCnt跳動,計數到下一個要存放座標的記憶體空間。
// CString strTemp;
// strTemp.Format(_T(“SetCellNum(%d/%d, %d/%d), VAlue=%d\n”), m_xCnt, m_xCnt_Max, m_yCnt, m_yCnt_Max, <br />// m_SpanTable[(m_xCnt%m_xCnt_Max)]);
// ViewSpanTableValue(strTemp);
m_ptCur.x = m_ptNextXY.x;
do
{
++m_xCnt;
//strTemp.Format("%d", m_SpanTable[m_xCnt + m_yCnt * m_xCnt_Max]);
// strTemp.Format("%d/%d", m_xCnt + m_yCnt * m_xCnt_Max, m_xCnt_Maxm_yCnt_Max);
// AfxMessageBox(strTemp);
//最後一個不要讀取while裡的m_SpanTable[m_xCnt + m_yCnt * m_xCnt_Max]
//指標指向不知道哪裡的地方,會當掉。
if (m_xCnt + m_yCnt * m_xCnt_Max == m_xCnt_Maxm_yCnt_Max)
break;
} while (m_SpanTable[(m_xCnt + m_yCnt * m_xCnt_Max)]);
return this;
}
UINT CTable::nextX(UINT SpanNum)
{
UINT nX = m_ptCur.x;
UINT tXCnt = m_xCnt;
for (int i = 0; i < SpanNum; ++i)
{
if (m_xCnt != 0 && m_yCnt != 0)
nX = nX + m_SpanTable[(tXCnt%m_xCnt_Max)] + m_CellSpace.cx2; //取寬度,設定座標
tXCnt = (tXCnt < m_xCnt_Max) ? tXCnt + 1 : 1 ;
}
return nX;
}
UINT CTable::nextY(UINT SpanNum)
{
UINT nY = m_ptCur.y;
UINT tYCnt = m_yCnt;
//修正Cell高度(符合字高)
int TextHight(m_SpanTable[(m_yCnt%m_yCnt_Max)m_xCnt_Max]); //取高度,設定座標
// strTemp.Format(“m_yCnt m_yCnt_Max\n%d, %d = %d”, m_yCnt, m_yCnt_Max, m_yCnt%m_yCnt_Maxm_xCnt_Max);
// AfxMessageBox(strTemp);
TextHight = (TextHight < m_lft.lfHeight) ? m_lft.lfHeight : TextHight;
m_SpanTable[(m_yCnt%m_yCnt_Max)m_xCnt_Max] = TextHight;
for (int i = 0; i < SpanNum; ++i)
{
if (m_xCnt != 0 && m_yCnt != 0)
nY = nY + TextHight + m_CellSpace.cy2; //取寬度,設定座標
tYCnt = (tYCnt < m_yCnt_Max) ? tYCnt + 1 : 1 ;
}
return nY;
}
CTable& CTable::text(CString str, UINT nFlags)
{
UINT X, Y;
switch (nFlags)
{
case TA_CENTER:
//靠中的字,定位點=(左格線+留白+格寬+留白)/2
//也就是說,定位點=左格線到右格線的中間
X = (m_ptCur.x + m_ptNextXY.x)/2 + m_CellSpace.cx;
Y = (m_ptCur.y + m_ptNextXY.y)/2 - m_lft.lfHeight + m_CellSpace.cy;
//p_DC->TextOut ((m_ptCur.x + m_ptNextXY.x)/2 + m_CellSpace.cx, (m_ptCur.y + m_ptNextXY.y)/2 + m_CellSpace.cy, <br /> // str.GetBuffer(0), str.GetLength());
break;
case TA_RIGHT:
//靠右的字,定位點=左格線+留白+格子寬
//也就是說,定位點=右格線-留白
X = m_ptNextXY.x - m_CellSpace.cx;
//p_DC->TextOut (m_ptNextXY.x - m_CellSpace.cx, m_ptNextXY.y - m_CellSpace.cy, <br /> // str.GetBuffer(0), str.GetLength());
break;
default:
case TA_LEFT:
X = m_ptCur.x + m_CellSpace.cx;
//p_DC->TextOut (m_ptCur.x + m_CellSpace.cx, m_ptCur.y + m_CellSpace.cy, str.GetBuffer(0), str.GetLength());
break;
}
switch (nFlags)
{
case TA_BOTTOM:
//靠右的字,定位點=左格線+留白+格子寬
//也就是說,定位點=右格線-留白
Y = m_ptNextXY.y - m_CellSpace.cy;
//p_DC->TextOut (m_ptNextXY.x - m_CellSpace.cx, m_ptNextXY.y - m_CellSpace.cy, <br /> // str.GetBuffer(0), str.GetLength());
break;
default:
case TA_TOP:
Y = m_ptCur.y + m_CellSpace.cy;
//p_DC->TextOut (m_ptCur.x + m_CellSpace.cx, m_ptCur.y + m_CellSpace.cy, str.GetBuffer(0), str.GetLength());
break;
}
p_DC->SetTextAlign(nFlags);
p_DC->TextOut (X, Y, str.GetBuffer(0), str.GetLength());
return *this;
}
CTable& CTable::text(CString str, CFont& ft, UINT nFlags)
{
//主要設定字型
p_OldFont = p_DC->SelectObject(&ft);
ft.DeleteObject();
text(str, nFlags);
p_DC->SelectObject(p_OldFont);
return *this;
}
CTable& CTable::text(CString str, CFont& ft, COLORREF clr, UINT nFlags)
{
//主要設定color
m_clrText = clr;
m_oldclr = p_DC->SetTextColor(m_clrText);
text(str, ft, nFlags);
p_DC->SetTextColor(m_oldclr);
return this;
}
CTable& CTable::Hight(std::vector::size_type n, UINT h) //SetHight(第幾個Cell, 多高)
{
m_SpanTable[m_xCnt_Max (n+1)] = h;
return this;
}
CTable& CTable::Width(std::vector::size_type n, UINT w) //SetWidth(第幾個Cell, 多寬)
{
// ViewSpanTableValue(); //Debug
m_SpanTable[n+1] = w;
return this;
}
CTable& CTable::SetCellNum(UINT x, UINT y)//(11, 7)
{
//設定儲存格定位點的對照表
//初始值以每個表格的原點為準
//之後儲存CurrPoint就可以了
m_xCnt_Max = x;
m_yCnt_Max = y;
UINT xit;
UINT yit;
for (yit = 0; yit < m_yCnt_Max; ++yit) // 8
for (xit = 0; xit < m_xCnt_Max; ++xit) // 12
m_PointTable.push_back(m_ptOrig);
//設定表格限定值
//先設定好字的高與寬,才可以設定這個
m_xCnt_Max = x+1;
m_yCnt_Max = y+1;
UINT initValue = 0;
for (yit = 0; yit < m_yCnt_Max; ++yit) // 8
for (xit = 0; xit < m_xCnt_Max; ++xit) // 12
{
if (xit == 0 && yit == 0)
m_SpanTable.push_back(initValue);
else if (xit == 0)//欄寬
m_SpanTable.push_back(16);
else if (yit == 0)//列高
m_SpanTable.push_back(1);
else//內容
m_SpanTable.push_back(initValue);
}
// CString strTemp;
// strTemp.Format(“SetCellNum(%d, %d)”, m_xCnt_Max, m_yCnt_Max);
// ViewSpanTableValue(strTemp);
return this;
}
CPoint CTable::GetCellNum()
{
CPoint pt((int)m_xCnt_Max, (int)m_yCnt_Max);
return pt;
}
CPoint CTable::table_(std::vector& tbPt)
{
//tbPt.clear();
tbPt.clear();
tbPt.push_back(m_ptOrig);
for (std::vector::iterator it = m_PointTable.begin(); it != m_PointTable.end(); ++it)
tbPt.push_back(it);
tbPt.push_back(m_ptEnd);
// ViewSpanTableValue();
// ViewTableTableValue();
return table_();
}
CPoint CTable::table_()
{
// ViewSpanTableValue("
"); // ViewTableTableValue(""); //設定內格線 m_GridPen.CreatePen((m_gBoard == 0)?PS_NULL:PS_SOLID, m_gBoard, m_gbColor); p_OldPen = p_DC->SelectObject(&m_GridPen); DrawGridBoard(); p_DC->SelectObject(p_OldPen); //設定外框線 m_FramPen.CreatePen((m_fBoard == 0)?PS_NULL:PS_SOLID, m_fBoard, m_fbColor); p_OldPen = p_DC->SelectObject(&m_FramPen); DrawFrameBoard(); p_DC->SelectObject(p_OldPen); //釋放 m_SpanTable.clear(); m_PointTable.clear(); return m_ptCur; } void CTable::ViewSpanTableValue(const CString title) { //all of table value CString strTemp, temp; strTemp.Format((title.IsEmpty()) ? (_T(“SetCellNum(%d/%d, %d/%d)”), m_xCnt, m_xCnt_Max, m_yCnt, m_yCnt_Max) : (_T("%s"), title)); strTemp += _T("\n"); for (std::vector
發表於
tags:
{ C_and_Cpp }
{ WIN32 API/MFC }