1. 如何在指定矩形框内水平/垂直显示多行文字
///////////////////////////////////////////////////////
//说明:
// 在矩形框中水平或垂直显示多行文字,jingzhou xu.
// lMode: 排列方式,0:水平方式; 1:垂直对齐
// lHori: 水平对齐方式, 0:左对齐; 1:居中; 2:右对齐; 3:自定义
// lVert: 垂直对齐方式, 0:顶对齐; 1:居中; 2:底对齐; 3:自定义
///////////////////////////////////////////////////////
CRect DrawTitleInRect(CDC *pDC, CString szString, LPRECT lpRect, long lMode, long lHori, long lVert)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int tmpWidth=tm.tmAveCharWidth, tmpHeight=tm.tmHeight;
CRect rcInner(lpRect);
if(lMode==0)
{
rcInner.left+=tmpWidth;
rcInner.right-=tmpWidth;
rcInner.top-=tmpWidth;
rcInner.bottom+=tmpWidth;
}
if(lMode==1)
{
rcInner.left+=tmpWidth;
rcInner.right=rcInner.left+tmpWidth;
rcInner.top-=tmpWidth;
rcInner.bottom+=tmpWidth;
}
pDC->DrawText(szString, rcInner,DT_CALCRECT);
switch(lHori)
{
case 0:
break;
case 1:
{
long xOutCent=(lpRect->right+lpRect->left)/2;
long xInnCent=(rcInner.right+rcInner.left)/2;
rcInner.left+=(xOutCent-xInnCent);
rcInner.right+=(xOutCent-xInnCent);
}
break;
case 2:
{
long lInWidth=rcInner.right-rcInner.left;
rcInner.right=lpRect->right-tmpWidth;
rcInner.left=rcInner.right-lInWidth;
}
break;
default:
break;
}
switch(lVert)
{
case 0:
break;
case 1:
{
long yOutCent=(lpRect->bottom+lpRect->top)/2;
long yInnCent=(rcInner.bottom+rcInner.top)/2;
rcInner.top-=(yInnCent-yOutCent);
rcInner.bottom-=(yInnCent-yOutCent);
}
break;
case 2:
{
long lInHeigh=rcInner.top-rcInner.bottom;
rcInner.bottom=lpRect->bottom+tmpWidth;
rcInner.top=rcInner.bottom+lInHeigh;
}
break;
default:
break;
}
//---------------------------------------------------------------------------------------------
//功能:根据新、老矩形,重新计算行数,使文字多行显示,jingzhou xu
//---------------------------------------------------------------------------------------------
//一行中最大字符数
int nMaxLineChar = abs(lpRect->right - lpRect->left) / tmpWidth ;
//记录当前行的宽度
short theLineLength=0;
//记录当前行中汉字字节数,以防止将一半汉字分为两行
unsigned short halfChinese=0;
for(int i=0; i<=szString.GetLength()-1; i++)
{
if(((unsigned char)szString.GetAt(i) == 0x0d) && ((unsigned char)szString.GetAt(i+1) == 0x0a))
theLineLength=0;
//大于0xa1的字节为汉字字节
if((unsigned char)szString.GetAt(i) >= 0xA1)
halfChinese++;
theLineLength++;
//如果行宽大于每行最大宽度,进行特殊处理
if(theLineLength > nMaxLineChar)
{
//防止将一个汉字分为两行,回溯
if(halfChinese%2)
{
szString.Insert(i,(unsigned char)0x0a);
szString.Insert(i,(unsigned char)0x0d);
}
else
{
szString.Insert(i-1,(unsigned char)0x0a);
szString.Insert(i-1,(unsigned char)0x0d);
}
theLineLength = 0;
}
}
//重新计算矩形边界范围
// int tmpLine = int(abs(szString.GetLength()*tmpWidth / abs(lpRect->right - lpRect->left)-0.5));
// tmpLine += (szString.GetLength()*tmpWidth % abs(lpRect->right - lpRect->left))? 1 : 0;
// if(tmpLine == 0)
// tmpLine = 1;
if(rcInner.bottom > lpRect->bottom)
rcInner.bottom = lpRect->bottom;
if(rcInner.top < lpRect->top)
rcInner.top = lpRect->top;
//---------------------------------------------------------------------------------------------
if(lHori==0)
pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_LEFT);
else if(lHori==1)
pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_CENTER);
else if(lHori==2)
pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_RIGHT);
return rcInner;
}
2. 如何在指定矩形中旋转显示文字
///////////////////////////////////////////////////////
//说明:
// 在矩形框中旋转方式显示文字,jingzhou xu
//参数:
// pDC: DC指针
// str: 显示文字
// rect: 显示范围
// angle: 旋转角度
// nOptions: ExtTextOut()中相应设置<ETO_CLIPPED 和 ETO_OPAQUE>
///////////////////////////////////////////////////////
void DrawRotatedText(CDC* pDC, const CString str, CRect rect,
double angle, UINT nOptions)
{
//按比例转换角度值
double pi = 3.141592654;
double radian = pi * 2 / 360 * angle;
//获取显示文字中心点
CSize TextSize = pDC->GetTextExtent(str);
CPoint center;
center.x = TextSize.cx / 2;
center.y = TextSize.cy / 2;
//计算显示文字新的中心点
CPoint rcenter;
rcenter.x = long(cos(radian) * center.x - sin(radian) * center.y);
rcenter.y = long(sin(radian) * center.x + cos(radian) * center.y);
//绘制文字
pDC->SetTextAlign(TA_BASELINE);
pDC->SetBkMode(TRANSPARENT);
pDC->ExtTextOut(rect.left + rect.Width() / 2 - rcenter.x,
rect.top + rect.Height() / 2 + rcenter.y,
nOptions, rect, str, NULL);
}
3. 如何将32 x 32像素图标转换为16 x 16像素值的图标
HICON Convert32x32IconTo16x16(HICON h32x32Icon)
{
HDC hMainDC, hMemDC1, hMemDC2;
HICON h16x16Icon;
BITMAP bmp;
HBITMAP hOldBmp1, hOldBmp2;
ICONINFO IconInfo32x32, IconInfo16x16;
GetIconInfo(h32x32Icon, &IconInfo32x32);
hMainDC = ::GetDC(m_hWnd);
hMemDC1 = CreateCompatibleDC(hMainDC);
hMemDC2 = CreateCompatibleDC(hMainDC);
GetObject(IconInfo32x32.hbmColor, sizeof(BITMAP), &bmp);
IconInfo16x16.hbmColor = CreateBitmap( 16, 16,
bmp.bmPlanes,
bmp.bmBitsPixel,
NULL);
hOldBmp1 = (HBITMAP) SelectObject( hMemDC1,
IconInfo32x32.hbmColor);
hOldBmp2 = (HBITMAP) SelectObject( hMemDC2,
IconInfo16x16.hbmColor);
StretchBlt(hMemDC2,
0, 0,
16, 16,
hMemDC1,
0, 0,
32, 32,
SRCCOPY
);
GetObject(IconInfo32x32.hbmMask, sizeof(BITMAP), &bmp);
IconInfo16x16.hbmMask = CreateBitmap( 16, 16,
bmp.bmPlanes,
bmp.bmBitsPixel,
NULL);
SelectObject(hMemDC1, IconInfo32x32.hbmMask);
SelectObject(hMemDC2, IconInfo16x16.hbmMask);
StretchBlt(hMemDC2,
0, 0,
16, 16,
hMemDC1,
0, 0,
32, 32,
SRCCOPY
);
SelectObject(hMemDC1, hOldBmp1);
SelectObject(hMemDC2, hOldBmp2);
IconInfo16x16.fIcon = TRUE;
h16x16Icon = CreateIconIndirect(&IconInfo16x16);
DeleteObject(IconInfo32x32.hbmColor);
DeleteObject(IconInfo16x16.hbmColor);
DeleteObject(IconInfo32x32.hbmMask);
DeleteObject(IconInfo16x16.hbmMask);
DeleteDC(hMemDC1);
DeleteDC(hMemDC2);
::ReleaseDC(m_hWnd, hMainDC);
return h16x16Icon;
}
4. 如何建立一个灰度级图标
HICON CreateGrayscaleIcon(HICON hIcon)
{
HICON hGrayIcon = NULL;
HDC hMainDC = NULL,
hMemDC1 = NULL,
hMemDC2 = NULL;
BITMAP bmp;
HBITMAP hOldBmp1 = NULL,
hOldBmp2 = NULL;
ICONINFO csII, csGrayII;
BOOL
bRetValue = FALSE;
bRetValue = ::GetIconInfo(hIcon, &csII);
if (bRetValue == FALSE) return NULL;
hMainDC = ::GetDC(m_hWnd);
hMemDC1 = ::CreateCompatibleDC(hMainDC);
hMemDC2 = ::CreateCompatibleDC(hMainDC);
if (hMainDC == NULL ||
hMemDC1 == NULL ||
hMemDC2 == NULL)
return NULL;
if (::GetObject(csII.hbmColor,
sizeof(BITMAP), &
amp;bmp))
{
csGrayII.hbmColor =
::CreateBitmap(csII.xHotspot*2,
csII.yHotspot*2,
bmp.bmPlanes,
bmp.bmBitsPixel,
NULL);
if (csGrayII.hbmColor)
{
hOldBmp1 =
(HBITMAP)::SelectObject(hMemDC1,
csII.hbmColor);
hOldBmp2 =
(HBITMAP)::SelectObject(hMemDC2,
csGrayII.hbmColor);
::BitBlt(hMemDC2, 0, 0, csII.xHotspot*2,
csII.yHotspot*2, hMemDC1, 0, 0,
SRCCOPY);
DWORD dwLoopY = 0, dwLoopX = 0;
COLORREF crPixel = 0;
BYTE byNewPixel = 0;
for (dwLoopY = 0; dwLoopY < csII.yHotspot*2; dwLoopY++)
{
for (dwLoopX = 0; dwLoopX < csII.xHotspot*2; dwLoopX++)
{
crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);
byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) +
(GetGValue(crPixel) * 0.587) +
(GetBValue(crPixel) * 0.114));
if (crPixel) ::SetPixel(hMemDC2,
dwLoopX,
dwLoopY,
RGB(byNewPixel,
byNewPixel,
byNewPixel));
} // for
} // for
::SelectObject(hMemDC1, hOldBmp1);
::SelectObject(hMemDC2, hOldBmp2);
csGrayII.hbmMask = csII.hbmMask;
csGrayII.fIcon = TRUE;
hGrayIcon = ::CreateIconIndirect(&csGrayII);
} // if
::DeleteObject(csGrayII.hbmColor);
//::DeleteObject(csGrayII.hbmMask);
} // if
::DeleteObject(csII.hbmColor);
::DeleteObject(csII.hbmMask);
::DeleteDC(hMemDC1);
::DeleteDC(hMemDC2);
::ReleaseDC(m_hWnd, hMainDC);
return hGrayIcon;
}
5. 如何按指定角度旋转显示内存位图(用法和BitBlt类似)
void RotBlt(HDC destDC, int srcx1, int srcy1, int srcx2, int srcy2,
HDC srcDC , int destx1, int desty1 ,int thetaInDegrees ,DWORD mode)
{
double theta = thetaInDegrees * (3.14159/180);
//原图像原始大小
int width = srcx2 - srcx1;
int height = srcy2 - srcy1;
//原图像中心点
int centreX = int(float(srcx2 + srcx1)/2);
int centreY = int(float(srcy2 + srcy1)/2);
//判断出图像可以沿任意方向旋转的矩形框
if(width>height)height = width;
else
width = height;
HDC memDC = CreateCompatibleDC(destDC);
HBITMAP memBmp = CreateCompatibleBitmap(destDC, width, height);
HBITMAP obmp = (HBITMAP) SelectObject(memDC, memBmp);
//内存DC新在中心点
int newCentre = int(float(width)/2);
//开始旋转
for(int x = srcx1; x<=srcx2; x++)
for(int y = srcy1; y<=srcy2; y++)
{
COLORREF col = GetPixel(srcDC,x,y);
int newX = int((x-centreX)*sin(theta)+(y-centreY)*cos(theta));
int newY = int((x-centreX)*cos(theta)-(y-centreY)*sin(theta));
SetPixel(memDC , newX + newCentre, newY + newCentre, col);
}
//复制到目标DC上
BitBlt(destDC, destx1, desty1, width, height, memDC, 0,0,mode);
//释放内存
SelectObject(memDC, obmp);
DeleteDC(memDC);
DeleteObject(memBmp);
}
用法:
RotBlt(dc, 0,0,150,150,memDC,200,0, 45, SRCCOPY);
6. 如何将指定的窗体,以位图形式复制到系统剪切板上
void CScreenSnapDlg::toClipboard_Bio(CWnd * wnd, BOOL FullWnd)
{
CDC *dc;
if(FullWnd)
{ /* 抓取整个窗口 */
dc = new CWindowDC(wnd);
} /* 抓取整个窗口 */
else
{ /* 仅抓取客户区时 */
dc = new CClientDC(wnd);
} /* 仅抓取客户区时 */
CDC memDC;
memDC.CreateCompatibleDC(dc);
CBitmap bm;
CRect r;
if(FullWnd)
wnd->GetWindowRect(&r);
else
wnd->GetClientRect(&r);
CString s;
wnd->GetWindowText(s);
CSize sz(r.Width(), r.Height());
bm.CreateCompatibleBitmap(dc, sz.cx, sz.cy);
CBitmap * oldbm = memDC.SelectObject(&bm);
memDC.BitBlt(0, 0, sz.cx, sz.cy, dc, 0, 0, SRCCOPY);
//直接调用OpenClipboard(),而不用wnd->GetParent()->OpenClipboard();
wnd->OpenClipboard();
::EmptyClipboard();
::SetClipboardData(CF_BITMAP, bm.m_hObject);
CloseClipboard();
//恢复原始环境
memDC.SelectObject(oldbm);
bm.Detach();
delete dc;
}