GDI作图,请问怎么实现作图不被覆盖

GuidoLuo0521 2018-04-28 10:29:57
请问怎么实现下面这中效果啊。

要画的步骤是这样的(背景为黑色):
1、底部的小圆最先画。
2、小圆上面部分是个整体,是两根不同宽度的方头线和四个圆组成,相交点的圆是一个黑色的圆。
在上面整体画的时候不能覆盖掉小圆。请问下怎么实现啊。最好有源代码可以作为参考的。谢谢了!
...全文
1021 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2018-05-08
  • 打赏
  • 举报
回复
打开 #ifndef TEST// OK
GuidoLuo0521 2018-05-08
  • 打赏
  • 举报
回复
我想创建单色的位图(黑白的),我将bitCount改成1后,画出来的图是空白的。
schlafenhamster 2018-05-07
  • 打赏
  • 举报
回复
为什么 bitCount改为1 ? 应该 >=8
GuidoLuo0521 2018-05-07
  • 打赏
  • 举报
回复
您好 schlafenhamster,我将位图头的bitCount改为1后,为什么会出错啦? 画出来的图是空白的。
schlafenhamster 2018-05-04
  • 打赏
  • 举报
回复

#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);
}
schlafenhamster 2018-05-04
  • 打赏
  • 举报
回复

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);
}
GuidoLuo0521 2018-05-04
  • 打赏
  • 举报
回复
请问,你们有将createDIBsection() 创建的单色位图加入DC后用GDI作图的例子么? 最好有源码的。问完这个结帖,如果好的话追加点数。
GuidoLuo0521 2018-05-04
  • 打赏
  • 举报
回复
谢谢了 schlafenhamster 因为有需要,所以选用了MM_ANISOTROPIC模式。
schlafenhamster 2018-05-03
  • 打赏
  • 举报
回复
与 双缓冲 无关 ! 不要把问题复杂化,先把 MM_TEXT 用好 !再 用 MM_ANISOTROPIC
GuidoLuo0521 2018-05-03
  • 打赏
  • 举报
回复
谢谢大家了,我最终还是用了 BitBlt(),但是出现个问题,因为之前我的DC做了相应的变换,源DC贴到目标DC上的时候始终不正确。
GuidoLuo0521 2018-05-03
  • 打赏
  • 举报
回复
能请指教下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();
zgl7903 2018-05-02
  • 打赏
  • 举报
回复
画之前选入 GetStockObject(NULL_BRUSH) 空画刷
一彤 2018-05-02
  • 打赏
  • 举报
回复
用不规则图形RGN可能行
hhhh63 2018-05-01
  • 打赏
  • 举报
回复
用多缓存技术
schlafenhamster 2018-04-29
  • 打赏
  • 举报
回复
大园 不覆盖小园的 代码 如下 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)));
schlafenhamster 2018-04-28
  • 打赏
  • 举报
回复
dc.BeginPath(); dc.Ellipse(&rcRound);// 画图 dc.EndPath(); CRgn rgn0; rgn0.CreateFromPath(&dc); dc.FillRgn(&rgn,&black_brush);// 填充
GuidoLuo0521 2018-04-28
  • 打赏
  • 举报
回复
因为有其他的要求,所以还是想用GDI来实现。就没有考虑GDI+了
赵4老师 2018-04-28
  • 打赏
  • 举报
回复
直接改用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.
GuidoLuo0521 2018-04-28
  • 打赏
  • 举报
回复
你好,我这个实现的顺序被要求死了的,所以先画面积大的好像不行。
GuidoLuo0521 2018-04-28
  • 打赏
  • 举报
回复
小圆是蓝色方框部分。
加载更多回复(12)

15,978

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧