GDI+使用PNG格式图实现对话框背景及控件全透明技术实现思想(范例有treectrl 和 editboxctrl)之二

 GDI+使用PNG格式图实现对话框背景及控件全透明技术实现思想

    以下是我用这种方法实现Editbox 的例子:

 

 

实现文件

/************************************************************

 Author:LiuGuanfa
  Version:1.1
  Date:2011.03.26
  Description:

  History:   
      <author>  <time>   <version >   <desc>
      LiuGuanfa    2011/03/20     1.0  build this moudle 
***********************************************************/

#include "stdafx.h"
#include "TprEditBoxCtrl.h"
#include "TprUiFun.h"
#include "../ItfResource/ItfResource1920/resource.h"

#include <iostream>
#include <cassert>


IMPLEMENT_DYNAMIC(CTprEditBoxCtrl, CEdit)

CTprEditBoxCtrl::CTprEditBoxCtrl()
{
 m_pLogTprEditBoxCtrl = NULL;
 m_pTprEditBoxCtrlLogFont = NULL;
 m_m_pTprEditBoxCtrlSysFont = NULL;
 m_pTprEditBoxCtrlTxtFont = NULL;
 m_ContextOfEditBox = L"";
}

CTprEditBoxCtrl::~CTprEditBoxCtrl()
{
 if(m_pTprEditBoxCtrlTxtFont!=NULL)
 {
  delete m_pTprEditBoxCtrlTxtFont;
  m_pTprEditBoxCtrlTxtFont = NULL;
 }

 if(m_pLogTprEditBoxCtrl!=NULL)
 {
  delete m_pLogTprEditBoxCtrl;
  m_pLogTprEditBoxCtrl = NULL;
 }

 if(m_pTprEditBoxCtrlLogFont!=NULL)
 {
  delete m_pTprEditBoxCtrlLogFont;
  m_pTprEditBoxCtrlLogFont = NULL;
 }

 if(m_m_pTprEditBoxCtrlSysFont!=NULL)
 {
  delete m_m_pTprEditBoxCtrlSysFont;
  m_m_pTprEditBoxCtrlSysFont = NULL;
 }
}

BEGIN_MESSAGE_MAP(CTprEditBoxCtrl, CEdit)
 ON_WM_LBUTTONUP()
 ON_WM_MOUSEMOVE()  
 ON_WM_LBUTTONDOWN()
 ON_WM_PAINT()
END_MESSAGE_MAP()

void CTprEditBoxCtrl::InitEditBox(const LOGFONT *pLogFont, const EDITBOX *pLogEditBox)
{
 int i;

 if(m_pTprEditBoxCtrlLogFont==NULL)
 {
  m_pTprEditBoxCtrlLogFont = new LOGFONT;
 }
 m_pTprEditBoxCtrlLogFont->lfHeight = pLogFont->lfHeight;
 m_pTprEditBoxCtrlLogFont->lfWidth = pLogFont->lfWidth;
 m_pTprEditBoxCtrlLogFont->lfEscapement = pLogFont->lfEscapement;
 m_pTprEditBoxCtrlLogFont->lfOrientation = pLogFont->lfOrientation;
 m_pTprEditBoxCtrlLogFont->lfWeight = pLogFont->lfWeight;
 m_pTprEditBoxCtrlLogFont->lfItalic = pLogFont->lfItalic;
 m_pTprEditBoxCtrlLogFont->lfUnderline = pLogFont->lfUnderline;
 m_pTprEditBoxCtrlLogFont->lfStrikeOut = pLogFont->lfStrikeOut;
 m_pTprEditBoxCtrlLogFont->lfCharSet = pLogFont->lfCharSet;
 m_pTprEditBoxCtrlLogFont->lfOutPrecision = pLogFont->lfOutPrecision;
 m_pTprEditBoxCtrlLogFont->lfClipPrecision = pLogFont->lfClipPrecision;
 m_pTprEditBoxCtrlLogFont->lfQuality = pLogFont->lfQuality;
 m_pTprEditBoxCtrlLogFont->lfPitchAndFamily = pLogFont->lfPitchAndFamily;
 wcscpy(m_pTprEditBoxCtrlLogFont->lfFaceName,pLogFont->lfFaceName);

 if(m_pLogTprEditBoxCtrl==NULL)
 {
  m_pLogTprEditBoxCtrl = new EDITBOX;
 }
 m_pLogTprEditBoxCtrl->dwCtrl_id = pLogEditBox->dwCtrl_id;
 m_pLogTprEditBoxCtrl->dwStyle = pLogEditBox->dwStyle;
 m_pLogTprEditBoxCtrl->dwTextLimit = pLogEditBox->dwTextLimit;
 m_pLogTprEditBoxCtrl->fPercentage = pLogEditBox->fPercentage;
 m_pLogTprEditBoxCtrl->fTopGap = pLogEditBox->fTopGap;
 m_pLogTprEditBoxCtrl->fCharGap= pLogEditBox->fCharGap;
 m_pLogTprEditBoxCtrl->iLastCharNum = pLogEditBox->iLastCharNum;
 m_pLogTprEditBoxCtrl->fCaretHight = pLogEditBox->fCaretHight;
 m_pLogTprEditBoxCtrl->fCaretOffsetX = pLogEditBox->fCaretOffsetX;
 m_pLogTprEditBoxCtrl->fCaretOffsetY = pLogEditBox->fCaretOffsetY;
 m_pLogTprEditBoxCtrl->dwStatus = pLogEditBox->dwStatus;
 for(i=0;i<3;i++)
 {
  m_pLogTprEditBoxCtrl->pImgActive[i] = pLogEditBox->pImgActive[i];
  m_pLogTprEditBoxCtrl->pImgInactive[i] = pLogEditBox->pImgInactive[i];
  m_pLogTprEditBoxCtrl->pImgGray[i] = pLogEditBox->pImgGray[i];

  if (CTprUiFun::IsImageAvail(m_pLogTprEditBoxCtrl->pImgActive[i])
   &&CTprUiFun::IsImageAvail(m_pLogTprEditBoxCtrl->pImgInactive[i])
   &&CTprUiFun::IsImageAvail(m_pLogTprEditBoxCtrl->pImgGray[i]))
  {
  }
  else
  {
   MessageBox(_T("编辑框加载图片失败!"), _T("提示"), MB_OK);
  }
 }

 //设置GDI编辑框字体
 m_m_pTprEditBoxCtrlSysFont = new CFont;
 if (!(m_m_pTprEditBoxCtrlSysFont->CreateFontIndirect(m_pTprEditBoxCtrlLogFont)))
 {
  MessageBox(_T("创建字体失败!"), _T("提示"), MB_OK);
 }
 this->SetFont(m_m_pTprEditBoxCtrlSysFont,TRUE);
 this->SetLimitText(m_pLogTprEditBoxCtrl->dwTextLimit);  

 //创建GDI+编辑框字体
 m_pTprEditBoxCtrlTxtFont = new TEXTFONT;
 if (m_pTprEditBoxCtrlTxtFont)
 {
  m_pTprEditBoxCtrlTxtFont->coColor = Color(245,0,0,0);
  m_pTprEditBoxCtrlTxtFont->pStringFormat = new StringFormat;
  m_pTprEditBoxCtrlTxtFont->pStringFormat->SetAlignment(StringAlignmentNear);
  m_pTprEditBoxCtrlTxtFont->pStringFormat->SetLineAlignment(StringAlignmentCenter);
  m_pTprEditBoxCtrlTxtFont->pStringFormat->SetTrimming(StringTrimmingEllipsisCharacter);
  
  m_pTprEditBoxCtrlLogFont->lfWidth = m_pTprEditBoxCtrlLogFont->lfWidth * m_pLogTprEditBoxCtrl->fPercentage;
  m_pTprEditBoxCtrlLogFont->lfHeight= m_pTprEditBoxCtrlLogFont->lfHeight * m_pLogTprEditBoxCtrl->fPercentage;
  m_pTprEditBoxCtrlTxtFont->pFont =new Font(this->GetDC()->m_hDC,m_pTprEditBoxCtrlLogFont);
 } 

 //开启光标闪烁定时器,尚未实现
 //this->SetTimer(8,50,(CALLBACK*)ShowCaretProc);
}

void CTprEditBoxCtrl::SetEditBoxStatus(DWORD dwStatus)
{
 if(m_pLogTprEditBoxCtrl==NULL)
 {
  m_pLogTprEditBoxCtrl = new EDITBOX;
 }
 m_pLogTprEditBoxCtrl->dwStatus = dwStatus;
}

void CTprEditBoxCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
 CWnd::OnLButtonUp(nFlags, point);
 //增加使编辑区域还原的代码,以示当前处于不可输入状态
}


void CTprEditBoxCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
 CWnd::OnLButtonDown(nFlags, point);
 //增加使编辑区域变亮的代码,以示当前处于可输入状态
}

void CTprEditBoxCtrl::DrawEditBoxCtrl(CDC* pDC)
{
 TRACE(L"\nCTprEditBoxCtrl::DrawEditBoxCtrl"); 

 CDC *pDCDst=this->GetDC();
 CDC dcSrc;
 dcSrc.CreateCompatibleDC(pDCDst);
 CRect reWindowRect;
 this->GetWindowRect(&reWindowRect);
 CBitmap cBitmap;
 cBitmap.CreateCompatibleBitmap(pDCDst, reWindowRect.Width(), reWindowRect.Height());
 dcSrc.SelectObject(&cBitmap);

 Graphics *pGraphics = new Graphics(dcSrc.m_hDC);
 if(NULL!=pGraphics)
 {
  DrawFrame(pGraphics);  
  DrawEditText(pGraphics);
  switch(m_pLogTprEditBoxCtrl->dwStatus)
  {
   case STATUS_EDITBOX_ACTIVE:
    DrawCaret(pGraphics); 
    break;
   case STATUS_EDITBOX_INACTIVE:
    break;
   case STATUS_EDITBOX_GRAY:
    break;
   default:
    break;
  }   
 }

 CRect rePrRect;
 GetParent()->GetWindowRect(&rePrRect);
 CRect reWinRect;
 this->GetWindowRect(&reWinRect);
 CRect reDlgRect;
 reDlgRect.left = reWinRect.left - rePrRect.left;
 reDlgRect.top = reWinRect.top - rePrRect.top;
 pDC->BitBlt(reDlgRect.left, reDlgRect.top, reWinRect.Width(), reWinRect.Height(), &dcSrc, 0, 0, SRCCOPY);

 delete pGraphics;
 pGraphics = NULL;
 cBitmap.DeleteObject();
 dcSrc.DeleteDC();
 this->ReleaseDC(pDCDst);
}

/**
@relief 绘制控件边框
@return BOOL 返回是否成功
@date [03/17/2011]
*/
BOOL CTprEditBoxCtrl::DrawFrame(Graphics *pGraphics)
{
 CRect reWin;
 CRect reRect;
 int nWidth;
 int nHight;
 GetClientRect(&reWin);
 Image *pImage=NULL;

 //三宫格绘制左边的图
 reRect.left = reWin.left;
 reRect.top  = reWin.top; 
 nHight = reWin.Height();
 switch(m_pLogTprEditBoxCtrl->dwStatus)
 {
  case STATUS_EDITBOX_ACTIVE:
   nWidth = m_pLogTprEditBoxCtrl->pImgActive[0]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgActive[0];
   break;
  case STATUS_EDITBOX_INACTIVE:
   nWidth = m_pLogTprEditBoxCtrl->pImgInactive[0]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgInactive[0];
   break;
  case STATUS_EDITBOX_GRAY:
   nWidth = m_pLogTprEditBoxCtrl->pImgGray[0]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgGray[0];
   break;
  default:
   break;
 }
 CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));
 

 //三宫格绘制中间的图
 int nMidWidth;
 int nCycTimes;
 int i=0;
 reRect.top  = reWin.top; 
 nHight = reWin.Height();
 switch(m_pLogTprEditBoxCtrl->dwStatus)
 {
  case STATUS_EDITBOX_ACTIVE:
   nMidWidth = reWin.right - reWin.left - m_pLogTprEditBoxCtrl->pImgActive[0]->GetWidth() - m_pLogTprEditBoxCtrl->pImgActive[2]->GetWidth();
   nCycTimes = nMidWidth/(m_pLogTprEditBoxCtrl->pImgActive[1]->GetWidth());
   nWidth = m_pLogTprEditBoxCtrl->pImgActive[1]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgActive[1];

   for(i=0;i<nCycTimes;i++)
   {
    reRect.left = reWin.left + m_pLogTprEditBoxCtrl->pImgActive[0]->GetWidth() + i*nWidth;
    CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));
   }
   reRect.left += nWidth;
   nWidth = nMidWidth - i*nWidth;
   CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));//剩下不够整块的进行缩小贴图

   break;
  case STATUS_EDITBOX_INACTIVE:
   nMidWidth = reWin.right - reWin.left - m_pLogTprEditBoxCtrl->pImgInactive[0]->GetWidth() - m_pLogTprEditBoxCtrl->pImgInactive[2]->GetWidth();
   nCycTimes = nMidWidth/(m_pLogTprEditBoxCtrl->pImgInactive[1]->GetWidth());
   nWidth = m_pLogTprEditBoxCtrl->pImgInactive[1]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgInactive[1];

   for(i=0;i<nCycTimes;i++)
   {
    reRect.left = reWin.left + m_pLogTprEditBoxCtrl->pImgInactive[0]->GetWidth() + i*nWidth;
    CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));
   }
   reRect.left += nWidth;
   nWidth = nMidWidth - i*nWidth;
   CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));//剩下不够整块的进行缩小贴图

   break;
  case STATUS_EDITBOX_GRAY:
   nMidWidth = reWin.right - reWin.left - m_pLogTprEditBoxCtrl->pImgGray[0]->GetWidth() - m_pLogTprEditBoxCtrl->pImgGray[2]->GetWidth();
   nCycTimes = nMidWidth/(m_pLogTprEditBoxCtrl->pImgGray[1]->GetWidth());
   nWidth = m_pLogTprEditBoxCtrl->pImgGray[1]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgGray[1];

   for(i=0;i<nCycTimes;i++)
   {
    reRect.left = reWin.left + m_pLogTprEditBoxCtrl->pImgGray[0]->GetWidth() + i*nWidth;
    CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));
   }
   reRect.left += nWidth;
   nWidth = nMidWidth - i*nWidth;
   CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));//剩下不够整块的进行缩小贴图

   break;
  default:
   break;
 }

 //三宫格绘制右边的图 
 reRect.top  = reWin.top; 
 nHight = reWin.Height();
 switch(m_pLogTprEditBoxCtrl->dwStatus)
 {
  case STATUS_EDITBOX_ACTIVE:
   reRect.left = reWin.right -  m_pLogTprEditBoxCtrl->pImgActive[2]->GetWidth();
   nWidth =  m_pLogTprEditBoxCtrl->pImgActive[2]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgActive[2];
   break;
  case STATUS_EDITBOX_INACTIVE:
   reRect.left = reWin.right -  m_pLogTprEditBoxCtrl->pImgInactive[2]->GetWidth();
   nWidth =  m_pLogTprEditBoxCtrl->pImgInactive[2]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgInactive[2];
   break;
  case STATUS_EDITBOX_GRAY:
   reRect.left = reWin.right -  m_pLogTprEditBoxCtrl->pImgGray[2]->GetWidth();
   nWidth =  m_pLogTprEditBoxCtrl->pImgGray[2]->GetWidth();
   pImage = m_pLogTprEditBoxCtrl->pImgGray[2];
   break;
  default:
   break;
 }
 CTprUiFun::DrawImage(pGraphics, pImage, RectF(reRect.left, reRect.top, nWidth, nHight));

 return TRUE;
}

/**
@relief 绘制控件文字,以系统编辑框的光标坐标为参照系,用化整为零的方法是DrawString绘画出的每个字符坐标尽量接近系统编辑框所绘字符的坐标,以达到仿真系统编辑框的目的
@return BOOL 返回是否成功
@date [03/25/2011]
*/
BOOL CTprEditBoxCtrl::DrawEditText(Graphics *pGraphics)
{
 int i = 0;
 int iCharactersTotalNum=0;//字符总数 
 int iCharIndexFormPos=0;//字符所在字符串的索引
 CRect reWin;
 float fGap=0;//字符平均占位宽
 char* cStrDes;
 char* cStrSrc;
 wchar_t wChar[2]={0};
 CPoint cCaretPos;

 cCaretPos = GetCaretPos();//获取光标位置
 CWnd::GetClientRect(&reWin); 
 GetWindowText(m_ContextOfEditBox);

 iCharactersTotalNum = wcslen(m_ContextOfEditBox);
 if(iCharactersTotalNum==0)
 {
  return FALSE;
 }

 iCharIndexFormPos = this->CharFromPos(cCaretPos);//获取系统光标所在位置的字符索引
 if(iCharIndexFormPos!=0)
 {
  fGap = cCaretPos.x/iCharIndexFormPos;//化整为零,计算单个字符绘画位置以让其跟看不见那个编辑框写出的字符位置基本保持一致
  
 }
 else
 {
  fGap = m_pLogTprEditBoxCtrl->fCharGap;
 }

 if(m_pLogTprEditBoxCtrl->iLastCharNum != iCharactersTotalNum)
 {
  m_pLogTprEditBoxCtrl->iLastCharNum = iCharactersTotalNum;
 }
 else if(m_pLogTprEditBoxCtrl->iLastCharNum == iCharactersTotalNum && m_pLogTprEditBoxCtrl->fCharGap != fGap)
 {
  fGap = m_pLogTprEditBoxCtrl->fCharGap;
 }

 for(i=1;i<=iCharactersTotalNum;i++)
 {
  if(m_pLogTprEditBoxCtrl->dwStyle==STYLE_EDITBOX_DEFAULT)
  {
   CopyOneWideCharacter(wChar,m_ContextOfEditBox,i);
  }
  else
  {
   wcscpy(wChar,_T("*"));
  }
  pGraphics->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);//优化字体,消除锯齿走样
  pGraphics->DrawString((CONST WCHAR*)(wChar), -1, m_pTprEditBoxCtrlTxtFont->pFont, PointF(reWin.left, cCaretPos.y + m_pLogTprEditBoxCtrl->fTopGap), m_pTprEditBoxCtrlTxtFont->pStringFormat, &SolidBrush(m_pTprEditBoxCtrlTxtFont->coColor));
  reWin.left += fGap;
 }

 m_pLogTprEditBoxCtrl->fCharGap = fGap;//保留上一次GDI+写字符的间距

 return TRUE;
}

/**
@relief 取出字符串里的任意位置的一个字符
@[inout] wStrDes 取出的那个字符 iWhichCharacter 原字符串 iWhichCharacter 取出的那个字符的索引
@return IN  OUT wchar_t * 返回的是取出的那个字符
@date [03/20/2011]
*/
wchar_t * CTprEditBoxCtrl::CopyOneWideCharacter(wchar_t * wStrDes,const wchar_t *wStrSrc,int iWhichCharacter)
{
 wchar_t *pwDes;
 const wchar_t *pwSrc;
 pwDes = wStrDes;
 pwSrc = wStrSrc;

 int iCount=1;
 assert(pwDes!=NULL||pwDes!=NULL);
 while(*pwSrc!='\0')
 {
  *pwDes=*pwSrc;
  if(iCount==iWhichCharacter)
  {
   break;
  }
  pwSrc++;
  iCount++;
 }
 return pwDes;
}


/**
@relief 绘制控件插入符
@return BOOL 返回是否成功
@date [03/19/2011]
*/
BOOL CTprEditBoxCtrl::DrawCaret(Graphics *pGraphics)
{
 CPoint cCaretPos;
 cCaretPos = GetCaretPos();
 Point Point1(cCaretPos.x + m_pLogTprEditBoxCtrl->fCaretOffsetX, cCaretPos.y + m_pLogTprEditBoxCtrl->fCaretOffsetY);
 Point Point2(cCaretPos.x + m_pLogTprEditBoxCtrl->fCaretOffsetX, cCaretPos.y + m_pLogTprEditBoxCtrl->fCaretOffsetY + m_pLogTprEditBoxCtrl->fCaretHight);
 
 Pen *myPen = new Pen(Color(255, 0, 0, 0), 1);
 pGraphics->DrawLine(myPen,Point1,Point2);
 delete myPen;


 return TRUE;
}

/**
@relief 用来触发绘画文字及插入符
@return BOOL 返回是否成功
@date [03/19/2011]
*/
void CTprEditBoxCtrl::OnPaint()
{
 ::SendMessage(GetParent()->m_hWnd, WM_PAINT, (WPARAM)0, (LPARAM)0);
}

 

转:http://hi.baidu.com/guanfaliu/blog/item/240eefc40ca84bde39db498c.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值