背景,从mfc开发的demo 向产品改进的时候 仍然使用mfc ,并用此方法美化界面
原理:在窗口中增加自绘元素,本文给出一个极简的例子,通过OnInitDialog解析一个配置字符串来创建自绘控件
同时要处理一下事件
BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
RECT rcClient;
::GetClientRect(m_hWnd, &rcClient);
m_drawUI.OnEraseBkgnd(pDC->m_hDC, rcClient);
return TRUE;
}
void CMyDlg::OnPaint()
{
PAINTSTRUCT ps;
HDC dc = ::BeginPaint(m_hWnd, &ps);
m_drawUI.OnPaint(dc);
::EndPaint(m_hWnd, &ps);
}
void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
m_drawUI.OnMouseMove(nFlags, point);
}
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
m_drawUI.OnLButtonDown(nFlags, point);
}
void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
m_drawUI.OnLButtonUp(nFlags, point);
}
LRESULT CMyDlg::OnNcHitTest(CPoint point)
{
::ScreenToClient(m_hWnd, &point);
if (point.y < ScalByDpi(45) && point.x < ScalByDpi(400))
{
return HTCAPTION;
}
return HTCLIENT;
}
HBRUSH CMyDlg::OnCtlColor(CDC * pDC, CWnd * pWnd, UINT nCtlColor)
{
// 其他控件背景色
DWORD id = pWnd->GetDlgCtrlID();
if (IDC_STATIC_LEAK_BOTTOM == id)
{
static CBrush bgBrush(COLOR_CLIENT_CTRL_BG);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(COLOR_CLIENT_CTRL_FONT);
return (HBRUSH)bgBrush;
}
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
return hbr;
}
using namespace std;
class CDrawUIBaseCtrl
{
public:
CDrawUIBaseCtrl();
~CDrawUIBaseCtrl();
enum UBS_TYPE{
TYPE_NONE,
TYPE_STATIC,
TYPE_PICTURE,
TYPE_PANEL,
TYPE_BUTTON,
};
public:
virtual void DrawOnDc(HDC dc) = 0;
virtual BOOL ProcessMouseMove(UINT nFlags, CPoint point, HWND hOP) { return FALSE; }
virtual BOOL ProcessLButtonDown(UINT nFlags, CPoint point, HWND hOP) { return FALSE; }
virtual BOOL ProcessLButtonUp(UINT nFlags, CPoint point, HWND hOP) { return FALSE; }
virtual INT GetType() = 0;
void InvalidRect(HWND hWnd);
public:
CRect m_rcPos;
BOOL m_bEraseOnInvalidRect = TRUE;
int m_nID = 0;
bool m_bVisible = true;
bool m_bEnable = true;
};
class CDrawUICtrl_Panel : public CDrawUIBaseCtrl
{
public:
CDrawUICtrl_Panel();
~CDrawUICtrl_Panel();
INT GetType() {
return CDrawUIBaseCtrl
::TYPE_PANEL;
}
public:
virtual void DrawOnDc(HDC dc);
public:
COLORREF m_fillColor;
};
class CDrawUICtrl_Static : public CDrawUIBaseCtrl
{
public:
CDrawUICtrl_Static();
~CDrawUICtrl_Static();
INT GetType() {
return CDrawUIBaseCtrl
::TYPE_STATIC;
}
public:
virtual void DrawOnDc(HDC dc);
public:
CString m_str;
COLORREF m_clrTxt;
int m_fontSize;
DWORD m_DrawType;
};
class CDrawUICtrl_Button : public CDrawUICtrl_Static
{
public:
CDrawUICtrl_Button();
~CDrawUICtrl_Button();
INT GetType() {
return CDrawUIBaseCtrl
::TYPE_BUTTON;
}
BOOL HasSelfBackColor() { return m_bHasSelfBkColor; }
void DrawSelfBkgndOnEraseBkgnd(HDC dc);
public:
virtual void DrawOnDc(HDC dc);
virtual BOOL ProcessMouseMove(UINT nFlags, CPoint point, HWND hOP);
virtual BOOL ProcessLButtonDown(UINT nFlags, CPoint point, HWND hOP);
virtual BOOL ProcessLButtonUp(UINT nFlags, CPoint point, HWND hOP);
public:
CDibMemHdc m_bkimg;
int m_nFrameId;
BOOL m_bHasSelfBkColor = FALSE;
COLORREF m_clrSelfBkgnd = RGB(255, 255, 255);
};
class CDrawUICtrl_Picture : public CDrawUIBaseCtrl
{
public:
virtual void DrawOnDc(HDC dc);
INT GetType() {
return CDrawUIBaseCtrl
::TYPE_PICTURE;
}
public:
CDibMemHdc m_bkimg;
};
typedef map<CString, CString, less_case_string> MAPKVS;
class Cbmp;
class CDrawUI
{
public:
CDrawUI();
~CDrawUI();
public:
void Unload();
void OnEraseBkgnd(HDC dc, CRect RcClient);
void OnPaint(HDC dc);
void OnMouseMove(UINT nFlags, CPoint point);
void OnLButtonDown(UINT nFlags, CPoint point);
void OnLButtonUp(UINT nFlags, CPoint point);
bool get_visible(int id);
bool set_visible(int id, bool bVisible);
bool set_text(int id, LPCWSTR lpTxt);
bool get_enable(int id);
bool set_enable(int id, bool bEnable);
bool repaint(int id, bool bErase);
public:
//L"Type=Prop|BackGround=255,255,255,255|Size=467,280|TopMost=1" RN
//L"Type=Bkgnd|CtrlType=Panel|Pos=0,28,467,280|FillColor=255,255,255,255" RN
//L"Type=Ctrl|CtrlType=Picture|Pos=8,6,88,26|BkBmp=longxiatitle|MaxTrans=255" RN
//L"Type=Ctrl|CtrlType=Button|ID=2001|Pos=440,2,464,26|FontSize=9|Text=|TextColor=255,255,255,255|BkBmp=closebtn|MaxTrans=252" RN
//L"Type=Ctrl|CtrlType=Button|ID=2000|Pos=354,240,441,269|FontSize=10|Text=保存|TextColor=255,255,255,255|BkBmp=bigbtn|MaxTrans=225|HasSelfBKGND=1|SelfBKGND=255,244,242,243|EraseInv=0" RN
//L"Type=Ctrl|CtrlType=Picture|Pos=46,48,107,100|BkBmp=notifyark|MaxTrans=230" RN
/*
Type: Prop 窗口属性 BackGround 背景色,Size 尺寸, TopMost TOPMOST风格
Bkgnd: 绘制在非客户区
Ctrl:绘制在客户区
CtrlType:控件类型 Pos:RECT坐标
Panel: FillColor填充色
Picture: 图片控件 BkBmp:资源名字 通过查询得到数据 MaxTrans:灰度上限值
Button:ID:Command命令参数 FontSize:字体大小 Text TextColor文字及颜色
HasSelfBKGND自身带有背景色 SelfBKGND自身的背景色 EraseInv 是否绘制时擦除背景(用于擦除背景)
Static:和Button差不多
*/
BOOL LoadConfig(CString strConfig, HWND hWndOp); //简易的描述语法即可
protected:
BOOL ParseLineConfig(CString strLineCfg);
BOOL ConvertLineToMap(CString strLineCfg, MAPKVS& OUT mapKVS);
void ClearCtrls();
void OperatorWindow(HWND hWndOp);
void ParseProperty(MAPKVS& IN mapKVS);
void AppendCtrls(MAPKVS& IN mapKVS);
void AppendBkgndCtrl(MAPKVS& IN mapKVS);
COLORREF GetColorFromString(CString strRgb);
BOOL Parse4ColNum(CString strColorRef, int& OUT v1, int& OUT v2, int& OUT v3, int& OUT v4);
BOOL ParsePosRegion(CString strPos, CString strRegion, int &OUT nLeft, int &OUT nTop, int &OUT nRight, int &OUT nBottom);
BOOL Parse2ColNum(CString strSize, int& OUT nW, int& OUT nH);
void AppendCtrl_Static(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv);
void AppendCtrl_Button(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv);
void AppendCtrl_Picture(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv);
void AppendCtrl_Panel(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv);
CDrawUIBaseCtrl* FindByID(int id);
void __init_ctrl_base(CDrawUIBaseCtrl* pCtrl, CRect rcPos, BOOL bEraseInv, MAPKVS& IN mapKVS);
void __init_ctrl_static(CDrawUICtrl_Static* pCtrl, MAPKVS& IN mapKVS);
void __init_ctrl_button(CDrawUICtrl_Button* pCtrl, MAPKVS& IN mapKVS);
void __init_ctrl_picture(CDrawUICtrl_Picture* pCtrl, MAPKVS& IN mapKVS);
void __init_ctrl_panel(CDrawUICtrl_Panel* pCtrl, MAPKVS& IN mapKVS);
void __append_ctrl(CDrawUIBaseCtrl* pCtrl, BOOL bCtrlOrBkgnd);
void ConvertBMPStructToDibMemDC(Cbmp& IN bmpStruct, CDibMemHdc& OUT bkimg, int maxTrans);
protected:
COLORREF m_clr_Bkgnd;
//尺寸都是dpi放缩后,读配置时进行转换
int m_nWidth;
int m_nHeight;
BOOL m_bTopMost;
vector<CDrawUIBaseCtrl*> m_vetCtrlDraw;//按照此顺序绘制即可,事件处理时是反向的
vector<CDrawUIBaseCtrl*> m_vetBkgndCtrl;
HDC m_refDc;
HWND m_refDcFromWindow;
HWND m_hOpWindow;
};
int ScalByDpi(int px);
#include "stdafx.h"
#include "DrawUI.h"
#include "ImageRes.h"
#include "cbmp.h"
#include "FontMgr.h"
#include "ImageDebugHelp.h"
#include "../utility.h"
float GetDeviceScaleFactor()
{
static float scale_factor = 1.0f;
static bool initialized = false;
if (!initialized)
{
// This value is safe to cache for the life time of the app since the user
// must logout to change the DPI setting. This value also applies to all
// screens.
HDC screen_dc = ::GetDC(NULL);
int dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX);
scale_factor = static_cast<float>(dpi_x) / 96.0f;
::ReleaseDC(NULL, screen_dc);
initialized = true;
}
return scale_factor;
}
int ScalByDpi(int px)
{
return (int)(px * GetDeviceScaleFactor());
}
#define _S(x) ScalByDpi((x)) //_S 用于常量
/********************************************************************
*
* CDrawUIBaseCtrl
*
********************************************************************/
CDrawUIBaseCtrl::CDrawUIBaseCtrl()
{
m_nID = 0;
}
CDrawUIBaseCtrl::~CDrawUIBaseCtrl()
{
}
void CDrawUIBaseCtrl::InvalidRect(HWND hWnd)
{
if (::IsWindow(hWnd))
::InvalidateRect(hWnd, &m_rcPos, m_bEraseOnInvalidRect);
}
/********************************************************************
*
* CDrawUICtrl_Panel
*
********************************************************************/
CDrawUICtrl_Panel::CDrawUICtrl_Panel()
{
}
CDrawUICtrl_Panel::~CDrawUICtrl_Panel()
{
}
void CDrawUICtrl_Panel::DrawOnDc(HDC dc)
{
HBRUSH hb = CreateSolidBrush(m_fillColor);
if (hb)
{
::FillRect(dc, &m_rcPos, hb);
::DeleteObject(hb);
}
}
/********************************************************************
*
* CDrawUICtrl_Static
*
********************************************************************/
CDrawUICtrl_Static::CDrawUICtrl_Static()
{
m_DrawType = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_WORDBREAK;
}
CDrawUICtrl_Static::~CDrawUICtrl_Static()
{
}
void CDrawUICtrl_Static::DrawOnDc(HDC dc)
{
int bkm = GetBkMode(dc);
::SetBkMode(dc, TRANSPARENT);
HFONT fnt = GetFontMgr().EasyGetFont((int)(m_fontSize * (-4.0f) / 3), 0, 0, 0, 0);
if (fnt)
{
HFONT ofnt = (HFONT)::SelectObject(dc, fnt);
COLORREF oldClr = GetTextColor(dc);
::SetTextColor(dc, m_clrTxt);
::DrawTextW(dc, m_str, -1, &m_rcPos, m_DrawType);
::SetTextColor(dc, oldClr);
::SelectObject(dc, ofnt);
}
::SetBkMode(dc, bkm);
}
/********************************************************************
*
* CDrawUICtrl_Button
*
********************************************************************/
CDrawUICtrl_Button::CDrawUICtrl_Button()
{
m_nFrameId = 0;
m_DrawType = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
}
CDrawUICtrl_Button::~CDrawUICtrl_Button()
{
}
void CDrawUICtrl_Button::DrawSelfBkgndOnEraseBkgnd(HDC dc)
{
HBRUSH hb = ::CreateSolidBrush(m_clrSelfBkgnd);
if (hb)
{
::FillRect(dc, &m_rcPos, hb);
DeleteObject(hb);
}
}
void CDrawUICtrl_Button::DrawOnDc(HDC dc)
{
int bkW = m_bkimg.GetWidth();
int l_framid = m_nFrameId;
if (!m_bEnable)
l_framid = 3;
RECT rcSrc = { l_framid*(bkW / 4), 0, 0, m_bkimg.GetHeight() };
rcSrc.right = rcSrc.left + bkW / 4;
m_bkimg.DrawSubAreaToHDC(dc, &rcSrc, m_rcPos.left, m_rcPos.top, m_rcPos.Width(), m_rcPos.Height(), 0, 0, 0, TRUE);
CDrawUICtrl_Static::DrawOnDc(dc);
}
BOOL CDrawUICtrl_Button::ProcessMouseMove(UINT nFlags, CPoint point, HWND hOP)
{
if (::PtInRect(&m_rcPos, point) && m_bEnable)
{
if (m_nFrameId == 0)
{
InvalidRect(hOP);
}
m_nFrameId = 1;
//Debug_View(L"CSuperKillerFailPage::TravelCtrl: msg == WM_MOUSEMOVE");
return TRUE;
}
else
{
if (m_nFrameId != 0)
{
m_nFrameId = 0;
InvalidRect(hOP);
}
}
return FALSE;
}
BOOL CDrawUICtrl_Button::ProcessLButtonDown(UINT nFlags, CPoint point, HWND hOP)
{
if (::PtInRect(&m_rcPos, point) && m_bEnable)
{
m_nFrameId = 2;
InvalidRect(hOP);
//Debug_View(L"CSuperKillerFailPage::TravelCtrl: msg == WM_MOUSEMOVE");
return TRUE;
}
return FALSE;
}
BOOL CDrawUICtrl_Button::ProcessLButtonUp(UINT nFlags, CPoint point, HWND hOP)
{
if (::PtInRect(&m_rcPos, point) && m_bEnable)
{
m_nFrameId = 1;
InvalidRect(hOP);
//Debug_View(L"CSuperKillerFailPage::TravelCtrl: msg == WM_MOUSEMOVE");
//Trigger
::PostMessage(hOP, WM_COMMAND, ((WORD)m_nID), 0);
return TRUE;
}
return FALSE;
}
/********************************************************************
*
* CDrawUICtrl_Picture
*
********************************************************************/
void CDrawUICtrl_Picture::DrawOnDc(HDC dc)
{
RECT rcSrc = { 0, 0, m_bkimg.GetWidth(), m_bkimg.GetHeight() };
m_bkimg.DrawSubAreaToHDC(dc, &rcSrc, m_rcPos.left, m_rcPos.top, m_rcPos.Width(), m_rcPos.Height(), 0, 0, 0, TRUE);
}
/********************************************************************
*
* CDrawUI
*
********************************************************************/
CDrawUI::CDrawUI()
{
m_refDcFromWindow = 0;
m_nWidth = 0;
m_nHeight = 0;
m_bTopMost = 0;
m_refDc = 0;
m_hOpWindow = 0;
}
CDrawUI::~CDrawUI()
{
Unload();
}
void CDrawUI::Unload()
{
ClearCtrls();
if (m_refDc && m_refDcFromWindow)
{
::ReleaseDC(m_refDcFromWindow, m_refDc);
m_refDc = 0;
m_refDcFromWindow = 0;
}
}
void CDrawUI::OnEraseBkgnd(HDC dc, CRect RcClient)
{
if (dc)
{
HBRUSH br = ::CreateSolidBrush(m_clr_Bkgnd);
if (br)
{
::FillRect(dc, &RcClient, br);
::DeleteObject(br);
}
//排除按钮的所在区域
sentry<HRGN, hgdiobj_sentry> rgnClient = ::CreateRectRgn(RcClient.left, RcClient.top, RcClient.right, RcClient.bottom);
BOOL bCreateTotalRgnFail = FALSE;
if (rgnClient.m_p)
{
for (size_t i = 0; i < m_vetCtrlDraw.size(); i++)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl && pCtrl->m_bVisible && pCtrl->GetType() == CDrawUIBaseCtrl::TYPE_BUTTON)//遍历所有按钮获得一个合并区域
{
CDrawUICtrl_Button* pButton = (CDrawUICtrl_Button*)pCtrl;
if (pButton->HasSelfBackColor())
{
RECT rcCtrl = pCtrl->m_rcPos;
sentry<HRGN, hgdiobj_sentry> rgnCtrl = CreateRectRgn(rcCtrl.left, rcCtrl.top, rcCtrl.right, rcCtrl.bottom);
if (rgnCtrl.m_p)
{
sentry<HRGN, hgdiobj_sentry> rTemp = rgnClient.detach();
rgnClient = CreateRectRgn(RcClient.left, RcClient.top, RcClient.right, RcClient.bottom);
if (rgnClient.m_p)
{
int ret = ::CombineRgn(rgnClient, rTemp, rgnCtrl, RGN_DIFF);
if (!(COMPLEXREGION == ret || ret == SIMPLEREGION))
{
bCreateTotalRgnFail = TRUE;
break;
}
}
else
{
bCreateTotalRgnFail = TRUE;
break;
}
}
else
{
bCreateTotalRgnFail = TRUE;
break;
}
}
}
}
}
//sentry<HRGN,hgdiobj_sentry> hOldClipRgn = CreateRectRgn(0,0,0,0);
if (!bCreateTotalRgnFail && rgnClient.m_p)
{
//GetClipRgn(dc, hOldClipRgn.m_p);
::SelectClipRgn(dc, rgnClient.m_p);
}
for (size_t i = 0; i < m_vetBkgndCtrl.size(); i++)
{
CDrawUIBaseCtrl* pCtrl = m_vetBkgndCtrl[i];
if (pCtrl && pCtrl->m_bVisible)
{
pCtrl->DrawOnDc(dc);
}
}
//如果按钮有设置背景色,擦除成背景色
if (!bCreateTotalRgnFail && rgnClient.m_p)
{
::SelectClipRgn(dc, NULL);
for (size_t i = 0; i < m_vetCtrlDraw.size(); i++)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl && pCtrl->m_bVisible && pCtrl->GetType() == CDrawUIBaseCtrl::TYPE_BUTTON)
{
CDrawUICtrl_Button* pButton = (CDrawUICtrl_Button*)pCtrl;
if (pButton->HasSelfBackColor())
{
pButton->DrawSelfBkgndOnEraseBkgnd(dc);
}
}
}
}
}
}
void CDrawUI::OnPaint(HDC dc)
{
for (size_t i = 0; i < m_vetCtrlDraw.size(); i++)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl && pCtrl->m_bVisible)
{
pCtrl->DrawOnDc(dc);
}
}
}
void CDrawUI::OnMouseMove(UINT nFlags, CPoint point)
{
for (int i = (int)(m_vetCtrlDraw.size()) - 1; i >= 0; i--)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl)
{
if (pCtrl->ProcessMouseMove(nFlags, point, m_hOpWindow))
{
break;
}
}
}
}
void CDrawUI::OnLButtonDown(UINT nFlags, CPoint point)
{
for (int i = (int)(m_vetCtrlDraw.size()) - 1; i >= 0; i--)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl)
{
if (pCtrl->ProcessLButtonDown(nFlags, point, m_hOpWindow))
{
break;
}
}
}
}
void CDrawUI::OnLButtonUp(UINT nFlags, CPoint point)
{
for (int i = (int)(m_vetCtrlDraw.size()) - 1; i >= 0; i--)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl)
{
if (pCtrl->ProcessLButtonUp(nFlags, point, m_hOpWindow))
{
break;
}
}
}
}
bool CDrawUI::get_visible(int id)
{
CDrawUIBaseCtrl* pCtrl = FindByID(id);
if (pCtrl)
return pCtrl->m_bVisible;
return false;
}
bool CDrawUI::set_visible(int id, bool bVisible)
{
CDrawUIBaseCtrl* pCtrl = FindByID(id);
if (pCtrl) {
pCtrl->m_bVisible = bVisible;
return true;
}
return false;
}
bool CDrawUI::set_text(int id, LPCWSTR lpTxt)
{
CDrawUIBaseCtrl* pCtrl = FindByID(id);
if (pCtrl) {
int type = pCtrl->GetType();
if (type == CDrawUIBaseCtrl::TYPE_BUTTON) {
CDrawUICtrl_Button* pSt = (CDrawUICtrl_Button*)pCtrl;
pSt->m_str = lpTxt;
return true;
}
else if (type == CDrawUIBaseCtrl::TYPE_STATIC) {
CDrawUICtrl_Static* pSt = (CDrawUICtrl_Static*)pCtrl;
pSt->m_str = lpTxt;
return true;
}
}
return false;
}
bool CDrawUI::get_enable(int id)
{
CDrawUIBaseCtrl* pCtrl = FindByID(id);
if (pCtrl)
return pCtrl->m_bEnable;
return false;
}
bool CDrawUI::set_enable(int id, bool bEnable)
{
CDrawUIBaseCtrl* pCtrl = FindByID(id);
if (pCtrl) {
pCtrl->m_bEnable = bEnable;
return true;
}
return false;
}
bool CDrawUI::repaint(int id, bool bErase)
{
CDrawUIBaseCtrl* pCtrl = FindByID(id);
if (pCtrl) {
::InvalidateRect(m_hOpWindow, &pCtrl->m_rcPos, bErase);
return true;
}
return false;
}
BOOL CDrawUI::LoadConfig(CString strConfig, HWND hWndOp)
{
ClearCtrls();
//m_refDcFromWindow = GetDesktopWindow();
m_refDcFromWindow = hWndOp;
m_hOpWindow = hWndOp;
m_refDc = GetDC(m_refDcFromWindow);
BOOL bRet = 0;
vector<CString> vetLines;
SplitString(strConfig, vetLines, L'\r');
for (size_t i = 0; i < vetLines.size(); i++)
{
if (ParseLineConfig(vetLines[i]))
{
bRet = TRUE;
}
}
if (bRet)
{
OperatorWindow(m_hOpWindow);
}
return bRet;
}
BOOL CDrawUI::ParseLineConfig(CString strLineCfg)
{
BOOL bRet = 0;
//格式:
//Type=[Prop/Ctrl/BKGND]|k1=v1|k2=v2|...
MAPKVS mapKVS;
if (ConvertLineToMap(strLineCfg, mapKVS))
{
CString strType = mapKVS[L"Type"];
if (strType.CompareNoCase(L"Prop") == 0)
{
ParseProperty(mapKVS);
bRet = TRUE;
}
else if (strType.CompareNoCase(L"Ctrl") == 0)
{
AppendCtrls(mapKVS);
bRet = TRUE;
}
else if (strType.CompareNoCase(L"BkGnd") == 0)
{
AppendBkgndCtrl(mapKVS);//背景控件只有Panel
bRet = TRUE;
}
}
return bRet;
}
BOOL CDrawUI::ConvertLineToMap(CString strLineCfg, MAPKVS& OUT mapKVS)
{
BOOL bRet = 0;
vector<CString >vetKVS;
SplitString(strLineCfg, vetKVS, L'|');
for (size_t i = 0; i < vetKVS.size(); i++)
{
vector<CString>vet2C;
SplitString(vetKVS[i], vet2C, L'=');
if (vet2C.size() == 2)
{
mapKVS[vet2C[0]] = vet2C[1];
bRet = TRUE;
}
}
return bRet;
}
void CDrawUI::ClearCtrls()
{
for (size_t i = 0; i < m_vetCtrlDraw.size(); i++)
{
CDrawUIBaseCtrl* pCtrl = m_vetCtrlDraw[i];
if (pCtrl)
{
delete pCtrl;
m_vetCtrlDraw[i] = NULL;
}
}
for (size_t i = 0; i < m_vetBkgndCtrl.size(); i++)
{
CDrawUIBaseCtrl* pCtrl = m_vetBkgndCtrl[i];
if (pCtrl)
{
delete pCtrl;
m_vetBkgndCtrl[i] = NULL;
}
}
}
void CDrawUI::OperatorWindow(HWND hWndOp)
{
//初始化之后对窗口的操作,比如设置大小 剧中等操作
if (m_bTopMost)
{
::SetWindowPos(hWndOp, HWND_TOPMOST, 0, 0, m_nWidth, m_nHeight, SWP_NOMOVE);
}
else
{
::SetWindowPos(hWndOp, NULL, 0, 0, m_nWidth, m_nHeight, SWP_NOZORDER | SWP_NOMOVE);
}
}
void CDrawUI::ParseProperty(MAPKVS& IN mapKVS)
{
CString strColorRef = mapKVS[L"BackGround"];
int a = 0;
int r = 0;
int G = 0;
int b = 0;
if (Parse4ColNum(strColorRef, a, r, G, b))
{
m_clr_Bkgnd = RGB(r, G, b);
}
CString strSize = mapKVS[L"Size"];
int nW = 0;
int nH = 0;
if (Parse2ColNum(strSize, nW, nH))
{
m_nWidth = ScalByDpi(nW);
m_nHeight = ScalByDpi(nH);
}
CString strTopMost = mapKVS[L"TopMost"];
BOOL bTopMost = !!_wtoi(strTopMost);
m_bTopMost = bTopMost;
}
void CDrawUI::AppendCtrls(MAPKVS& IN mapKVS)
{
CString strCtrlType = mapKVS[L"CtrlType"];
CString strPos = mapKVS[L"Pos"];
CString strRegion = mapKVS[L"Region"];
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
CString strEraseInvalid = mapKVS[L"EraseInv"];
BOOL bEraseOnInvalidRect = _wtoi(strEraseInvalid);
if (ParsePosRegion(strPos, strRegion, left, top, right, bottom))
{
CRect rcPos(ScalByDpi(left), ScalByDpi(top), ScalByDpi(right), ScalByDpi(bottom));
if (strCtrlType.CompareNoCase(L"Static") == 0)
{
AppendCtrl_Static(mapKVS, rcPos, TRUE, bEraseOnInvalidRect);
}
else if (strCtrlType.CompareNoCase(L"Button") == 0)
{
AppendCtrl_Button(mapKVS, rcPos, TRUE, bEraseOnInvalidRect);
}
else if (strCtrlType.CompareNoCase(L"Picture") == 0)
{
AppendCtrl_Picture(mapKVS, rcPos, TRUE, bEraseOnInvalidRect);
}
else if (strCtrlType.CompareNoCase(L"Panel") == 0)
{
AppendCtrl_Panel(mapKVS, rcPos, TRUE, bEraseOnInvalidRect);
}
}
}
void CDrawUI::AppendBkgndCtrl(MAPKVS& IN mapKVS)
{
CString strCtrlType = mapKVS[L"CtrlType"];
CString strPos = mapKVS[L"Pos"];
CString strRegion = mapKVS[L"Region"];
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
CString strEraseInvalid = mapKVS[L"EraseInv"];
BOOL bEraseOnInvalidRect = _wtoi(strEraseInvalid);
if (ParsePosRegion(strPos, strRegion, left, top, right, bottom))
{
CRect rcPos(ScalByDpi(left), ScalByDpi(top), ScalByDpi(right), ScalByDpi(bottom));
if (strCtrlType.CompareNoCase(L"Static") == 0)
{
AppendCtrl_Static(mapKVS, rcPos, FALSE, bEraseOnInvalidRect);
}
else if (strCtrlType.CompareNoCase(L"Panel") == 0)
{
AppendCtrl_Panel(mapKVS, rcPos, FALSE, bEraseOnInvalidRect);
}
else if (strCtrlType.CompareNoCase(L"Picture") == 0)
{
AppendCtrl_Picture(mapKVS, rcPos, FALSE, bEraseOnInvalidRect);
}
}
}
BOOL CDrawUI::Parse4ColNum(CString strColorRef, int& OUT v1, int& OUT v2, int& OUT v3, int& OUT v4)
{
BOOL bRet = 0;
vector<CString> vet4;
SplitString(strColorRef, vet4, L',');
if (vet4.size() == 4)
{
v1 = _wtoi(vet4[0]);
v2 = _wtoi(vet4[1]);
v3 = _wtoi(vet4[2]);
v4 = _wtoi(vet4[3]);
bRet = TRUE;
}
return bRet;
}
BOOL CDrawUI::ParsePosRegion(CString strPos, CString strRegion, int &OUT nLeft, int &OUT nTop, int &OUT nRight, int &OUT nBottom)
{
BOOL bRet = 0;
vector<CString> vet4;
bool bRegion = false;
if (strPos.GetLength()) {
SplitString(strPos, vet4, L',');
}
else {
bRegion = true;
SplitString(strRegion, vet4, L',');
}
if (vet4.size() == 4)
{
nLeft = _wtoi(vet4[0]);
nTop = _wtoi(vet4[1]);
if (bRegion)
{
int nW = _wtoi(vet4[2]);
int nH = _wtoi(vet4[3]);
nRight = nLeft + nW;
nBottom = nTop + nH;
}
else
{
nRight = _wtoi(vet4[2]);
nBottom = _wtoi(vet4[3]);
}
bRet = TRUE;
}
return bRet;
}
BOOL CDrawUI::Parse2ColNum(CString strSize, int& OUT nW, int& OUT nH)
{
BOOL bRet = 0;
vector<CString> vet2;
SplitString(strSize, vet2, L',');
if (vet2.size() == 2)
{
nW = _wtoi(vet2[0]);
nH = _wtoi(vet2[1]);
bRet = TRUE;
}
return bRet;
}
void CDrawUI::AppendCtrl_Static(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv)
{
CDrawUIBaseCtrl* pCtrl = new(nothrow) CDrawUICtrl_Static;
if (pCtrl)
{
__init_ctrl_base(pCtrl, rcPos, bEraseInv, mapKVS);
__init_ctrl_static((CDrawUICtrl_Static*)pCtrl, mapKVS);
__append_ctrl(pCtrl, bCtrlOrBkgnd);
}
}
void CDrawUI::AppendCtrl_Button(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv)
{
CDrawUIBaseCtrl* pCtrl = new(nothrow) CDrawUICtrl_Button;
if (pCtrl)
{
__init_ctrl_base(pCtrl, rcPos, bEraseInv, mapKVS);
__init_ctrl_static((CDrawUICtrl_Static*)pCtrl, mapKVS);
__init_ctrl_button((CDrawUICtrl_Button*)pCtrl, mapKVS);
__append_ctrl(pCtrl, bCtrlOrBkgnd);
}
}
void CDrawUI::AppendCtrl_Picture(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv)
{
CDrawUIBaseCtrl* pCtrl = new(nothrow) CDrawUICtrl_Picture;
if (pCtrl)
{
__init_ctrl_base(pCtrl, rcPos, bEraseInv, mapKVS);
__init_ctrl_picture((CDrawUICtrl_Picture*)pCtrl, mapKVS);
__append_ctrl(pCtrl, bCtrlOrBkgnd);
}
}
void CDrawUI::AppendCtrl_Panel(MAPKVS& IN mapKVS, CRect rcPos, BOOL bCtrlOrBkgnd, BOOL bEraseInv)
{
CDrawUIBaseCtrl* pCtrl = new(nothrow) CDrawUICtrl_Panel;
if (pCtrl)
{
__init_ctrl_base(pCtrl, rcPos, bEraseInv, mapKVS);
__init_ctrl_panel((CDrawUICtrl_Panel*)pCtrl, mapKVS);
__append_ctrl(pCtrl, bCtrlOrBkgnd);
}
}
CDrawUIBaseCtrl * CDrawUI::FindByID(int id)
{
for (size_t i = 0; i < m_vetBkgndCtrl.size(); i++) {
if (m_vetBkgndCtrl[i]->m_nID == id)
return m_vetBkgndCtrl[i];
}
for (size_t i = 0; i < m_vetCtrlDraw.size(); i++) {
if (m_vetCtrlDraw[i]->m_nID == id)
return m_vetCtrlDraw[i];
}
return 0;
}
void CDrawUI::__init_ctrl_base(CDrawUIBaseCtrl* pCtrl, CRect rcPos, BOOL bEraseInv, MAPKVS& IN mapKVS)
{
CString strID = mapKVS[L"ID"];
pCtrl->m_nID = _wtoi(strID);
MAPKVS::iterator iter = mapKVS.find(L"Visible");
if (iter != mapKVS.end())
pCtrl->m_bVisible = !!(_wtoi(iter->second));
pCtrl->m_rcPos = rcPos;
pCtrl->m_bEraseOnInvalidRect = bEraseInv;
}
COLORREF CDrawUI::GetColorFromString(CString strRgb)
{
int a, r, g, b;
if (Parse4ColNum(strRgb, a, r, g, b))
{
return RGB(r, g, b);
}
return RGB(255, 255, 255);
}
CString ParseText(CString strIn)
{
strIn.Replace(L"&enter;", L"\r\n");
return strIn;
}
void CDrawUI::__init_ctrl_static(CDrawUICtrl_Static* pCtrl, MAPKVS& IN mapKVS)
{
CString strFontSize = mapKVS[L"FontSize"];
pCtrl->m_fontSize = _wtoi(strFontSize);
pCtrl->m_str = ParseText(mapKVS[L"Text"]);
int a, r, g, b;
if (Parse4ColNum(mapKVS[L"TextColor"], a, r, g, b))
{
pCtrl->m_clrTxt = RGB(r, g, b);
}
}
void CDrawUI::__init_ctrl_button(CDrawUICtrl_Button* pCtrl, MAPKVS& IN mapKVS)
{
CString strBkBmp = mapKVS[L"BkBmp"];
const BYTE* pbImage = 0;
DWORD cbImage = 0;
CString strMaxTransparent = mapKVS[L"MaxTrans"];
int MaxTrans = _wtoi((strMaxTransparent));
if (strMaxTransparent.GetLength() == 0)
MaxTrans = 255;
CString strHasSelfBkColor = mapKVS[L"HasSelfBKGND"];
pCtrl->m_bHasSelfBkColor = _wtoi(strHasSelfBkColor);
CString strSelfBkgndClr = mapKVS[L"SelfBKGND"];
pCtrl->m_clrSelfBkgnd = GetColorFromString(strSelfBkgndClr);
if (GetImageDataByName(strBkBmp, pbImage, cbImage) && pbImage && cbImage)
{
Cbmp bmpStruct;
if (bmpStruct.loadFromBuffer((BYTE*)pbImage, cbImage))
{
int w = bmpStruct.GetWidth();
int h = bmpStruct.GetHeight();
pCtrl->m_bkimg.CreateDIBSectionBitmap(m_refDc, w, h, 0, 0, 32, 0);
if (!pCtrl->m_bkimg.IsNull())
{
ConvertBMPStructToDibMemDC(bmpStruct, pCtrl->m_bkimg, MaxTrans);
pCtrl->m_bkimg.PreMultiplyDIBAlpha();
}
}
}
}
void CDrawUI::__init_ctrl_picture(CDrawUICtrl_Picture* pCtrl, MAPKVS& IN mapKVS)
{
CString strBkBmp = mapKVS[L"BkBmp"];
const BYTE* pbImage = 0;
DWORD cbImage = 0;
CString strMaxTransparent = mapKVS[L"MaxTrans"];
int MaxTrans = _wtoi((strMaxTransparent));
if (strMaxTransparent.GetLength() == 0)
MaxTrans = 255;
if (GetImageDataByName(strBkBmp, pbImage, cbImage) && pbImage && cbImage)
{
Cbmp bmpStruct;
if (BO_OK == bmpStruct.loadFromBuffer((BYTE*)pbImage, cbImage))
{
pCtrl->m_bkimg.CreateDIBSectionBitmap(m_refDc, bmpStruct.GetWidth(), bmpStruct.GetHeight(), 0, 0, 32, 0);
if (!pCtrl->m_bkimg.IsNull())
{
ConvertBMPStructToDibMemDC(bmpStruct, pCtrl->m_bkimg, MaxTrans);
pCtrl->m_bkimg.PreMultiplyDIBAlpha();
}
}
free((void*)pbImage);
}
}
void CDrawUI::__init_ctrl_panel(CDrawUICtrl_Panel* pCtrl, MAPKVS& IN mapKVS)
{
CString strColorFill = mapKVS[L"FillColor"];
int a, r, g, b;
if (Parse4ColNum(strColorFill, a, r, g, b))
{
pCtrl->m_fillColor = RGB(r, g, b);
}
}
void CDrawUI::__append_ctrl(CDrawUIBaseCtrl* pCtrl, BOOL bCtrlOrBkgnd)
{
if (pCtrl)
{
if (bCtrlOrBkgnd)
{
m_vetCtrlDraw.push_back(pCtrl);
}
else
{
m_vetBkgndCtrl.push_back(pCtrl);
}
}
}
void CDrawUI::ConvertBMPStructToDibMemDC(Cbmp& IN bmpStruct, CDibMemHdc& OUT bkimg, int maxTrans)
{
#ifdef _DEBUG
if (0)
{
bmpStruct.Save("C:\\aa.bmp");
}
#endif
int w = bmpStruct.GetWidth();
int h = bmpStruct.GetHeight();
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
DWORD dw24 = bmpStruct.F24(i, j);
BYTE bRed = BM_Red(dw24);
BYTE bGreen = BM_Green(dw24);
BYTE bBlue = BM_Blue(dw24);
BYTE bGray = CalcGray(bRed, bGreen, bBlue);
if (bGray > maxTrans)
{
bkimg.SetPix(i, h - 1 - j, 0, 0, 0, 0);
}
else
{
bkimg.SetPix(i, h - 1 - j, 255, bBlue, bGreen, bRed);
}
}
}
#ifdef _DEBUG
if (0)
{
SaveHBITMAP(m_refDc, bkimg.GetHBitmap(), L"C:\\bb.bmp", TRUE);
}
#endif
}

2万+

被折叠的 条评论
为什么被折叠?



