编程技巧15法之二

类别:VC语言 点击:0 评论:0 推荐:
   

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;

}

 

本文地址:http://com.8s8s.com/it/it2302.htm