请问怎么实现下面这中效果啊。要画的步骤是这样的(背景为黑色):
1、底部的小圆最先画。
2、小圆上面部分是个整体,是两根不同宽度的方头线和四个圆组成,相交点的圆是一个黑色的圆。
在上面整体画的时候不能覆盖掉小圆。请问下怎么实现啊。最好有源代码可以作为参考的。谢谢了!

解决方案 »

  1.   

    4楼那个图是个整体,它由 圆1,方头线。圆2,圆3,方头线,圆4构成的。 但圆3是黑色的,其他是红色的,我就是在画那个圆3这个黑色圆的时候把下面的圆覆盖了。估计是我方法画错了。没理解到GDI   用了 beginPath  endpath  selectclippath。
      

  2.   

    直接改用GDI+画半透明的图形?
    ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/gdicpp/GDIPlus/usingGDIPlus/alphablendinglinesandfills/usingcompositingmodetocontrolalphablending.htm
    Using Compositing Mode to Control Alpha Blending --------------------------------------------------------------------------------There might be times when you want to create an off-screen bitmap that has the following characteristics: Colors have alpha values that are less than 255. 
    Colors are not alpha blended with each other as you create the bitmap. 
    When you display the finished bitmap, colors in the bitmap are alpha blended with the background colors on the display device. 
    To create such a bitmap, construct a blank Bitmap object, and then construct a Graphics object based on that bitmap. Set the compositing mode of the Graphics object to CompositingModeSourceCopy.The following example creates a Graphics object based on a Bitmap object. The code uses the Graphics object along with two semitransparent brushes (alpha = 160) to paint on the bitmap. The code fills a red ellipse and a green ellipse using the semitransparent brushes. The green ellipse overlaps the red ellipse, but the green is not blended with the red because the compositing mode of the Graphics object is set to CompositingModeSourceCopy.Next the code prepares to draw on the screen by calling BeginPaint and creating a Graphics object based on a device context. The code draws the bitmap on the screen twice: once on a white background and once on a multicolored background. The pixels in the bitmap that are part of the two ellipses have an alpha component of 160, so the ellipses are blended with the background colors on the screen.Show Example// Create a blank bitmap.
    Bitmap bitmap(180, 100);
    // Create a Graphics object that can be used to draw on the bitmap.
    Graphics bitmapGraphics(&bitmap);
    // Create a red brush and a green brush, each with an alpha value of 160.
    SolidBrush redBrush(Color(210, 255, 0, 0));
    SolidBrush greenBrush(Color(210, 0, 255, 0));
    // Set the compositing mode so that when overlapping ellipses are drawn,
    // the colors of the ellipses are not blended.
    bitmapGraphics.SetCompositingMode(CompositingModeSourceCopy);
    // Fill an ellipse using a red brush that has an alpha value of 160.
    bitmapGraphics.FillEllipse(&redBrush, 0, 0, 150, 70);
    // Fill a second ellipse using green brush that has an alpha value of 160. 
    // The green ellipse overlaps the red ellipse, but the green is not 
    // blended with the red.
    bitmapGraphics.FillEllipse(&greenBrush, 30, 30, 150, 70);
    // Prepare to draw on the screen.
    hdc = BeginPaint(hWnd, &ps);
    Graphics* pGraphics = new Graphics(hdc);
    pGraphics->SetCompositingQuality(CompositingQualityGammaCorrected);
    // Draw a multicolored background.
    SolidBrush brush(Color((ARGB)Color::Aqua));
    pGraphics->FillRectangle(&brush, 200, 0, 60, 100);
    brush.SetColor(Color((ARGB)Color::Yellow));
    pGraphics->FillRectangle(&brush, 260, 0, 60, 100);
    brush.SetColor(Color((ARGB)Color::Fuchsia));
    pGraphics->FillRectangle(&brush, 320, 0, 60, 100);
       
    // Display the bitmap on a white background.
    pGraphics->DrawImage(&bitmap, 0, 0);
    // Display the bitmap on a multicolored background.
    pGraphics->DrawImage(&bitmap, 200, 0);
    delete pGraphics;
    EndPaint(hWnd, &ps);
    The following illustration shows the output of the preceding code. Note that the ellipses are blended with the background, but they are not blended with each other.The preceding code example has the following statement:bitmapGraphics.SetCompositingMode(CompositingModeSourceCopy);
    If you want the ellipses to be blended with each other as well as with the background, change that statement to the following:bitmapGraphics.SetCompositingMode(CompositingModeSourceOver);
    The following illustration shows the output of the revised code.
    --------------------------------------------------------------------------------© 2005 Microsoft Corporation. All rights reserved. 
      

  3.   

    因为有其他的要求,所以还是想用GDI来实现。就没有考虑GDI+了
      

  4.   

    dc.BeginPath(); 
    dc.Ellipse(&rcRound);// 画图
    dc.EndPath();
    CRgn rgn0;
    rgn0.CreateFromPath(&dc);
    dc.FillRgn(&rgn,&black_brush);// 填充
      

  5.   

    //创建DC
    CClientDC pDC(this);
    bool isOK=false; CBrush bkBrush;
    CPen   pen;
    HGDIOBJ orgBrush = NULL;
    HGDIOBJ orgPen=NULL; bkBrush.CreateSolidBrush(LPC_BLACK);
    orgBrush=SelectObject(pDC,bkBrush);
    Rectangle(pDC,0,0,500,500);
    pDC.SelectObject(orgBrush); CBrush wtBrush(LPD_WRITE);  
    orgBrush = pDC.SelectObject(&wtBrush);  
    pDC.Ellipse(150-10,150-10,150+10,150+10);  // 小圆
    pDC.SelectObject(orgBrush);
    LOGBRUSH lb;
    lb.lbStyle = BS_SOLID; 
    lb.lbColor = LPD_WRITE; 
    lb.lbHatch = 0; 
    HPEN hpen;
    hpen=ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_INSIDEFRAME,
    50,
    &lb,
    0,
    NULL);
    orgPen=pDC.SelectObject(hpen); // 组合图
    pDC.BeginPath(); // 组合图的图形1
    pDC.Ellipse(50-25,300-25,50+25,300+25); // 组合图的图形2
    ::MoveToEx(pDC,50,300,NULL);
    ::LineTo(pDC,150,150); // 组合图的图形3
    //想这三个组成一个图形,然后贴在原来的那个上面,但是又不覆盖前面那个小圆
    //pDC.Ellipse(150-25,150-25,150+25,150+25);  //这个想画成黑色的,但是又不覆盖最开始画那个小圆 pDC.EndPath();
    //pDC.FillPath();
    //pDC.StrokePath();
    pDC.StrokeAndFillPath();

    pDC.SelectObject(orgPen);
    DeleteObject(hpen);
    lb.lbColor = LPC_BLACK; 
    hpen=ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_INSIDEFRAME,
    0,
    &lb,
    0,
    NULL);
    orgPen=pDC.SelectObject(hpen);
    pDC.SelectObject(bkBrush);
    //提到外面测试
    //// // 组合图的图形3
    //pDC.BeginPath();
    //pDC.Ellipse(150-25,150-25,150+25,150+25);  //这个想画成黑色的,但是又不覆盖最开始画那个小圆
    //pDC.EndPath();
    ////pDC.SelectClipPath(RGN_OR);
    //pDC.StrokeAndFillPath(); //CRgn rgn0;
    //rgn0.CreateFromPath(&pDC);
    //pDC.FillRgn(&rgn0,&bkBrush);// 填充 pDC.SelectObject(orgPen);
    pDC.SelectObject(orgBrush); DeleteObject(bkBrush);
    DeleteObject(wtBrush);
    DeleteObject(orgPen);
    DeleteObject(orgBrush);
    DeleteObject(hpen);
    DeleteObject(pen); DeleteDC(pDC);
    不好意思啊,我好像不太明白。
      

  6.   


    //颜色定义
    #define LPD_WRITE RGB(255,255,255) 
    #define LPC_BLACK RGB(0,0,0) 
    //创建DC
    CClientDC pDC(this);
    bool isOK=false;
    CBrush bkBrush;
    CPen   pen;
    HGDIOBJ orgBrush = NULL;
    HGDIOBJ orgPen=NULL; bkBrush.CreateSolidBrush(LPC_BLACK);
    orgBrush=SelectObject(pDC,bkBrush);
    Rectangle(pDC,0,0,500,500);
    pDC.SelectObject(orgBrush); CBrush wtBrush(LPD_WRITE);  
    orgBrush = pDC.SelectObject(&wtBrush);  
    pDC.Ellipse(150-10,150-10,150+10,150+10);  // 小圆
    pDC.SelectObject(orgBrush);
    LOGBRUSH lb;
    lb.lbStyle = BS_SOLID; 
    lb.lbColor = LPD_WRITE; 
    lb.lbHatch = 0; 
    HPEN hpen;
    hpen=ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_INSIDEFRAME,
    50,
    &lb,
    0,
    NULL);
    orgPen=pDC.SelectObject(hpen); // 组合图
    pDC.BeginPath(); // 组合图的图形1
    pDC.Ellipse(50-25,300-25,50+25,300+25); // 组合图的图形2
    ::MoveToEx(pDC,50,300,NULL);
    ::LineTo(pDC,150,150); // 组合图的图形3
    //想这三个组成一个图形,然后贴在原来的那个上面,但是又不覆盖前面那个小圆
    //pDC.Ellipse(150-25,150-25,150+25,150+25);  //这个想画成黑色的,但是又不覆盖最开始画那个小圆 pDC.EndPath();
    //pDC.FillPath();
    //pDC.StrokePath();
    pDC.StrokeAndFillPath();

    pDC.SelectObject(orgPen);
    DeleteObject(hpen);
    lb.lbColor = LPC_BLACK; 
    hpen=ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_INSIDEFRAME,
    0,
    &lb,
    0,
    NULL);
    orgPen=pDC.SelectObject(hpen);
    pDC.SelectObject(bkBrush);
    //提到外面测试
    //// // 组合图的图形3
    //pDC.BeginPath();
    //pDC.Ellipse(150-25,150-25,150+25,150+25);  //这个想画成黑色的,但是又不覆盖最开始画那个小圆
    //pDC.EndPath();
    ////pDC.SelectClipPath(RGN_OR);
    //pDC.StrokeAndFillPath(); //CRgn rgn0;
    //rgn0.CreateFromPath(&pDC);
    //pDC.FillRgn(&rgn0,&bkBrush);// 填充 pDC.SelectObject(orgPen);
    pDC.SelectObject(orgBrush); DeleteObject(bkBrush);
    DeleteObject(wtBrush);
    DeleteObject(orgPen);
    DeleteObject(orgBrush);
    DeleteObject(hpen);
    DeleteObject(pen); DeleteDC(pDC);
      

  7.   

    "然后贴在原来的那个上面"
    不透明 ,不能 贴 , 会 覆盖。
    要 path 里 一次 画完
      

  8.   

    分别产生 不同的 rgn ,然后 组合 CRgn::CombineRgn , rgn  最后 画一次
      

  9.   

    // 组合图的图形1
    pDC.Ellipse(50-25,300-25,50+25,300+25);
    这时 pen 已经=50, 这个 园 不能画 !
      

  10.   

    大园 不覆盖小园的 代码 如下
    CRgn rgnSmBall;
    rgnSmBall.CreateEllipticRgn(150-10,150-10,150+10,150+10);
    dc.FillRgn(&rgnSmBall,CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH))); CRgn rgnBkBall;
    rgnBkBall.CreateEllipticRgn(150-25,150-25,150+25,150+25);
    rgnBkBall.CombineRgn(&rgnBkBall,&rgnSmBall,RGN_XOR);
    dc.FillRgn(&rgnBkBall,CBrush::FromHandle((HBRUSH)GetStockObject(GRAY_BRUSH)));
      

  11.   

    用不规则图形RGN可能行
      

  12.   

    画之前选入  GetStockObject(NULL_BRUSH)  空画刷
      

  13.   

    谢谢大家了,我最终还是用了 BitBlt(),但是出现个问题,因为之前我的DC做了相应的变换,源DC贴到目标DC上的时候始终不正确。
      

  14.   

    能请指教下BitBlt在这种情况下的用法么,谢谢了
    const int nWidth=400,nHeight=400; CDC MemDC;
    CDC tpMemDC; CBitmap MemBitmap;
    CBitmap tpBitmap;
    MemDC.CreateCompatibleDC(NULL);
    MemBitmap.CreateCompatibleBitmap(&MemDC, nWidth*2, nHeight);
    tpMemDC.CreateCompatibleDC(NULL);
    nWidth-=100;nHeight-=100;
    tpBitmap.CreateCompatibleBitmap(&tpMemDC, nWidth*2, nHeight);
    tpMemDC.SetWindowOrg(100,100);
    CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
    tpMemDC.SelectObject(&tpBitmap); //设置坐标变换属性
    MemDC.SetBkMode(TRANSPARENT);
    MemDC.SetMapMode(MM_ANISOTROPIC); //映射模式设定任意比例
    tpMemDC.SetBkMode(TRANSPARENT);
    tpMemDC.SetMapMode(MM_ANISOTROPIC); //映射模式设定任意比例
    MemDC.SetWindowExt(2,1);
    MemDC.SetViewportExt(4,1); tpMemDC.SetWindowExt(2,1);
    tpMemDC.SetViewportExt(4,1); MemDC.FillSolidRect(0 ,0, nWidth, nHeight, RGB(0, 0, 0)); CBrush wtBrush(LPD_WRITE); 
    MemDC.SelectObject(wtBrush);
    MemDC.Ellipse(180,180,210,210);
    CBrush bkBrush(LPC_BLACK);  
    tpMemDC.SelectObject(wtBrush);
    tpMemDC.Ellipse(100,100,300,300);   //左上角为100,100
    tpMemDC.SelectObject(bkBrush);
    tpMemDC.Ellipse(110,110,290,290);
    // 左上角 
    BitBlt(MemDC,100,100, nWidth, nHeight,tpMemDC, 0, 0, SRCPAINT ); MemDC.SelectObject(pOldBit);
    CImage img;
    img.Attach(MemBitmap);
    //img.SetTransparentColor(LPC_BLACK);
    //存图
    CString path="F:\\1.bmp";
    img.Save(path);
    img.Detach(); MemBitmap.DeleteObject(); MemDC.DeleteDC();
      

  15.   

    与 双缓冲 无关 !
    不要把问题复杂化,先把 MM_TEXT 用好 !再 用 MM_ANISOTROPIC
      

  16.   


    #define BR_WHITE RGB(255,255,255) 
    #define BR_BLACK RGB(0,0,0)
    #define CENTER_X 195 
    #define CENTER_Y 195 
    #define R1 15 
    #define R2 90 
    #define R3 100 void CxxxxDlg::OnXXX() 
    {
    // TODO: Add your control notification handler code here
    CClientDC dc(this);
    // 2 brush
    CBrush bkBrush;
    bkBrush.CreateSolidBrush(BR_BLACK);
    CBrush wtBrush;
    wtBrush.CreateSolidBrush(BR_WHITE);
    // 
    HBRUSH orgBrush = NULL;
    // draw background
    orgBrush=(HBRUSH)SelectObject(dc,bkBrush);
    dc.Rectangle(0,0,500,500);
    // restore
    dc.SelectObject(orgBrush);
    // draw a small ball in white color
    CRgn rgnSmBall;
    rgnSmBall.CreateEllipticRgn(CENTER_X-R1,CENTER_Y-R1,CENTER_X+R1,CENTER_Y+R1);
    dc.FillRgn(&rgnSmBall,&wtBrush);
    // draw a big ball covers small ball
    CRgn rgnBgBall;
    rgnBgBall.CreateEllipticRgn(CENTER_X-R3,CENTER_Y-R3,CENTER_X+R3,CENTER_Y+R3);
    rgnBgBall.CombineRgn(&rgnBgBall,&rgnSmBall,RGN_XOR);
    dc.FillRgn(&rgnBgBall,&wtBrush);
    //  draw a mid ball also covers small ball
    CRgn rgnMdBall;
    rgnMdBall.CreateEllipticRgn(CENTER_X-R2,CENTER_Y-R2,CENTER_X+R2,CENTER_Y+R2);
    rgnMdBall.CombineRgn(&rgnMdBall,&rgnSmBall,RGN_XOR);
    dc.FillRgn(&rgnMdBall,&bkBrush);
    }
      

  17.   

    谢谢了 schlafenhamster  因为有需要,所以选用了MM_ANISOTROPIC模式。  
      

  18.   

    请问,你们有将createDIBsection() 创建的单色位图加入DC后用GDI作图的例子么?   最好有源码的。问完这个结帖,如果好的话追加点数。
      

  19.   


    void CCBlistDlg::OnButton1() 
    {
    ////////// Using CreateDIBSection is too slow !
    #if 0
    ShowWindow(SW_HIDE);
    Sleep(0);// compare with Sleep(100) HDC hScrDC = ::GetDC(NULL);
        HDC hMemDC = NULL;
        
        
        int nWidth = GetSystemMetrics(SM_CXSCREEN);
        int nHeight = GetSystemMetrics(SM_CYSCREEN); 
        
        hMemDC = ::CreateCompatibleDC(hScrDC); 
        
        BITMAPINFO bi; 
        ZeroMemory(&bi, sizeof(BITMAPINFO));
        bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bi.bmiHeader.biWidth = nWidth;
        bi.bmiHeader.biHeight = nHeight;
        bi.bmiHeader.biPlanes = 1;
        bi.bmiHeader.biBitCount = 24;
        
        HCURSOR hCursor = GetCursor();
        POINT ptCursor;
        GetCursorPos(&ptCursor);
        ICONINFO IconInfo = {0};
        if(GetIconInfo(hCursor, &IconInfo))
        {
            ptCursor.x -= IconInfo.xHotspot;
            ptCursor.y -= IconInfo.yHotspot;
            if(NULL != IconInfo.hbmMask)
                DeleteObject(IconInfo.hbmMask);
            if(NULL != IconInfo.hbmColor)
                DeleteObject(IconInfo.hbmColor);
        }
        
        BYTE *lpBitmapBits = NULL; 
        HBITMAP bitmap = ::CreateDIBSection(hMemDC, &bi, DIB_RGB_COLORS, (LPVOID*)&lpBitmapBits, NULL, 0);
        HGDIOBJ oldbmp = ::SelectObject(hMemDC, bitmap); 
        
        ::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, SRCCOPY);
        DrawIconEx(hMemDC, ptCursor.x, ptCursor.y, hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT);
        
        int rest = nWidth*3 %4 ;    BITMAPFILEHEADER bh;
        ZeroMemory(&bh, sizeof(BITMAPFILEHEADER));
        bh.bfType = 0x4d42;  //bitmap  
        bh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
        bh.bfSize = bh.bfOffBits + (nWidth*3+rest)*nHeight;
        
        CFile file;
        if(file.Open("2.bmp", CFile::modeCreate | CFile::modeWrite))
        {  
            file.Write(&bh, sizeof(BITMAPFILEHEADER));
            file.Write(&(bi.bmiHeader), sizeof(BITMAPINFOHEADER));
        //    file.Write(lpBitmapBits, 3 * nWidth * nHeight);
            file.Write(lpBitmapBits, (nWidth*3+rest)*nHeight);
            file.Close();
        }
        ::SelectObject(hMemDC, oldbmp);
    #ifndef TEST//  error !   bitmap seperated with lpBitmapBits ?
    OpenClipboard();
    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP,bitmap);
    CloseClipboard();
    #endif
        ::DeleteObject(bitmap);
        ::DeleteObject(hMemDC);
        ::ReleaseDC(NULL, hScrDC);
    ShowWindow(SW_SHOW);
    ////////// Using CreateCompatibleBitmap is more fast !
    #else
    ShowWindow(SW_HIDE);
    Sleep(100);    CDC *pDC;
        pDC = GetDesktopWindow()->GetDC();
        if(pDC == NULL) return;
        int BitPerPixel = pDC->GetDeviceCaps(BITSPIXEL);
        int Width = pDC->GetDeviceCaps(HORZRES);
        int Height = pDC->GetDeviceCaps(VERTRES);
        
        CDC memDC;
        if(memDC.CreateCompatibleDC(pDC) == 0) return;
        
        CBitmap memBitmap, *oldmemBitmap;
        if(memBitmap.CreateCompatibleBitmap(pDC, Width, Height) == NULL) return;
    #ifndef TEST//  OK
    OpenClipboard();
    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP,memBitmap);
    CloseClipboard();
    #endif
        oldmemBitmap = memDC.SelectObject(&memBitmap);    if(memDC.BitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY) == 0) return;
        
        BITMAP bmp;
        memBitmap.GetBitmap(&bmp);
        //计算24位图像每行的字节数
        int BytesPerLine = 3 * bmp.bmWidth;
        while(BytesPerLine % 4 != 0)
            BytesPerLine ++;
        
        BITMAPINFOHEADER bih = {0};//位图信息头
        bih.biBitCount = 24;//每个像素字节大小
        bih.biCompression = BI_RGB;
        bih.biHeight = bmp.bmHeight;//高度
        bih.biPlanes = 1;
        bih.biSize = sizeof(BITMAPINFOHEADER);
        bih.biSizeImage = BytesPerLine * bmp.bmHeight;//图像数据大小
        bih.biWidth = bmp.bmWidth;//宽度
        
        BITMAPFILEHEADER bfh = {0};//位图文件头
        bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量
        bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;//文件总的大小
        bfh.bfType = (WORD)0x4d42;
        
        FILE *fp = fopen("xxxx.bmp", "w+b");
        
        fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头
        
        fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头
        
        byte *p = new byte[bih.biSizeImage];
        
        //获取当前32位图像数据
        GetDIBits(memDC.m_hDC,
            (HBITMAP) memBitmap.m_hObject,
            0,
            Height,
            p,
            (LPBITMAPINFO) &bih,
            DIB_RGB_COLORS);
        
        //只取rgb值,存入文件
        byte b = 0;//用于填充
        for(int i = 0 ; i < bmp.bmWidth * bmp.bmHeight ; i ++)
        {
            //32位位图图像的格式为:Blue, Green, Red, Alpha
            fwrite(&(p[i * 3]), 1, 3, fp);
            if(i % bmp.bmWidth == bmp.bmWidth - 1)//填充字节
            {
                for(int k = 0 ; k < (BytesPerLine - bmp.bmWidth * 3) ; k ++)
                    fwrite(&b, sizeof(byte), 1, fp);
            }
        }
        
        delete [] p;
        
        fclose(fp);
        memDC.SelectObject(oldmemBitmap);
    //
    ShowWindow(SW_SHOW);
    #endif
    AfxMessageBox("xxxx.bmp Created!");
    // ShowWindow(SW_MINIMIZE);
    }
      

  20.   

    您好  schlafenhamster,我将位图头的bitCount改为1后,为什么会出错啦? 画出来的图是空白的。
      

  21.   

    为什么 bitCount改为1 ? 应该 >=8
      

  22.   

    我想创建单色的位图(黑白的),我将bitCount改成1后,画出来的图是空白的。
      

  23.   

    打开 #ifndef TEST//  OK