Win32 位图直接绘制

这篇具有很好参考价值的文章主要介绍了Win32 位图直接绘制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

CBitmapDraw.h

#pragma once
#include <wtypes.h>
#include <type_traits>

#define COLOR_RGB_TO_BGR(_rgb) ( (_rgb & 0xFF) << 16)  |  (_rgb & 0x00FF00)  | ( (_rgb >> 16) & 0xFF)

typedef struct _BITMAP_DRAW_DATA
{
    BITMAPINFO binfo = { 0 };       //位图原始信息
    HBITMAP hBitmap = nullptr;      //位图句柄
    LONG width = 0;                 //位图宽度
    LONG height = 0;                //位图高度
    LPDWORD lpBits = nullptr;       //位图全部数据缓冲 宽度 * 高度 * sizeof(DWORD)
    LPDWORD lpLineBuf = nullptr;    //位图单行数据缓冲 宽度 * sizeof(DWORD)

    _BITMAP_DRAW_DATA(const _BITMAP_DRAW_DATA&) = delete;

    _BITMAP_DRAW_DATA()
    {
        ZeroMemory(this, sizeof(_BITMAP_DRAW_DATA));
    }

    ~_BITMAP_DRAW_DATA()
    {
        this->Release();
    }

    _BITMAP_DRAW_DATA(_BITMAP_DRAW_DATA&& r) noexcept
    {
        this->binfo = r.binfo;
        this->hBitmap = r.hBitmap;
        this->width = r.width;
        this->height = r.height;
        this->lpBits = r.lpBits;
        this->lpLineBuf = r.lpLineBuf;
        
        *this = std::move(r);
    }

    _BITMAP_DRAW_DATA operator = (const _BITMAP_DRAW_DATA&) = delete;
    _BITMAP_DRAW_DATA& operator = (_BITMAP_DRAW_DATA&& r) noexcept
    {
        this->binfo = r.binfo;
        this->hBitmap = r.hBitmap;
        this->width = r.width;
        this->height = r.height;
        this->lpBits = r.lpBits;
        this->lpLineBuf = r.lpLineBuf;

        r.lpBits = nullptr;
        r.lpLineBuf = nullptr;
        r.hBitmap = nullptr;

        return *this;
    }

    void Release()
    {
        if (nullptr != lpBits)
        {
            delete[] lpBits;
            lpBits = nullptr;
        }
        if (nullptr != lpLineBuf)
        {
            delete[] lpLineBuf;
            lpLineBuf = nullptr;
        }

        ZeroMemory(this, sizeof(_BITMAP_DRAW_DATA));
    }
}BITMAP_DRAW_DATA, * PBITMAP_DRAW_DATA;

class CBitmapDraw
{
public:

    CBitmapDraw(HDC hdc);

    ~CBitmapDraw();

    //获取位图宽度
    LONG GetWidth() const;

    //获取位图高度
    LONG GetHeight() const;

    //获取位图左上坐标
    POINT GetLeftTop() const;

    //获取位图右下坐标
    POINT GetRightBottom() const;

    //准备绘制
    bool BeginDraw();

    //结束绘制
    bool EndDraw();

    //绘制矩形边框
    void DrawRect(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode = false);

    //绘制线条
    void DrawLine(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode = false);

    //绘制圆形
    void DrawCircle(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode = false);

    //绘制网格
    void DrawGrid(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, LONG xCount = 1, LONG yCount = 1, bool bDotMode = false);

    //填充网格
    void FillGrid(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, LONG xCount = 1, LONG yCount = 1, POINT pt = { 0, 0 });

    //填充矩形区域
    void FillRect(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor);

    //限制坐标
    void LimitPiont(POINT& ptLT, POINT& ptRB);

public:

    //调节起始坐标点, 确保起始点坐标在终止坐标的左上方
    static void AdjustPiont(POINT& ptLT, POINT& ptRB);

    //网格命中测试
    static bool GridHitTest(POINT ptLT, POINT ptRB, DWORD xCount, DWORD yCount, POINT ptCheck, POINT& ptOut);

private:

    BITMAP_DRAW_DATA m_DrawData;    //绘制数据
    HDC m_hDC = nullptr;            //DC句柄
};

CBitmapDraw.cpp

#include "CBitmapDraw.h"
#include <new>
#include <memory.h>
#include <math.h>

#pragma intrinsic(memcpy)

CBitmapDraw::CBitmapDraw(HDC hdc)
{
    if (nullptr == hdc)
    {
        return;
    }

    do
    {
        m_hDC = hdc;
        int nScanlines = 0;

        //获取位图句柄
        m_DrawData.hBitmap = (HBITMAP)::GetCurrentObject(hdc, OBJ_BITMAP);
        if (nullptr == m_DrawData.hBitmap)
        {
            break;
        }

        //获取位图信息
        m_DrawData.binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        nScanlines = ::GetDIBits(hdc, m_DrawData.hBitmap, 0, 0, nullptr, &m_DrawData.binfo, DIB_RGB_COLORS);
        if (0 == nScanlines)
        {
            break;
        }

        m_DrawData.binfo.bmiHeader.biPlanes = 1;
        m_DrawData.binfo.bmiHeader.biBitCount = 32;

        //取得位图尺寸, 分配位图数据缓冲
        m_DrawData.width = m_DrawData.binfo.bmiHeader.biWidth;
        m_DrawData.height = ::abs(m_DrawData.binfo.bmiHeader.biHeight);

        //高度方向矫正
        m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;
        if (m_DrawData.binfo.bmiHeader.biHeight > 0)
        {
            m_DrawData.binfo.bmiHeader.biHeight = 0 - m_DrawData.binfo.bmiHeader.biHeight;
        }

        m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;

    } while (false);
}

CBitmapDraw::~CBitmapDraw()
{
    m_DrawData.Release();
}

LONG CBitmapDraw::GetWidth() const
{
    return m_DrawData.width;
}

LONG CBitmapDraw::GetHeight() const
{
    return m_DrawData.height;
}

POINT CBitmapDraw::GetLeftTop() const
{
    return {0, 0};
}

POINT CBitmapDraw::GetRightBottom() const
{
    return { m_DrawData.width - 1, m_DrawData.height - 1 };
}

bool CBitmapDraw::BeginDraw()
{
    if (nullptr == m_hDC)
    {
        return false;
    }

    bool bRes = false;
    do
    {
        m_DrawData.Release();

        //获取位图句柄
        m_DrawData.hBitmap = (HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP);
        if (nullptr == m_DrawData.hBitmap)
        {
            break;
        }

        //获取位图信息
        m_DrawData.binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        if (0 == ::GetDIBits(m_hDC, m_DrawData.hBitmap, 0, 0, nullptr, &m_DrawData.binfo, DIB_RGB_COLORS))
        {
            break;
        }

        m_DrawData.binfo.bmiHeader.biPlanes = 1;
        m_DrawData.binfo.bmiHeader.biBitCount = 32;

        //取得位图尺寸, 分配位图数据缓冲
        m_DrawData.width = m_DrawData.binfo.bmiHeader.biWidth;
        m_DrawData.height = ::abs(m_DrawData.binfo.bmiHeader.biHeight);
        m_DrawData.lpBits = new (std::nothrow) DWORD[m_DrawData.width * m_DrawData.height];
        if (nullptr == m_DrawData.lpBits)
        {
            break;
        }

        memset(m_DrawData.lpBits, 0, (m_DrawData.width * m_DrawData.height) * sizeof(DWORD));

        //分配单行缓冲
        m_DrawData.lpLineBuf = new (std::nothrow) DWORD[m_DrawData.width];
        if (nullptr == m_DrawData.lpLineBuf)
        {
            break;
        }
        memset(m_DrawData.lpLineBuf, 0, m_DrawData.width * sizeof(DWORD));

        //高度方向矫正
        m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;
        if (m_DrawData.binfo.bmiHeader.biHeight > 0)
        {
            m_DrawData.binfo.bmiHeader.biHeight = 0 - m_DrawData.binfo.bmiHeader.biHeight;
        }

        //取得位图数据
        int nScanlines = ::GetDIBits(m_hDC, m_DrawData.hBitmap, 0, m_DrawData.height, m_DrawData.lpBits, &m_DrawData.binfo, DIB_RGB_COLORS);
        if (0 == nScanlines)
        {
            break;
        }

        m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;

        bRes = true;

    } while (false);

    return bRes;
}

bool CBitmapDraw::EndDraw()
{
    if (nullptr == m_DrawData.lpBits)
    {
        return false;
    }

    if (m_DrawData.lpBits)
    {
        //设置兼容位图中的像素。
        int nScanlines = ::SetDIBits(m_hDC, m_DrawData.hBitmap, 0, m_DrawData.height, m_DrawData.lpBits, &m_DrawData.binfo, DIB_RGB_COLORS);
        if (0 != nScanlines)
        {
            return true;
        }
    }

    return false;
}

void CBitmapDraw::LimitPiont(POINT& ptLT, POINT& ptRB)
{
    LONG nWidth = m_DrawData.width;
    LONG nHeight = m_DrawData.height;

    //起点坐标限制
    if (ptLT.x < 0) ptLT.x = 0;
    if (ptLT.y < 0) ptLT.y = 0;
    if (ptLT.x > nWidth - 1) ptLT.x = nWidth - 1;
    if (ptLT.y > nHeight - 1) ptLT.y = nHeight - 1;

    //终点坐标限制
    if (ptRB.x < 0) ptRB.x = 0;
    if (ptRB.y < 0) ptRB.y = 0;
    if (ptRB.x > nWidth - 1) ptRB.x = nWidth - 1;
    if (ptRB.y > nHeight - 1) ptRB.y = nHeight - 1;
}

void CBitmapDraw::AdjustPiont(POINT& ptLT, POINT& ptRB)
{
    LONG x0 = ptLT.x < ptRB.x ? ptLT.x : ptRB.x;
    LONG y0 = ptLT.y < ptRB.y ? ptLT.y : ptRB.y;
    LONG x1 = ptLT.x > ptRB.x ? ptLT.x : ptRB.x;
    LONG y1 = ptLT.y > ptRB.y ? ptLT.y : ptRB.y;
    ptLT = { x0 , y0 };
    ptRB = { x1 , y1 };
}
bool CBitmapDraw::GridHitTest(POINT ptLT, POINT ptRB, DWORD xCount, DWORD yCount, POINT ptCheck, POINT& ptOut)
{
    //调节限制位置
    (void)AdjustPiont(ptLT, ptRB);

    //计算绘制区域宽高, 单行线条字节长度
    int nDrawWidth = ptRB.x - ptLT.x + 1;
    int nDrawHeight = ptRB.y - ptLT.y + 1;

    //格子数量限定
    if (xCount < 1) xCount = 1;
    if (yCount < 1) yCount = 1;

    //计算格子宽度
    int xGridWidth = nDrawWidth / xCount;
    int yGridHeight = nDrawHeight / yCount;

    //检查是否位于指定区域内(包含边框)
    if (!((ptCheck.x >= ptLT.x && ptCheck.x <= ptRB.x) && (ptCheck.y >= ptLT.y && ptCheck.y <= ptRB.y)))
    {
        return false;
    }

    ptOut.x = (ptCheck.x - ptLT.x) / xGridWidth;
    ptOut.y = (ptCheck.y - ptLT.y) / yGridHeight;

    return true;
}

void CBitmapDraw::DrawGrid(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, LONG xCount/* = 1*/, LONG yCount/* = 1*/, bool bDotMode/* = false*/)
{
    dwColor = COLOR_RGB_TO_BGR(dwColor);
    if (nullptr == m_DrawData.lpBits)
    {
        return;
    }

    LPDWORD lpBits = m_DrawData.lpBits;
    LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    LONG nWidth = m_DrawData.width;
    LONG nHeight = m_DrawData.height;

    //调节限制位置
    (void)AdjustPiont(ptSrcLT, ptSrcRB);

    //填充单行颜色
    if (lpLineBuf[0] != dwColor)
    {
        LPDWORD lpBuf = lpLineBuf;
        for (int i = 0; i < nWidth; i++)
        {
            *lpBuf++ = dwColor;
        }
    }

    //计算绘制区域宽高, 单行线条字节长度
    int nDrawWidth = ptSrcRB.x - ptSrcLT.x + 1;
    int nDrawHeight = ptSrcRB.y - ptSrcLT.y + 1;

    //格子数量限定
    if (xCount < 1) xCount = 1;
    if (yCount < 1) yCount = 1;

    //计算格子宽度
    int xGridSize = nDrawWidth / xCount;
    int yGridSize = nDrawHeight / yCount;

    LPDWORD lpData = nullptr;

    LONG nLineXBegin = ptSrcLT.x;
    LONG nLineXEnd = ptSrcRB.x;
    LONG nLineYBegin = ptSrcLT.y;
    LONG nLineYEnd = ptSrcRB.y;
    LONG nLineXSize = 0;

    if (nLineXBegin < 0) nLineXBegin = 0;
    if (nLineXEnd >= nWidth) nLineXEnd = nWidth - 1;
    if (nLineYBegin < 0) nLineYBegin = 0;
    if (nLineYEnd >= nHeight) nLineYEnd = nHeight - 1;
    nLineXSize = (nLineXEnd - nLineXBegin) * sizeof(DWORD);

    //左边竖线
    {
        if (bDotMode)
        {
            int nIndex = 0;
            LONG nCount = 0;
            for (LONG i = ptSrcLT.x; i < ptSrcRB.x && nCount < xCount; i += xGridSize, nCount++)
            {
                if (i >= 0 && i < nWidth)
                {
                    lpData = lpBits + nLineYBegin * nWidth + i;
                    for (LONG j = nLineYBegin; j < nLineYEnd; j++)
                    {
                        if (nIndex & 0x01)
                        {
                            *lpData = dwColor;
                        }
                        lpData += nWidth;
                        nIndex++;
                    }
                }
            }
        }
        else
        {
            LONG nCount = 0;
            for (LONG i = ptSrcLT.x; i < ptSrcRB.x && nCount < xCount; i += xGridSize, nCount++)
            {
                if (i >= 0 && i < nWidth)
                {
                    lpData = lpBits + nLineYBegin * nWidth + i;
                    for (LONG j = nLineYBegin; j < nLineYEnd; j++)
                    {
                        *lpData = dwColor;
                        lpData += nWidth;
                    }
                }
            }
        }
    }

    //顶部横线
    {
        if (bDotMode)
        {
            LONG nCount = 0;
            int nSize = nLineXEnd - nLineXBegin;
            for (LONG i = ptSrcLT.y; i < ptSrcRB.y && nCount < yCount; i += yGridSize, nCount++)
            {
                if (i >= 0 && i < nHeight)
                {
                    lpData = lpBits + i * nWidth + nLineXBegin;

                    int nIndex = 0;
                    for (int j = 0; j < nSize; j++)
                    {
                        if (nIndex & 0x01)
                        {
                            lpData[j] = dwColor;
                        }
                        nIndex++;
                    }

                }
            }
        }
        else
        {
            LONG nCount = 0;
            for (LONG i = ptSrcLT.y; i < ptSrcRB.y && nCount < yCount; i += yGridSize, nCount++)
            {
                if (i >= 0 && i < nHeight)
                {
                    lpData = lpBits + i * nWidth + nLineXBegin;
                    ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
                }
            }
        }
    }

    //右边竖线
    if (bDotMode)
    {
        if (ptSrcRB.x >= 0 && ptSrcRB.x < nWidth)
        {
            int nIndex = 0;
            lpData = lpBits + nLineYBegin * nWidth + ptSrcRB.x;
            for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
            {
                if (nIndex & 0x01)
                {
                    *lpData = dwColor;
                }

                lpData += nWidth;
                nIndex++;
            }
        }
    }
    else
    {
        if (ptSrcRB.x >= 0 && ptSrcRB.x < nWidth)
        {
            lpData = lpBits + nLineYBegin * nWidth + ptSrcRB.x;
            for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
            {
                *lpData = dwColor;
                lpData += nWidth;
            }
        }
    }

    //底部横线
    if (ptSrcRB.y >= 0 && ptSrcRB.y < nHeight)
    {
        lpData = lpBits + nLineYEnd * nWidth + nLineXBegin;
        if (bDotMode)
        {
            int nIndex = 0;
            int nSize = nLineXEnd - nLineXBegin;
            for (int i = 0; i < nSize; i++)
            {
                if (nIndex & 0x01)
                {
                    lpData[i] = dwColor;
                }
                nIndex++;
            }
        }
        else
        {
            ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
        }
    }
}

void CBitmapDraw::FillGrid(POINT ptLT, POINT ptRB, DWORD dwColor, LONG xCount/* = 1*/, LONG yCount/* = 1*/, POINT pt/* = { 0, 0 }*/)
{
    dwColor = COLOR_RGB_TO_BGR(dwColor);
    if (nullptr == m_DrawData.lpBits)
    {
        return;
    }

    LPDWORD lpBits = m_DrawData.lpBits;
    LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    LONG nWidth = m_DrawData.width;

    //调节限制位置
    (void)AdjustPiont(ptLT, ptRB);
    (void)LimitPiont(ptLT, ptRB);

    //填充单行颜色
    if (lpLineBuf[0] != dwColor)
    {
        LPDWORD lpBuf = lpLineBuf;
        for (int i = 0; i < nWidth; i++)
        {
            *lpBuf++ = dwColor;
        }
    }

    //计算绘制区域宽高, 单行线条字节长度
    int nDrawWidth = ptRB.x - ptLT.x + 1;
    int nDrawHeight = ptRB.y - ptLT.y + 1;

    //格子数量限定
    if (xCount < 1) xCount = 1;
    if (yCount < 1) yCount = 1;

    //限定目标格子坐标
    if (pt.x < 0) pt.x = 0;
    if (pt.y < 0) pt.y = 0;
    if (pt.x >= xCount) pt.x = xCount - 1;
    if (pt.y >= yCount) pt.y = yCount - 1;

    //计算格子宽度
    int xGridWidth = nDrawWidth / xCount;
    int yGridHeight = nDrawHeight / yCount;
    int xGridWidthSize = xGridWidth * sizeof(DWORD);

    //填充单行颜色
    if (lpLineBuf[0] != dwColor)
    {
        LPDWORD lpBuf = lpLineBuf;
        for (int i = 0; i < nWidth; i++)
        {
            *lpBuf++ = dwColor;
        }
    }

    //填充
    LPDWORD lpData = lpBits + (ptLT.y + pt.y * yGridHeight) * nWidth + ptLT.x + pt.x * xGridWidth;
    for (int i = 0; i < yGridHeight; i++)
    {
        memcpy_s(lpData, xGridWidthSize, lpLineBuf, xGridWidthSize);
        lpData += nWidth;
    }
}

void CBitmapDraw::FillRect(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor)
{
    dwColor = COLOR_RGB_TO_BGR(dwColor);
    if (nullptr == m_DrawData.lpBits)
    {
        return;
    }

    LPDWORD lpBits = m_DrawData.lpBits;
    LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    LONG nWidth = m_DrawData.width;

    POINT ptLT = ptSrcLT;
    POINT ptRB = ptSrcRB;

    //调节限制位置
    (void)AdjustPiont(ptLT, ptRB);
    (void)LimitPiont(ptLT, ptRB);

    //填充单行颜色
    if (lpLineBuf[0] != dwColor)
    {
        LPDWORD lpBuf = lpLineBuf;
        for (int i = 0; i < nWidth; i++)
        {
            *lpBuf++ = dwColor;
        }
    }

    //计算绘制区域宽高, 单行线条字节长度
    int nDrawWidth = ptRB.x - ptLT.x + 1;
    int nDrawHeight = ptRB.y - ptLT.y + 1;
    int nDrawLineSize = nDrawWidth * sizeof(DWORD);

    LPDWORD lpData = lpBits + (ptLT.y) * nWidth + ptLT.x;
    for (int i = 0; i < nDrawHeight; i++)
    {
        memcpy_s(lpData, nDrawLineSize, lpLineBuf, nDrawLineSize);
        lpData += nWidth;
    }
}

void CBitmapDraw::DrawRect(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, bool bDotMode/* = true*/)
{
    dwColor = COLOR_RGB_TO_BGR(dwColor);
    if (nullptr == m_DrawData.lpBits)
    {
        return;
    }

    LPDWORD lpBits = m_DrawData.lpBits;
    LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    LONG nWidth = m_DrawData.width;
    LONG nHeight = m_DrawData.height;

    //调节限制位置
    (void)AdjustPiont(ptSrcLT, ptSrcRB);

    //填充单行颜色
    if (lpLineBuf[0] != dwColor)
    {
        LPDWORD lpBuf = lpLineBuf;
        for (int i = 0; i < nWidth; i++)
        {
            *lpBuf++ = dwColor;
        }
    }

    LONG nLineXBegin = ptSrcLT.x;
    LONG nLineXEnd = ptSrcRB.x;
    LONG nLineYBegin = ptSrcLT.y;
    LONG nLineYEnd = ptSrcRB.y;
    LONG nLineXSize = 0;

    if (nLineXBegin < 0) nLineXBegin = 0;
    if (nLineXEnd >= nWidth) nLineXEnd = nWidth - 1;
    if (nLineYBegin < 0) nLineYBegin = 0;
    if (nLineYEnd >= nHeight) nLineYEnd = nHeight - 1;
    nLineXSize = (nLineXEnd - nLineXBegin) * sizeof(DWORD);

    LPDWORD lpData = nullptr;

    //顶部横线
    if (ptSrcLT.y >= 0 && ptSrcLT.y < nHeight && nLineXSize > 0)
    {
        lpData = lpBits + nLineYBegin * nWidth + nLineXBegin;

        if (bDotMode)
        {
            int nIndex = 0;
            int nSize = nLineXEnd - nLineXBegin;
            for (int i = 0; i < nSize; i++)
            {
                if (nIndex & 0x01)
                {
                    lpData[i] = dwColor;
                }
                nIndex++;
            }
        }
        else
        {
            ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
        }

    }

    //底部横线
    if (ptSrcRB.y >= 0 && ptSrcRB.y < nHeight && nLineXSize > 0)
    {
        lpData = lpBits + nLineYEnd * nWidth + nLineXBegin;
        if (bDotMode)
        {
            int nIndex = 0;
            int nSize = nLineXEnd - nLineXBegin;
            for (int i = 0; i < nSize; i++)
            {
                if (nIndex & 0x01)
                {
                    lpData[i] = dwColor;
                }
                nIndex++;
            }
        }
        else
        {
            ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
        }
    }

    //左边竖线
    if (ptSrcLT.x >= 0 && ptSrcLT.x < nWidth)
    {
        lpData = lpBits + nLineYBegin * nWidth + nLineXBegin;

        if (bDotMode)
        {
            int nIndex = 0;
            for (LONG i = nLineYBegin; i < nLineYEnd; i++)
            {
                if (nIndex & 0x01)
                {
                    *lpData = dwColor;
                }
                lpData += nWidth;
                nIndex++;
            }
        }
        else
        {
            for (LONG i = nLineYBegin; i < nLineYEnd; i++)
            {
                *lpData = dwColor;
                lpData += nWidth;
            }
        }
    }

    //右边竖线
    if (ptSrcRB.x >= 0 && ptSrcRB.x < nWidth)
    {
        lpData = lpBits + nLineYBegin * nWidth + nLineXEnd;

        if (bDotMode)
        {
            int nIndex = 0;
            for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
            {
                if (nIndex & 0x01)
                {
                    *lpData = dwColor;
                }
                lpData += nWidth;
                nIndex++;
            }
        }
        else
        {
            for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
            {
                *lpData = dwColor;
                lpData += nWidth;
            }
        }
    }
}

void CBitmapDraw::DrawLine(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, bool bDotMode/* = true*/)
{
    dwColor = COLOR_RGB_TO_BGR(dwColor);
    if (nullptr == m_DrawData.lpBits)
    {
        return;
    }

    LPDWORD lpBits = m_DrawData.lpBits;
    LONG nWidth = m_DrawData.width;
    LONG nHeight = m_DrawData.height;

    POINT ptLT = ptSrcLT;
    POINT ptRB = ptSrcRB;

    //计算绘制区域内相交点

    /*{
        int x0 = ptLT.x;
        int y0 = ptLT.y;
        int x1 = ptRB.x;
        int y1 = ptRB.y;

        int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
        int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
        int erro = (dx > dy ? dx : -dy) / 2;

        do
        {
            lpBits[y0 * nWidth + x0] = dwColor;

            int e2 = erro;
            if (e2 > -dx)
            {
                erro -= dy;
                x0 += sx;
            }

            if (e2 < dy)
            {
                erro += dx;
                y0 += sy;
            }

        } while (x0 != x1 || y0 != y1);
    }*/

    //画任意斜率的直线(基于 Bresenham 算法)
    
    {
        int x1 = ptLT.x;
        int y1 = ptLT.y;
        int x2 = ptRB.x;
        int y2 = ptRB.y;

        int x = ptLT.x;
        int y = ptLT.y;

        int dx = ::abs(x2 - x1);
        int dy = ::abs(y2 - y1);
        int s1 = x2 > x1 ? 1 : -1;
        int s2 = y2 > y1 ? 1 : -1;

        bool interchange = false;// 默认不互换 dx、dy
        if (dy > dx)// 当斜率大于 1 时,dx、dy 互换
        {
            int temp = dx;
            dx = dy;
            dy = temp;
            interchange = true;
        }

        int p = 2 * dy - dx;

        if (!interchange)
        {
            if (bDotMode)
            {
                int nIndex = 0;
                for (int i = 0; i <= dx; i++)
                {
                    if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
                    {
                        if (nIndex & 0x01)
                        {
                            lpBits[y * nWidth + x] = dwColor;
                        }
                        nIndex++;
                    }

                    if (p >= 0)
                    {
                        y += s2;
                        p -= 2 * dx;
                    }

                    x += s1;// 当斜率 < 1 时,选取 x 为步长
                    p += 2 * dy;
                }
            }
            else
            {
                for (int i = 0; i <= dx; i++)
                {
                    if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
                    {
                        lpBits[y * nWidth + x] = dwColor;
                    }

                    if (p >= 0)
                    {
                        y += s2;
                        p -= 2 * dx;
                    }

                    x += s1;// 当斜率 < 1 时,选取 x 为步长
                    p += 2 * dy;
                }
            }
        }
        else
        {
            if (bDotMode)
            {
                int nIndex = 0;
                for (int i = 0; i <= dx; i++)
                {
                    if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
                    {
                        if (nIndex & 0x01)
                        {
                            lpBits[y * nWidth + x] = dwColor;
                        }
                        nIndex++;
                    }

                    if (p >= 0)
                    {
                        x += s1;
                        p -= 2 * dx;
                    }

                    y += s2;// 当斜率 > 1 时,选取 y 为步长
                    p += 2 * dy;
                }
            }
            else
            {
                for (int i = 0; i <= dx; i++)
                {
                    if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
                    {
                        lpBits[y * nWidth + x] = dwColor;
                    }

                    if (p >= 0)
                    {
                        x += s1;
                        p -= 2 * dx;
                    }

                    y += s2;// 当斜率 > 1 时,选取 y 为步长
                    p += 2 * dy;
                }
            }
        }
    }
}

void CBitmapDraw::DrawCircle(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode/* = true*/)
{
    dwColor = COLOR_RGB_TO_BGR(dwColor);
    if (nullptr == m_DrawData.lpBits)
    {
        return;
    }

    LPDWORD lpBits = m_DrawData.lpBits;
    LONG nWidth = m_DrawData.width;
    LONG nHeight = m_DrawData.height;

    //调节限制位置
    (void)AdjustPiont(ptLT, ptRB);

    LONG nW = ptRB.x - ptLT.x;
    LONG nH = ptRB.y - ptLT.y;

    LONG r = (LONG)::sqrt((nW * nW) + (nH * nH)) / 2;

    LONG x = ptLT.x;
    LONG y = ptLT.y;

    x += nW / 2;
    y += nH / 2;

    {
        int  xi;
        int  yi;
        int  di;
        di = 1 - r;
        xi = 0;
        yi = r;
        LONGLONG dwOffset = 0;
        
        int nXPox = 0;
        int nYPos = 0;

        if (bDotMode)
        {
            int nIndex = 0;
            while (yi >= xi)
            {
                //右下 1/4
                nXPox = y + yi;
                nYPos = x + xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                nXPox = y + xi;
                nYPos = x + yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                //左下 1/4
                nXPox = y + yi;
                nYPos = x - xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                nXPox = y + xi;
                nYPos = x - yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                //左上 1/4
                nXPox = y - yi;
                nYPos = x - xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                nXPox = y - xi;
                nYPos = x - yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                //右上 1/4
                nXPox = y - yi;
                nYPos = x + xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                nXPox = y - xi;
                nYPos = x + yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;

                if (di < 0)
                {
                    di += 3 + (xi << 1);
                }
                else
                {
                    di += 5 + ((xi - yi) << 1);
                    yi--;
                }
                xi++;
                nIndex++;
            }
        }
        else
        {
            while (yi >= xi)
            {
                //右下 1/4
                nXPox = y + yi;
                nYPos = x + xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                nXPox = y + xi;
                nYPos = x + yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                //左下 1/4
                nXPox = y + yi;
                nYPos = x - xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                nXPox = y + xi;
                nYPos = x - yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                //左上 1/4
                nXPox = y - yi;
                nYPos = x - xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                nXPox = y - xi;
                nYPos = x - yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                //右上 1/4
                nXPox = y - yi;
                nYPos = x + xi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                nXPox = y - xi;
                nYPos = x + yi;
                dwOffset = nXPox * nWidth + nYPos;
                if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;

                if (di < 0)
                {
                    di += 3 + (xi << 1);
                }
                else
                {
                    di += 5 + ((xi - yi) << 1);
                    yi--;
                }
                xi++;
            }
        }
    }
}

Win32 位图直接绘制,Win32,windows,Win32,C++,位图,bitmap

CBitmapPaint: 位图操作绘制图形 1.绘制线条 2.绘制矩形边框 3.填充矩形区域 4.绘制圆形边框 5.绘制网格线条 并比较使用位图操作与使用GDI绘制的速度 (gitee.com)文章来源地址https://www.toymoban.com/news/detail-732131.html

到了这里,关于Win32 位图直接绘制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • zxing二维码位矩阵转换成Bitmap位图

    ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。 该项目可实现的条形码编码和解码。我们支持以下格式: UPC-A,UPC-E EAN-8,EAN-13 39码 93码 代码128 创新及科

    2023年04月11日
    浏览(49)
  • Java中利用BitMap位图实现海量级数据去重

    🏷️ 个人主页 :牵着猫散步的鼠鼠  🏷️ 系列专栏 :Java全栈-专栏 🏷️ 个人学习笔记,若有缺误,欢迎评论区指正 目录 前言 什么是BitMap?有什么用? 基本概念 位图的优势 位图的劣势 BitMap和Int的区别 使用场景 BitMap在Java中的使用 有许多方法可以用来去重,比如使用列

    2024年04月10日
    浏览(41)
  • 探索Redis特殊数据结构:Bitmaps(位图)在实际中的应用

    Redis官方提供了多种数据类型,除了常见的String、Hash、List、Set、zSet之外,还包括Stream、Geospatial、Bitmaps、Bitfields、Probabilistic(HyperLogLog、Bloom filter、Cuckoo filter、t-digest、Top-K、Count-min sketch、Configuration)和Time series。这些数据类型在Redis的数据结构中发挥着各自独特的作用。

    2024年01月19日
    浏览(44)
  • Android App开发之位图加工Bitmap中转换位图的像素色彩、裁剪内部区域、利用矩阵变换位图的讲解及实战(附源码和演示)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 给图片添加装饰物,只是在局部变换,如果想让图片一边保持轮廓一边改变色彩,就要深入图像的每个像素点,将这些像素点统统采取某种算法修改一番,在像素级别更改图像的话,要先把图片转换成位图对象再进一步加工位

    2024年02月13日
    浏览(37)
  • STM32直接驱动TFT LCD,在LCD上根据数据绘制曲线

    快速画点函数和绘制直线函数可以根据自己屏幕来编写, void Port_DrawCurve(u8 x ,u16 value) 1、绘制曲线函数中的形参x,相当于时间轴,每一次进入函数,x就会++; 2、在绘制曲线之前需要先清除3列,这样绘制曲线就不用到最后了再整屏幕擦除。

    2024年02月15日
    浏览(43)
  • Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)

    有一个遗留问题,每行加载16张图片,以行为原子单位。后面可以考虑另外一种实现,group分组标签单独占一行,图片可以一大片一大片的占据多行,每行16张。 Android Glide自定义AppCompatImageView切分成若干小格子,每个小格子onDraw绘制Bitmap,Kotlin(1)_android appcompatimageview-CSDN博

    2024年04月17日
    浏览(43)
  • Android Glide自定义AppCompatImageView切分成若干小格子,每个小格子onDraw绘制Bitmap,Kotlin(1)

      垂直方向的RecyclerView,每行一个AppCompatImageView,每个AppCompatImageView被均匀切割成n个小格子, 每个小格子通过Glide加载出来Bitmap,然后onDraw绘制整行。             上面每一行加载16个bitmap绘图,速度很快,因为是canvas直接绘图。但是,如果使用下文的方式: Android LinearLa

    2024年02月04日
    浏览(41)
  • 【openssl】openssl-cmake windows win32

    一开始用cygwin,折腾很久,发现不行, 回归控制台 发现要-G 啥的,出错还要看文字, 那还不如直接回归cmake-gui ,直接windows上cmake构建 。 虽然生成的还是camke生成的sln,但是够用就好。我们也不可能频繁改动ssl。

    2024年02月06日
    浏览(35)
  • Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b)

    对 Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)-CSDN博客 改进,用Glide批量把Bitmap加载出来,然后在RecyclerView成片成堆的绘制Canvas,此种实现是RecyclerView加载多宫格图片展示,卡顿丢帧最低的一种实现,上下滑动流畅。 Android GridLayoutManager Glide批量

    2024年04月25日
    浏览(43)
  • MS17-010永恒之蓝漏洞利用,win32安装,windows 7 32位

    漏洞复现:MS17-010 漏洞利用的条件:1.靶机开启445端口(如果未打开该端口将会攻击失败,百度打开445端口)                              2.关闭防火墙 靶机:windows 7(未知X32位还是X64位) ip:192.168.1.9 攻击机:kali linux (X64) ip:192.168.1.101 使用工具:meatsploit,nmap 前期准备工作 :

    2024年02月08日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包