📄 creditsctrl.cpp
字号:
hotDC.CreateCompatibleDC(pDC);
int nSaveDCNormal = normalDC.SaveDC();
int nSaveDCHot = hotDC.SaveDC();
// initialize bitmaps
if(m_bmpNormal.m_hObject)
m_bmpNormal.DeleteObject();
m_bmpNormal.CreateCompatibleBitmap(pDC,m_rcClient.Width(),nMaxHeight);
if(m_bmpHot.m_hObject)
m_bmpHot.DeleteObject();
m_bmpHot.CreateCompatibleBitmap(pDC,m_rcClient.Width(),nMaxHeight);
// select bitmaps into DCs
normalDC.SelectObject(&m_bmpNormal);
hotDC.SelectObject(&m_bmpHot);
// fill with transparent color
normalDC.FillSolidRect(0,0,m_rcClient.right,nMaxHeight,m_crInternalTransparentColor);
hotDC.FillSolidRect(0,0,m_rcClient.right,nMaxHeight,m_crInternalTransparentColor);
CString sData = m_sData;
// substitute line break tags with newline characters
// sData.Remove('\n');
// sData.Replace("<br>","\n");
// sData.Replace("<p>","\n\n");
// make sure we get the last line displayed
sData += '\n';
// variables used for parsing
CList<font_attribs,font_attribs&> font_attribs_tree;
font_attribs fa;
fa.bBold = FALSE;
fa.bItalic = FALSE;
fa.bUnderline = FALSE;
fa.bStrikeout = FALSE;
fa.crBkColor = CLR_NONE;
fa.crColor = RGB(0,0,0);
fa.nSize = 12;
strcpy(fa.szName,"Arial");
font_attribs_tree.AddTail(fa); // default font
CList<general_attribs,general_attribs&> general_attribs_tree;
general_attribs ga;
ga.nAlign = 1;
ga.nVAlign = 1;
ga.nMaxWidth = m_rcClient.Width();
ga.nMaxHeight = nMaxHeight;
general_attribs_tree.AddTail(ga); // default alignment
font_attribs link;
BOOL bInsideTag = FALSE;
CString sCurTagName;
CString sCurElement;
CString sCurOption;
int nCurHPos = 0;
int nCurVPos = 0;
int nCurLineHeight = 0;
CArray<line_rect,line_rect&> arcLineRects; // list containg information about the elements in the current line. used for vertical alignment of these element at line break.
BOOL bIsLineEmpty = TRUE;
BOOL bIsOption = FALSE;
TCHAR cTmp;
COLORREF crHrColor;
int nHrWidth;
int nHrSize;
int nHrAlign;
CString sCurLink;
COLORREF crBitmap;
int nBitmapBorder;
CString sBitmap;
CDC lineDC;
lineDC.CreateCompatibleDC(&normalDC);
CBitmap lineBmp;
lineBmp.CreateCompatibleBitmap(&normalDC,ga.nMaxWidth,ga.nMaxHeight);
CBitmap *pOldBmp = lineDC.SelectObject(&lineBmp);
CDC hover_lineDC;
hover_lineDC.CreateCompatibleDC(&hotDC);
CBitmap hover_lineBmp;
hover_lineBmp.CreateCompatibleBitmap(&hotDC,ga.nMaxWidth,ga.nMaxHeight);
CBitmap *pOldHoverBmp = hover_lineDC.SelectObject(&hover_lineBmp);
// main parsing loop... processing character by character
// (don't even _try_ to understand what's going on here :)
for(int i = 0; i < sData.GetLength() && i >= 0; i++)
{
if(!bInsideTag)
{
if(sData[i] == '<')
{
if(sCurElement != "")
{
Parse_AppendText(&lineDC,&hover_lineDC,&nCurHPos,&nCurVPos,&nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail(),&font_attribs_tree.GetTail(),sCurElement, sCurLink, link);
bIsLineEmpty = FALSE;
}
sCurTagName = "";
sCurElement = "";
bInsideTag = TRUE;
continue;
}
if(sData[i] == '\n') // line break
{
if(bIsLineEmpty) // if line is empty add the height of a space with the current font
{
fa = font_attribs_tree.GetTail();
CFont font;
font.CreateFont(-fa.nSize,0,0,0,fa.bBold?FW_BOLD:0,fa.bItalic,fa.bUnderline,fa.bStrikeout,0,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH|FF_DONTCARE,&fa.szName[0]);
CFont *pOldFont = lineDC.SelectObject(&font);
CRect rect(0,0,ga.nMaxWidth,ga.nMaxHeight);
lineDC.DrawText(" ",rect,DT_CALCRECT);
lineDC.SelectObject(pOldFont);
nCurVPos += rect.Height();
} else
{
if(sCurElement != "")
Parse_AppendText(&lineDC,&hover_lineDC,&nCurHPos,&nCurVPos,&nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail(),&font_attribs_tree.GetTail(),sCurElement,sCurLink,link);
Parse_VAlignLine(&normalDC,&hotDC,&lineDC,&hover_lineDC,nCurHPos,nCurVPos,nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail());
nCurVPos += nCurLineHeight;
bIsLineEmpty = TRUE;
}
arcLineRects.RemoveAll();
nCurLineHeight = 0;
nCurHPos = 0;
sCurElement = "";
continue;
}
sCurElement += sData[i];
bIsLineEmpty = FALSE;
} else
{
if(sData[i] == '>')
{
if(sCurTagName == "font") // <font face="s" size="n" style="[-b|b][-i|i][-u|u][-s|s]" color="n,n,n" background="n,n,n">
{
font_attribs_tree.AddTail(fa);
general_attribs_tree.AddTail(ga);
} else if(sCurTagName == "" && sCurElement == "/font") // closing font tag.. revove the last attributes from the lists
{
if(font_attribs_tree.GetCount() > 1)
font_attribs_tree.RemoveTail();
if(general_attribs_tree.GetCount() > 1)
general_attribs_tree.RemoveTail();
} else if(sCurTagName == "" && sCurElement == "hr") // no parameters specified for the hr tag.. use the defaults
{
crHrColor = GetSysColor(COLOR_BTNSHADOW); // default color
nHrWidth = ga.nMaxWidth-100; // default width
nHrSize = 2; // default height
nHrAlign = 1; // center by default
sCurTagName = "hr";
}
if(sCurTagName == "hr") // wrap line is needed and draw rect
{
if(!bIsLineEmpty)
{
Parse_VAlignLine(&normalDC,&hotDC,&lineDC,&hover_lineDC,nCurHPos,nCurVPos,nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail());
nCurVPos += nCurLineHeight;
bIsLineEmpty = TRUE;
}
arcLineRects.RemoveAll();
nCurLineHeight = 0;
nCurHPos = 0;
CRect rect;
rect.left = nHrAlign == 0 ? 0 : (nHrAlign == 2 ? ga.nMaxWidth-nHrWidth : ga.nMaxWidth/2-nHrWidth/2);
rect.right = rect.left + nHrWidth;
rect.top = nCurVPos + 2;
rect.bottom = rect.top + nHrSize;
normalDC.FillSolidRect(rect,crHrColor);
nCurVPos += 4+nHrSize;
} else if(sCurTagName == "" && sCurElement== "/a" && sCurLink != "") // if we have an ending link tag AND valid link action and link region...
sCurLink = "";
else if(sCurTagName == "img" && sBitmap != "")
{
if(sBitmap[0]=='#') // only resource bitmaps allowed at this time
{
CBitmap bmp;
bmp.LoadBitmap(atoi(sBitmap.Mid(1)));
Parse_AppendBitmap(&lineDC,&hover_lineDC,&nCurHPos,&nCurVPos,&nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail(),&bmp, crBitmap, nBitmapBorder, sCurLink, link);
bIsLineEmpty = FALSE;
}
crBitmap = CLR_NONE;
nBitmapBorder = 0;
sBitmap = "";
} else if(sCurTagName == "br" || (sCurTagName == "" && sCurElement== "br")) // just substitute with newline character
{
sData.SetAt(i,'\n');
i--;
} else if(sCurTagName == "p" || (sCurTagName == "" && sCurElement== "p")) // just substitute with 2 newline characters
{
sData.SetAt(i,'\n');
sData.SetAt(i-1,'\n');
i-= 2;
}
sCurElement = "";
bInsideTag = FALSE;
continue;
}
if(sData[i] == ' ' && !bIsOption)
{
if(sCurElement != "")
{
if(sCurTagName == "")
{
sCurTagName = sCurElement;
sCurTagName.MakeLower();
if(sCurTagName == "font") // store latest font attributes. these are the ones that are modified by the font tags parameters
{
fa = font_attribs_tree.GetTail();
ga = general_attribs_tree.GetTail();
} else if(sCurTagName == "hr") // set default hr options...
{
crHrColor = GetSysColor(COLOR_BTNSHADOW);
nHrWidth = ga.nMaxWidth-10;
nHrSize = 2;
nHrAlign = 1;
} else if(sCurTagName == "a") // init link hot attributes
{
link = font_attribs_tree.GetTail();
link.crColor = 0xeeffffff;
link.crBkColor = 0xeeffffff;
link.bBold = -10;
link.bItalic = -10;
link.bUnderline = -10;
link.bStrikeout = -10;
link.nSize = 0;
link.szName[0] = '\0';
} else if(sCurTagName == "img")
{
nBitmapBorder = 2;
crBitmap = CLR_NONE;
sBitmap = "";
}
} else
{
sCurOption = sCurTagName;
sCurOption.MakeLower();
}
}
sCurElement = "";
continue;
}
if(sData[i] == '"' || sData[i] == '\'') // this happens when we have a new parameter value to parse
{
if(bIsOption && sData[i]==cTmp) // "sData[i]==cTmp" : closing (double)quote has to match opening quote
{
if(sCurTagName == "font") // parse font tag paramaters
{
if(sCurOption == "size") // font size
{
int nSize = atoi(sCurElement);
if(nSize > 0 && nSize < 2000) // let's be reasonable
fa.nSize = nSize;
} else if(sCurOption == "face") // font face
{
strcpy(fa.szName,sCurElement.Left(MAX_PATH-1));
} else if(sCurOption == "style") // font style (bold (b) ,italic (i) ,underline (u) ,strikeout (s) )
{
if(sCurElement.Find("-b")!=-1 || sCurElement.Find("-B")!=-1)
fa.bBold = FALSE;
else if(sCurElement.FindOneOf("bB")!=-1)
fa.bBold = TRUE;
if(sCurElement.Find("-i")!=-1 || sCurElement.Find("-I")!=-1)
fa.bItalic = FALSE;
else if(sCurElement.FindOneOf("iI")!=-1)
fa.bItalic = TRUE;
if(sCurElement.Find("-u")!=-1 || sCurElement.Find("-U")!=-1)
fa.bUnderline = FALSE;
else if(sCurElement.FindOneOf("uU")!=-1)
fa.bUnderline = TRUE;
if(sCurElement.Find("-s")!=-1 || sCurElement.Find("-S")!=-1)
fa.bStrikeout = FALSE;
else if(sCurElement.FindOneOf("sS")!=-1)
fa.bStrikeout = TRUE;
} else if(sCurOption == "color") // font color
StringToColor(sCurElement,fa.crColor);
else if(sCurOption == "background") // font background-color
StringToColor(sCurElement,fa.crBkColor);
else if(sCurOption == "align") // horisontal font alignment. here we change the "general_attribs"
{ // only the latest open font tag with this parameter takes effect at a line break!!
sCurElement.MakeLower();
if(sCurElement == "left")
ga.nAlign = 0;
else if(sCurElement == "center")
ga.nAlign = 1;
else if(sCurElement == "right")
ga.nAlign = 2;
} else if(sCurOption == "valign") // vertical font alignment. here we change the "general_attribs"
{
sCurElement.MakeLower();
if(sCurElement == "top")
ga.nVAlign = 0;
else if(sCurElement == "middle")
ga.nVAlign = 1;
else if(sCurElement == "bottom")
ga.nVAlign = 2;
}
} else if(sCurTagName == "a")
{
if(sCurOption == "href") // what to do
sCurLink = sCurElement;
else if(sCurOption == "size") // font size
{
int nSize = atoi(sCurElement);
if(nSize > 0 && nSize < 2000) // let's be reasonable
link.nSize = nSize;
} else if(sCurOption == "face") // font face
{
strcpy(link.szName,sCurElement.Left(MAX_PATH-1));
} else if(sCurOption == "style") // font style (bold (b) ,italic (i) ,underline (u) ,strikeout (s) )
{
if(sCurElement.Find("-b")!=-1 || sCurElement.Find("-B")!=-1)
link.bBold = FALSE;
else if(sCurElement.FindOneOf("bB")!=-1)
link.bBold = TRUE;
if(sCurElement.Find("-i")!=-1 || sCurElement.Find("-I")!=-1)
link.bItalic = FALSE;
else if(sCurElement.FindOneOf("iI")!=-1)
link.bItalic = TRUE;
if(sCurElement.Find("-u")!=-1 || sCurElement.Find("-U")!=-1)
link.bUnderline = FALSE;
else if(sCurElement.FindOneOf("uU")!=-1)
link.bUnderline = TRUE;
if(sCurElement.Find("-s")!=-1 || sCurElement.Find("-S")!=-1)
link.bStrikeout = FALSE;
else if(sCurElement.FindOneOf("sS")!=-1)
link.bStrikeout = TRUE;
} else if(sCurOption == "color") // font color
StringToColor(sCurElement,link.crColor);
else if(sCurOption == "background") // font background-color
StringToColor(sCurElement,link.crBkColor);
} else if(sCurTagName == "img") // image tag: <img src="#resourceID">
{
// TODO: alow usage of filenames in <img> tag
if(sCurOption == "src" && sCurElement != "")
sBitmap = sCurElement;
if(sCurOption == "color")
StringToColor(sCurElement,crBitmap);
if(sCurOption == "border" && sCurElement != "")
nBitmapBorder = atoi(sCurElement);
} else if(sCurTagName == "hr") // horisontal ruler
{
if(sCurElement != "")
{
if(sCurOption == "color") // color
StringToColor(sCurElement,crHrColor);
else if(sCurOption == "width") // width
nHrWidth = atoi(sCurElement);
else if(sCurOption == "size") // height
nHrSize = atoi(sCurElement);
else if(sCurOption == "align") // horz alignment
{
sCurElement.MakeLower();
if(sCurElement=="left")
nHrAlign = 0;
else if(sCurElement=="right")
nHrAlign = 2;
else
nHrAlign = 1;
}
}
} else if((sCurTagName == "vspace") && (sCurOption == "size")) // vertical space
{
if(!bIsLineEmpty) // insert linebreak only is line isn't empty
{
Parse_VAlignLine(&normalDC,&hotDC,&lineDC,&hover_lineDC,nCurHPos,nCurVPos,nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail());
nCurVPos += nCurLineHeight;
bIsLineEmpty = TRUE;
}
arcLineRects.RemoveAll();
nCurLineHeight = 0;
nCurHPos = 0;
nCurVPos += atoi(sCurElement); // add "size" parameters value to vertical offset
} else if((sCurTagName == "hspace") && (sCurOption == "size")) // horisontal space
nCurHPos += atoi(sCurElement); // add "size" parameters value to horisontal offset
sCurElement = "";
bIsOption = FALSE;
} else if(sData[i-1] == '=') // parameter is beginning
{
sCurOption = sCurElement;
sCurOption = sCurOption.Left(sCurOption.GetLength()-1); // remove trailing "=";
sCurOption.MakeLower();
sCurOption.TrimRight();
sCurElement = "";
cTmp = sData[i];
bIsOption = TRUE;
}
continue;
}
sCurElement += sData[i]; // append non-formatting-significant character to curent element
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -