• Win32 位图直接绘制


    CBitmapDraw.h

    1. #pragma once
    2. #include
    3. #include
    4. #define COLOR_RGB_TO_BGR(_rgb) ( (_rgb & 0xFF) << 16) | (_rgb & 0x00FF00) | ( (_rgb >> 16) & 0xFF)
    5. typedef struct _BITMAP_DRAW_DATA
    6. {
    7. BITMAPINFO binfo = { 0 }; //位图原始信息
    8. HBITMAP hBitmap = nullptr; //位图句柄
    9. LONG width = 0; //位图宽度
    10. LONG height = 0; //位图高度
    11. LPDWORD lpBits = nullptr; //位图全部数据缓冲 宽度 * 高度 * sizeof(DWORD)
    12. LPDWORD lpLineBuf = nullptr; //位图单行数据缓冲 宽度 * sizeof(DWORD)
    13. _BITMAP_DRAW_DATA(const _BITMAP_DRAW_DATA&) = delete;
    14. _BITMAP_DRAW_DATA()
    15. {
    16. ZeroMemory(this, sizeof(_BITMAP_DRAW_DATA));
    17. }
    18. ~_BITMAP_DRAW_DATA()
    19. {
    20. this->Release();
    21. }
    22. _BITMAP_DRAW_DATA(_BITMAP_DRAW_DATA&& r) noexcept
    23. {
    24. this->binfo = r.binfo;
    25. this->hBitmap = r.hBitmap;
    26. this->width = r.width;
    27. this->height = r.height;
    28. this->lpBits = r.lpBits;
    29. this->lpLineBuf = r.lpLineBuf;
    30. *this = std::move(r);
    31. }
    32. _BITMAP_DRAW_DATA operator = (const _BITMAP_DRAW_DATA&) = delete;
    33. _BITMAP_DRAW_DATA& operator = (_BITMAP_DRAW_DATA&& r) noexcept
    34. {
    35. this->binfo = r.binfo;
    36. this->hBitmap = r.hBitmap;
    37. this->width = r.width;
    38. this->height = r.height;
    39. this->lpBits = r.lpBits;
    40. this->lpLineBuf = r.lpLineBuf;
    41. r.lpBits = nullptr;
    42. r.lpLineBuf = nullptr;
    43. r.hBitmap = nullptr;
    44. return *this;
    45. }
    46. void Release()
    47. {
    48. if (nullptr != lpBits)
    49. {
    50. delete[] lpBits;
    51. lpBits = nullptr;
    52. }
    53. if (nullptr != lpLineBuf)
    54. {
    55. delete[] lpLineBuf;
    56. lpLineBuf = nullptr;
    57. }
    58. ZeroMemory(this, sizeof(_BITMAP_DRAW_DATA));
    59. }
    60. }BITMAP_DRAW_DATA, * PBITMAP_DRAW_DATA;
    61. class CBitmapDraw
    62. {
    63. public:
    64. CBitmapDraw(HDC hdc);
    65. ~CBitmapDraw();
    66. //获取位图宽度
    67. LONG GetWidth() const;
    68. //获取位图高度
    69. LONG GetHeight() const;
    70. //获取位图左上坐标
    71. POINT GetLeftTop() const;
    72. //获取位图右下坐标
    73. POINT GetRightBottom() const;
    74. //准备绘制
    75. bool BeginDraw();
    76. //结束绘制
    77. bool EndDraw();
    78. //绘制矩形边框
    79. void DrawRect(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode = false);
    80. //绘制线条
    81. void DrawLine(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode = false);
    82. //绘制圆形
    83. void DrawCircle(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode = false);
    84. //绘制网格
    85. void DrawGrid(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, LONG xCount = 1, LONG yCount = 1, bool bDotMode = false);
    86. //填充网格
    87. void FillGrid(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, LONG xCount = 1, LONG yCount = 1, POINT pt = { 0, 0 });
    88. //填充矩形区域
    89. void FillRect(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor);
    90. //限制坐标
    91. void LimitPiont(POINT& ptLT, POINT& ptRB);
    92. public:
    93. //调节起始坐标点, 确保起始点坐标在终止坐标的左上方
    94. static void AdjustPiont(POINT& ptLT, POINT& ptRB);
    95. //网格命中测试
    96. static bool GridHitTest(POINT ptLT, POINT ptRB, DWORD xCount, DWORD yCount, POINT ptCheck, POINT& ptOut);
    97. private:
    98. BITMAP_DRAW_DATA m_DrawData; //绘制数据
    99. HDC m_hDC = nullptr; //DC句柄
    100. };

    CBitmapDraw.cpp

    1. #include "CBitmapDraw.h"
    2. #include
    3. #include
    4. #include
    5. #pragma intrinsic(memcpy)
    6. CBitmapDraw::CBitmapDraw(HDC hdc)
    7. {
    8. if (nullptr == hdc)
    9. {
    10. return;
    11. }
    12. do
    13. {
    14. m_hDC = hdc;
    15. int nScanlines = 0;
    16. //获取位图句柄
    17. m_DrawData.hBitmap = (HBITMAP)::GetCurrentObject(hdc, OBJ_BITMAP);
    18. if (nullptr == m_DrawData.hBitmap)
    19. {
    20. break;
    21. }
    22. //获取位图信息
    23. m_DrawData.binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    24. nScanlines = ::GetDIBits(hdc, m_DrawData.hBitmap, 0, 0, nullptr, &m_DrawData.binfo, DIB_RGB_COLORS);
    25. if (0 == nScanlines)
    26. {
    27. break;
    28. }
    29. m_DrawData.binfo.bmiHeader.biPlanes = 1;
    30. m_DrawData.binfo.bmiHeader.biBitCount = 32;
    31. //取得位图尺寸, 分配位图数据缓冲
    32. m_DrawData.width = m_DrawData.binfo.bmiHeader.biWidth;
    33. m_DrawData.height = ::abs(m_DrawData.binfo.bmiHeader.biHeight);
    34. //高度方向矫正
    35. m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;
    36. if (m_DrawData.binfo.bmiHeader.biHeight > 0)
    37. {
    38. m_DrawData.binfo.bmiHeader.biHeight = 0 - m_DrawData.binfo.bmiHeader.biHeight;
    39. }
    40. m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;
    41. } while (false);
    42. }
    43. CBitmapDraw::~CBitmapDraw()
    44. {
    45. m_DrawData.Release();
    46. }
    47. LONG CBitmapDraw::GetWidth() const
    48. {
    49. return m_DrawData.width;
    50. }
    51. LONG CBitmapDraw::GetHeight() const
    52. {
    53. return m_DrawData.height;
    54. }
    55. POINT CBitmapDraw::GetLeftTop() const
    56. {
    57. return {0, 0};
    58. }
    59. POINT CBitmapDraw::GetRightBottom() const
    60. {
    61. return { m_DrawData.width - 1, m_DrawData.height - 1 };
    62. }
    63. bool CBitmapDraw::BeginDraw()
    64. {
    65. if (nullptr == m_hDC)
    66. {
    67. return false;
    68. }
    69. bool bRes = false;
    70. do
    71. {
    72. m_DrawData.Release();
    73. //获取位图句柄
    74. m_DrawData.hBitmap = (HBITMAP)::GetCurrentObject(m_hDC, OBJ_BITMAP);
    75. if (nullptr == m_DrawData.hBitmap)
    76. {
    77. break;
    78. }
    79. //获取位图信息
    80. m_DrawData.binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    81. if (0 == ::GetDIBits(m_hDC, m_DrawData.hBitmap, 0, 0, nullptr, &m_DrawData.binfo, DIB_RGB_COLORS))
    82. {
    83. break;
    84. }
    85. m_DrawData.binfo.bmiHeader.biPlanes = 1;
    86. m_DrawData.binfo.bmiHeader.biBitCount = 32;
    87. //取得位图尺寸, 分配位图数据缓冲
    88. m_DrawData.width = m_DrawData.binfo.bmiHeader.biWidth;
    89. m_DrawData.height = ::abs(m_DrawData.binfo.bmiHeader.biHeight);
    90. m_DrawData.lpBits = new (std::nothrow) DWORD[m_DrawData.width * m_DrawData.height];
    91. if (nullptr == m_DrawData.lpBits)
    92. {
    93. break;
    94. }
    95. memset(m_DrawData.lpBits, 0, (m_DrawData.width * m_DrawData.height) * sizeof(DWORD));
    96. //分配单行缓冲
    97. m_DrawData.lpLineBuf = new (std::nothrow) DWORD[m_DrawData.width];
    98. if (nullptr == m_DrawData.lpLineBuf)
    99. {
    100. break;
    101. }
    102. memset(m_DrawData.lpLineBuf, 0, m_DrawData.width * sizeof(DWORD));
    103. //高度方向矫正
    104. m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;
    105. if (m_DrawData.binfo.bmiHeader.biHeight > 0)
    106. {
    107. m_DrawData.binfo.bmiHeader.biHeight = 0 - m_DrawData.binfo.bmiHeader.biHeight;
    108. }
    109. //取得位图数据
    110. int nScanlines = ::GetDIBits(m_hDC, m_DrawData.hBitmap, 0, m_DrawData.height, m_DrawData.lpBits, &m_DrawData.binfo, DIB_RGB_COLORS);
    111. if (0 == nScanlines)
    112. {
    113. break;
    114. }
    115. m_DrawData.binfo.bmiHeader.biCompression = BI_RGB;
    116. bRes = true;
    117. } while (false);
    118. return bRes;
    119. }
    120. bool CBitmapDraw::EndDraw()
    121. {
    122. if (nullptr == m_DrawData.lpBits)
    123. {
    124. return false;
    125. }
    126. if (m_DrawData.lpBits)
    127. {
    128. //设置兼容位图中的像素。
    129. int nScanlines = ::SetDIBits(m_hDC, m_DrawData.hBitmap, 0, m_DrawData.height, m_DrawData.lpBits, &m_DrawData.binfo, DIB_RGB_COLORS);
    130. if (0 != nScanlines)
    131. {
    132. return true;
    133. }
    134. }
    135. return false;
    136. }
    137. void CBitmapDraw::LimitPiont(POINT& ptLT, POINT& ptRB)
    138. {
    139. LONG nWidth = m_DrawData.width;
    140. LONG nHeight = m_DrawData.height;
    141. //起点坐标限制
    142. if (ptLT.x < 0) ptLT.x = 0;
    143. if (ptLT.y < 0) ptLT.y = 0;
    144. if (ptLT.x > nWidth - 1) ptLT.x = nWidth - 1;
    145. if (ptLT.y > nHeight - 1) ptLT.y = nHeight - 1;
    146. //终点坐标限制
    147. if (ptRB.x < 0) ptRB.x = 0;
    148. if (ptRB.y < 0) ptRB.y = 0;
    149. if (ptRB.x > nWidth - 1) ptRB.x = nWidth - 1;
    150. if (ptRB.y > nHeight - 1) ptRB.y = nHeight - 1;
    151. }
    152. void CBitmapDraw::AdjustPiont(POINT& ptLT, POINT& ptRB)
    153. {
    154. LONG x0 = ptLT.x < ptRB.x ? ptLT.x : ptRB.x;
    155. LONG y0 = ptLT.y < ptRB.y ? ptLT.y : ptRB.y;
    156. LONG x1 = ptLT.x > ptRB.x ? ptLT.x : ptRB.x;
    157. LONG y1 = ptLT.y > ptRB.y ? ptLT.y : ptRB.y;
    158. ptLT = { x0 , y0 };
    159. ptRB = { x1 , y1 };
    160. }
    161. bool CBitmapDraw::GridHitTest(POINT ptLT, POINT ptRB, DWORD xCount, DWORD yCount, POINT ptCheck, POINT& ptOut)
    162. {
    163. //调节限制位置
    164. (void)AdjustPiont(ptLT, ptRB);
    165. //计算绘制区域宽高, 单行线条字节长度
    166. int nDrawWidth = ptRB.x - ptLT.x + 1;
    167. int nDrawHeight = ptRB.y - ptLT.y + 1;
    168. //格子数量限定
    169. if (xCount < 1) xCount = 1;
    170. if (yCount < 1) yCount = 1;
    171. //计算格子宽度
    172. int xGridWidth = nDrawWidth / xCount;
    173. int yGridHeight = nDrawHeight / yCount;
    174. //检查是否位于指定区域内(包含边框)
    175. if (!((ptCheck.x >= ptLT.x && ptCheck.x <= ptRB.x) && (ptCheck.y >= ptLT.y && ptCheck.y <= ptRB.y)))
    176. {
    177. return false;
    178. }
    179. ptOut.x = (ptCheck.x - ptLT.x) / xGridWidth;
    180. ptOut.y = (ptCheck.y - ptLT.y) / yGridHeight;
    181. return true;
    182. }
    183. void CBitmapDraw::DrawGrid(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, LONG xCount/* = 1*/, LONG yCount/* = 1*/, bool bDotMode/* = false*/)
    184. {
    185. dwColor = COLOR_RGB_TO_BGR(dwColor);
    186. if (nullptr == m_DrawData.lpBits)
    187. {
    188. return;
    189. }
    190. LPDWORD lpBits = m_DrawData.lpBits;
    191. LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    192. LONG nWidth = m_DrawData.width;
    193. LONG nHeight = m_DrawData.height;
    194. //调节限制位置
    195. (void)AdjustPiont(ptSrcLT, ptSrcRB);
    196. //填充单行颜色
    197. if (lpLineBuf[0] != dwColor)
    198. {
    199. LPDWORD lpBuf = lpLineBuf;
    200. for (int i = 0; i < nWidth; i++)
    201. {
    202. *lpBuf++ = dwColor;
    203. }
    204. }
    205. //计算绘制区域宽高, 单行线条字节长度
    206. int nDrawWidth = ptSrcRB.x - ptSrcLT.x + 1;
    207. int nDrawHeight = ptSrcRB.y - ptSrcLT.y + 1;
    208. //格子数量限定
    209. if (xCount < 1) xCount = 1;
    210. if (yCount < 1) yCount = 1;
    211. //计算格子宽度
    212. int xGridSize = nDrawWidth / xCount;
    213. int yGridSize = nDrawHeight / yCount;
    214. LPDWORD lpData = nullptr;
    215. LONG nLineXBegin = ptSrcLT.x;
    216. LONG nLineXEnd = ptSrcRB.x;
    217. LONG nLineYBegin = ptSrcLT.y;
    218. LONG nLineYEnd = ptSrcRB.y;
    219. LONG nLineXSize = 0;
    220. if (nLineXBegin < 0) nLineXBegin = 0;
    221. if (nLineXEnd >= nWidth) nLineXEnd = nWidth - 1;
    222. if (nLineYBegin < 0) nLineYBegin = 0;
    223. if (nLineYEnd >= nHeight) nLineYEnd = nHeight - 1;
    224. nLineXSize = (nLineXEnd - nLineXBegin) * sizeof(DWORD);
    225. //左边竖线
    226. {
    227. if (bDotMode)
    228. {
    229. int nIndex = 0;
    230. LONG nCount = 0;
    231. for (LONG i = ptSrcLT.x; i < ptSrcRB.x && nCount < xCount; i += xGridSize, nCount++)
    232. {
    233. if (i >= 0 && i < nWidth)
    234. {
    235. lpData = lpBits + nLineYBegin * nWidth + i;
    236. for (LONG j = nLineYBegin; j < nLineYEnd; j++)
    237. {
    238. if (nIndex & 0x01)
    239. {
    240. *lpData = dwColor;
    241. }
    242. lpData += nWidth;
    243. nIndex++;
    244. }
    245. }
    246. }
    247. }
    248. else
    249. {
    250. LONG nCount = 0;
    251. for (LONG i = ptSrcLT.x; i < ptSrcRB.x && nCount < xCount; i += xGridSize, nCount++)
    252. {
    253. if (i >= 0 && i < nWidth)
    254. {
    255. lpData = lpBits + nLineYBegin * nWidth + i;
    256. for (LONG j = nLineYBegin; j < nLineYEnd; j++)
    257. {
    258. *lpData = dwColor;
    259. lpData += nWidth;
    260. }
    261. }
    262. }
    263. }
    264. }
    265. //顶部横线
    266. {
    267. if (bDotMode)
    268. {
    269. LONG nCount = 0;
    270. int nSize = nLineXEnd - nLineXBegin;
    271. for (LONG i = ptSrcLT.y; i < ptSrcRB.y && nCount < yCount; i += yGridSize, nCount++)
    272. {
    273. if (i >= 0 && i < nHeight)
    274. {
    275. lpData = lpBits + i * nWidth + nLineXBegin;
    276. int nIndex = 0;
    277. for (int j = 0; j < nSize; j++)
    278. {
    279. if (nIndex & 0x01)
    280. {
    281. lpData[j] = dwColor;
    282. }
    283. nIndex++;
    284. }
    285. }
    286. }
    287. }
    288. else
    289. {
    290. LONG nCount = 0;
    291. for (LONG i = ptSrcLT.y; i < ptSrcRB.y && nCount < yCount; i += yGridSize, nCount++)
    292. {
    293. if (i >= 0 && i < nHeight)
    294. {
    295. lpData = lpBits + i * nWidth + nLineXBegin;
    296. ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
    297. }
    298. }
    299. }
    300. }
    301. //右边竖线
    302. if (bDotMode)
    303. {
    304. if (ptSrcRB.x >= 0 && ptSrcRB.x < nWidth)
    305. {
    306. int nIndex = 0;
    307. lpData = lpBits + nLineYBegin * nWidth + ptSrcRB.x;
    308. for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
    309. {
    310. if (nIndex & 0x01)
    311. {
    312. *lpData = dwColor;
    313. }
    314. lpData += nWidth;
    315. nIndex++;
    316. }
    317. }
    318. }
    319. else
    320. {
    321. if (ptSrcRB.x >= 0 && ptSrcRB.x < nWidth)
    322. {
    323. lpData = lpBits + nLineYBegin * nWidth + ptSrcRB.x;
    324. for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
    325. {
    326. *lpData = dwColor;
    327. lpData += nWidth;
    328. }
    329. }
    330. }
    331. //底部横线
    332. if (ptSrcRB.y >= 0 && ptSrcRB.y < nHeight)
    333. {
    334. lpData = lpBits + nLineYEnd * nWidth + nLineXBegin;
    335. if (bDotMode)
    336. {
    337. int nIndex = 0;
    338. int nSize = nLineXEnd - nLineXBegin;
    339. for (int i = 0; i < nSize; i++)
    340. {
    341. if (nIndex & 0x01)
    342. {
    343. lpData[i] = dwColor;
    344. }
    345. nIndex++;
    346. }
    347. }
    348. else
    349. {
    350. ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
    351. }
    352. }
    353. }
    354. void CBitmapDraw::FillGrid(POINT ptLT, POINT ptRB, DWORD dwColor, LONG xCount/* = 1*/, LONG yCount/* = 1*/, POINT pt/* = { 0, 0 }*/)
    355. {
    356. dwColor = COLOR_RGB_TO_BGR(dwColor);
    357. if (nullptr == m_DrawData.lpBits)
    358. {
    359. return;
    360. }
    361. LPDWORD lpBits = m_DrawData.lpBits;
    362. LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    363. LONG nWidth = m_DrawData.width;
    364. //调节限制位置
    365. (void)AdjustPiont(ptLT, ptRB);
    366. (void)LimitPiont(ptLT, ptRB);
    367. //填充单行颜色
    368. if (lpLineBuf[0] != dwColor)
    369. {
    370. LPDWORD lpBuf = lpLineBuf;
    371. for (int i = 0; i < nWidth; i++)
    372. {
    373. *lpBuf++ = dwColor;
    374. }
    375. }
    376. //计算绘制区域宽高, 单行线条字节长度
    377. int nDrawWidth = ptRB.x - ptLT.x + 1;
    378. int nDrawHeight = ptRB.y - ptLT.y + 1;
    379. //格子数量限定
    380. if (xCount < 1) xCount = 1;
    381. if (yCount < 1) yCount = 1;
    382. //限定目标格子坐标
    383. if (pt.x < 0) pt.x = 0;
    384. if (pt.y < 0) pt.y = 0;
    385. if (pt.x >= xCount) pt.x = xCount - 1;
    386. if (pt.y >= yCount) pt.y = yCount - 1;
    387. //计算格子宽度
    388. int xGridWidth = nDrawWidth / xCount;
    389. int yGridHeight = nDrawHeight / yCount;
    390. int xGridWidthSize = xGridWidth * sizeof(DWORD);
    391. //填充单行颜色
    392. if (lpLineBuf[0] != dwColor)
    393. {
    394. LPDWORD lpBuf = lpLineBuf;
    395. for (int i = 0; i < nWidth; i++)
    396. {
    397. *lpBuf++ = dwColor;
    398. }
    399. }
    400. //填充
    401. LPDWORD lpData = lpBits + (ptLT.y + pt.y * yGridHeight) * nWidth + ptLT.x + pt.x * xGridWidth;
    402. for (int i = 0; i < yGridHeight; i++)
    403. {
    404. memcpy_s(lpData, xGridWidthSize, lpLineBuf, xGridWidthSize);
    405. lpData += nWidth;
    406. }
    407. }
    408. void CBitmapDraw::FillRect(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor)
    409. {
    410. dwColor = COLOR_RGB_TO_BGR(dwColor);
    411. if (nullptr == m_DrawData.lpBits)
    412. {
    413. return;
    414. }
    415. LPDWORD lpBits = m_DrawData.lpBits;
    416. LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    417. LONG nWidth = m_DrawData.width;
    418. POINT ptLT = ptSrcLT;
    419. POINT ptRB = ptSrcRB;
    420. //调节限制位置
    421. (void)AdjustPiont(ptLT, ptRB);
    422. (void)LimitPiont(ptLT, ptRB);
    423. //填充单行颜色
    424. if (lpLineBuf[0] != dwColor)
    425. {
    426. LPDWORD lpBuf = lpLineBuf;
    427. for (int i = 0; i < nWidth; i++)
    428. {
    429. *lpBuf++ = dwColor;
    430. }
    431. }
    432. //计算绘制区域宽高, 单行线条字节长度
    433. int nDrawWidth = ptRB.x - ptLT.x + 1;
    434. int nDrawHeight = ptRB.y - ptLT.y + 1;
    435. int nDrawLineSize = nDrawWidth * sizeof(DWORD);
    436. LPDWORD lpData = lpBits + (ptLT.y) * nWidth + ptLT.x;
    437. for (int i = 0; i < nDrawHeight; i++)
    438. {
    439. memcpy_s(lpData, nDrawLineSize, lpLineBuf, nDrawLineSize);
    440. lpData += nWidth;
    441. }
    442. }
    443. void CBitmapDraw::DrawRect(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, bool bDotMode/* = true*/)
    444. {
    445. dwColor = COLOR_RGB_TO_BGR(dwColor);
    446. if (nullptr == m_DrawData.lpBits)
    447. {
    448. return;
    449. }
    450. LPDWORD lpBits = m_DrawData.lpBits;
    451. LPDWORD lpLineBuf = m_DrawData.lpLineBuf;
    452. LONG nWidth = m_DrawData.width;
    453. LONG nHeight = m_DrawData.height;
    454. //调节限制位置
    455. (void)AdjustPiont(ptSrcLT, ptSrcRB);
    456. //填充单行颜色
    457. if (lpLineBuf[0] != dwColor)
    458. {
    459. LPDWORD lpBuf = lpLineBuf;
    460. for (int i = 0; i < nWidth; i++)
    461. {
    462. *lpBuf++ = dwColor;
    463. }
    464. }
    465. LONG nLineXBegin = ptSrcLT.x;
    466. LONG nLineXEnd = ptSrcRB.x;
    467. LONG nLineYBegin = ptSrcLT.y;
    468. LONG nLineYEnd = ptSrcRB.y;
    469. LONG nLineXSize = 0;
    470. if (nLineXBegin < 0) nLineXBegin = 0;
    471. if (nLineXEnd >= nWidth) nLineXEnd = nWidth - 1;
    472. if (nLineYBegin < 0) nLineYBegin = 0;
    473. if (nLineYEnd >= nHeight) nLineYEnd = nHeight - 1;
    474. nLineXSize = (nLineXEnd - nLineXBegin) * sizeof(DWORD);
    475. LPDWORD lpData = nullptr;
    476. //顶部横线
    477. if (ptSrcLT.y >= 0 && ptSrcLT.y < nHeight && nLineXSize > 0)
    478. {
    479. lpData = lpBits + nLineYBegin * nWidth + nLineXBegin;
    480. if (bDotMode)
    481. {
    482. int nIndex = 0;
    483. int nSize = nLineXEnd - nLineXBegin;
    484. for (int i = 0; i < nSize; i++)
    485. {
    486. if (nIndex & 0x01)
    487. {
    488. lpData[i] = dwColor;
    489. }
    490. nIndex++;
    491. }
    492. }
    493. else
    494. {
    495. ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
    496. }
    497. }
    498. //底部横线
    499. if (ptSrcRB.y >= 0 && ptSrcRB.y < nHeight && nLineXSize > 0)
    500. {
    501. lpData = lpBits + nLineYEnd * nWidth + nLineXBegin;
    502. if (bDotMode)
    503. {
    504. int nIndex = 0;
    505. int nSize = nLineXEnd - nLineXBegin;
    506. for (int i = 0; i < nSize; i++)
    507. {
    508. if (nIndex & 0x01)
    509. {
    510. lpData[i] = dwColor;
    511. }
    512. nIndex++;
    513. }
    514. }
    515. else
    516. {
    517. ::memcpy_s(lpData, nLineXSize, lpLineBuf, nLineXSize);
    518. }
    519. }
    520. //左边竖线
    521. if (ptSrcLT.x >= 0 && ptSrcLT.x < nWidth)
    522. {
    523. lpData = lpBits + nLineYBegin * nWidth + nLineXBegin;
    524. if (bDotMode)
    525. {
    526. int nIndex = 0;
    527. for (LONG i = nLineYBegin; i < nLineYEnd; i++)
    528. {
    529. if (nIndex & 0x01)
    530. {
    531. *lpData = dwColor;
    532. }
    533. lpData += nWidth;
    534. nIndex++;
    535. }
    536. }
    537. else
    538. {
    539. for (LONG i = nLineYBegin; i < nLineYEnd; i++)
    540. {
    541. *lpData = dwColor;
    542. lpData += nWidth;
    543. }
    544. }
    545. }
    546. //右边竖线
    547. if (ptSrcRB.x >= 0 && ptSrcRB.x < nWidth)
    548. {
    549. lpData = lpBits + nLineYBegin * nWidth + nLineXEnd;
    550. if (bDotMode)
    551. {
    552. int nIndex = 0;
    553. for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
    554. {
    555. if (nIndex & 0x01)
    556. {
    557. *lpData = dwColor;
    558. }
    559. lpData += nWidth;
    560. nIndex++;
    561. }
    562. }
    563. else
    564. {
    565. for (LONG i = nLineYBegin; i <= nLineYEnd; i++)
    566. {
    567. *lpData = dwColor;
    568. lpData += nWidth;
    569. }
    570. }
    571. }
    572. }
    573. void CBitmapDraw::DrawLine(POINT ptSrcLT, POINT ptSrcRB, DWORD dwColor, bool bDotMode/* = true*/)
    574. {
    575. dwColor = COLOR_RGB_TO_BGR(dwColor);
    576. if (nullptr == m_DrawData.lpBits)
    577. {
    578. return;
    579. }
    580. LPDWORD lpBits = m_DrawData.lpBits;
    581. LONG nWidth = m_DrawData.width;
    582. LONG nHeight = m_DrawData.height;
    583. POINT ptLT = ptSrcLT;
    584. POINT ptRB = ptSrcRB;
    585. //计算绘制区域内相交点
    586. /*{
    587. int x0 = ptLT.x;
    588. int y0 = ptLT.y;
    589. int x1 = ptRB.x;
    590. int y1 = ptRB.y;
    591. int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
    592. int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
    593. int erro = (dx > dy ? dx : -dy) / 2;
    594. do
    595. {
    596. lpBits[y0 * nWidth + x0] = dwColor;
    597. int e2 = erro;
    598. if (e2 > -dx)
    599. {
    600. erro -= dy;
    601. x0 += sx;
    602. }
    603. if (e2 < dy)
    604. {
    605. erro += dx;
    606. y0 += sy;
    607. }
    608. } while (x0 != x1 || y0 != y1);
    609. }*/
    610. //画任意斜率的直线(基于 Bresenham 算法)
    611. {
    612. int x1 = ptLT.x;
    613. int y1 = ptLT.y;
    614. int x2 = ptRB.x;
    615. int y2 = ptRB.y;
    616. int x = ptLT.x;
    617. int y = ptLT.y;
    618. int dx = ::abs(x2 - x1);
    619. int dy = ::abs(y2 - y1);
    620. int s1 = x2 > x1 ? 1 : -1;
    621. int s2 = y2 > y1 ? 1 : -1;
    622. bool interchange = false;// 默认不互换 dx、dy
    623. if (dy > dx)// 当斜率大于 1 时,dx、dy 互换
    624. {
    625. int temp = dx;
    626. dx = dy;
    627. dy = temp;
    628. interchange = true;
    629. }
    630. int p = 2 * dy - dx;
    631. if (!interchange)
    632. {
    633. if (bDotMode)
    634. {
    635. int nIndex = 0;
    636. for (int i = 0; i <= dx; i++)
    637. {
    638. if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
    639. {
    640. if (nIndex & 0x01)
    641. {
    642. lpBits[y * nWidth + x] = dwColor;
    643. }
    644. nIndex++;
    645. }
    646. if (p >= 0)
    647. {
    648. y += s2;
    649. p -= 2 * dx;
    650. }
    651. x += s1;// 当斜率 < 1 时,选取 x 为步长
    652. p += 2 * dy;
    653. }
    654. }
    655. else
    656. {
    657. for (int i = 0; i <= dx; i++)
    658. {
    659. if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
    660. {
    661. lpBits[y * nWidth + x] = dwColor;
    662. }
    663. if (p >= 0)
    664. {
    665. y += s2;
    666. p -= 2 * dx;
    667. }
    668. x += s1;// 当斜率 < 1 时,选取 x 为步长
    669. p += 2 * dy;
    670. }
    671. }
    672. }
    673. else
    674. {
    675. if (bDotMode)
    676. {
    677. int nIndex = 0;
    678. for (int i = 0; i <= dx; i++)
    679. {
    680. if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
    681. {
    682. if (nIndex & 0x01)
    683. {
    684. lpBits[y * nWidth + x] = dwColor;
    685. }
    686. nIndex++;
    687. }
    688. if (p >= 0)
    689. {
    690. x += s1;
    691. p -= 2 * dx;
    692. }
    693. y += s2;// 当斜率 > 1 时,选取 y 为步长
    694. p += 2 * dy;
    695. }
    696. }
    697. else
    698. {
    699. for (int i = 0; i <= dx; i++)
    700. {
    701. if (y >= 0 && y < nHeight && x >= 0 && x < nWidth)
    702. {
    703. lpBits[y * nWidth + x] = dwColor;
    704. }
    705. if (p >= 0)
    706. {
    707. x += s1;
    708. p -= 2 * dx;
    709. }
    710. y += s2;// 当斜率 > 1 时,选取 y 为步长
    711. p += 2 * dy;
    712. }
    713. }
    714. }
    715. }
    716. }
    717. void CBitmapDraw::DrawCircle(POINT ptLT, POINT ptRB, DWORD dwColor, bool bDotMode/* = true*/)
    718. {
    719. dwColor = COLOR_RGB_TO_BGR(dwColor);
    720. if (nullptr == m_DrawData.lpBits)
    721. {
    722. return;
    723. }
    724. LPDWORD lpBits = m_DrawData.lpBits;
    725. LONG nWidth = m_DrawData.width;
    726. LONG nHeight = m_DrawData.height;
    727. //调节限制位置
    728. (void)AdjustPiont(ptLT, ptRB);
    729. LONG nW = ptRB.x - ptLT.x;
    730. LONG nH = ptRB.y - ptLT.y;
    731. LONG r = (LONG)::sqrt((nW * nW) + (nH * nH)) / 2;
    732. LONG x = ptLT.x;
    733. LONG y = ptLT.y;
    734. x += nW / 2;
    735. y += nH / 2;
    736. {
    737. int xi;
    738. int yi;
    739. int di;
    740. di = 1 - r;
    741. xi = 0;
    742. yi = r;
    743. LONGLONG dwOffset = 0;
    744. int nXPox = 0;
    745. int nYPos = 0;
    746. if (bDotMode)
    747. {
    748. int nIndex = 0;
    749. while (yi >= xi)
    750. {
    751. //右下 1/4
    752. nXPox = y + yi;
    753. nYPos = x + xi;
    754. dwOffset = nXPox * nWidth + nYPos;
    755. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    756. nXPox = y + xi;
    757. nYPos = x + yi;
    758. dwOffset = nXPox * nWidth + nYPos;
    759. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    760. //左下 1/4
    761. nXPox = y + yi;
    762. nYPos = x - xi;
    763. dwOffset = nXPox * nWidth + nYPos;
    764. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    765. nXPox = y + xi;
    766. nYPos = x - yi;
    767. dwOffset = nXPox * nWidth + nYPos;
    768. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    769. //左上 1/4
    770. nXPox = y - yi;
    771. nYPos = x - xi;
    772. dwOffset = nXPox * nWidth + nYPos;
    773. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    774. nXPox = y - xi;
    775. nYPos = x - yi;
    776. dwOffset = nXPox * nWidth + nYPos;
    777. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    778. //右上 1/4
    779. nXPox = y - yi;
    780. nYPos = x + xi;
    781. dwOffset = nXPox * nWidth + nYPos;
    782. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    783. nXPox = y - xi;
    784. nYPos = x + yi;
    785. dwOffset = nXPox * nWidth + nYPos;
    786. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth && nIndex & 0x01) lpBits[dwOffset] = dwColor;
    787. if (di < 0)
    788. {
    789. di += 3 + (xi << 1);
    790. }
    791. else
    792. {
    793. di += 5 + ((xi - yi) << 1);
    794. yi--;
    795. }
    796. xi++;
    797. nIndex++;
    798. }
    799. }
    800. else
    801. {
    802. while (yi >= xi)
    803. {
    804. //右下 1/4
    805. nXPox = y + yi;
    806. nYPos = x + xi;
    807. dwOffset = nXPox * nWidth + nYPos;
    808. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    809. nXPox = y + xi;
    810. nYPos = x + yi;
    811. dwOffset = nXPox * nWidth + nYPos;
    812. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    813. //左下 1/4
    814. nXPox = y + yi;
    815. nYPos = x - xi;
    816. dwOffset = nXPox * nWidth + nYPos;
    817. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    818. nXPox = y + xi;
    819. nYPos = x - yi;
    820. dwOffset = nXPox * nWidth + nYPos;
    821. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    822. //左上 1/4
    823. nXPox = y - yi;
    824. nYPos = x - xi;
    825. dwOffset = nXPox * nWidth + nYPos;
    826. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    827. nXPox = y - xi;
    828. nYPos = x - yi;
    829. dwOffset = nXPox * nWidth + nYPos;
    830. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    831. //右上 1/4
    832. nXPox = y - yi;
    833. nYPos = x + xi;
    834. dwOffset = nXPox * nWidth + nYPos;
    835. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    836. nXPox = y - xi;
    837. nYPos = x + yi;
    838. dwOffset = nXPox * nWidth + nYPos;
    839. if (nXPox >= 0 && nXPox < nHeight && nYPos >= 0 && nYPos < nWidth) lpBits[dwOffset] = dwColor;
    840. if (di < 0)
    841. {
    842. di += 3 + (xi << 1);
    843. }
    844. else
    845. {
    846. di += 5 + ((xi - yi) << 1);
    847. yi--;
    848. }
    849. xi++;
    850. }
    851. }
    852. }
    853. }

    be468fac3d7844ceba488d08aa36c289.png

    CBitmapPaint: 位图操作绘制图形 1.绘制线条 2.绘制矩形边框 3.填充矩形区域 4.绘制圆形边框 5.绘制网格线条 并比较使用位图操作与使用GDI绘制的速度 (gitee.com)

     

  • 相关阅读:
    【Jmeter 简单使用】
    换低挡装置(Kickdown, ACM/ICPC NEERC 2006, UVa1588)rust解法
    flink学习-容错机制
    golang程序能不能用LD_PRELOAD进行hook?
    我的Go并发之旅、01 并发哲学与并发原语
    基于Keras搭建LSTM网络实现文本情感分类
    金和OA C6任意文件读取漏洞 复现[附POC]
    UFS Power Management 介绍
    [JS] canvas 详解
    mybatis的简单使用
  • 原文地址:https://blog.csdn.net/Flame_Cyclone/article/details/133162340