From c643599414d93afcdc1e504abd036c0ded899aac Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期五, 06 六月 2025 15:43:22 +0800
Subject: [PATCH] 1. 通过双缓冲解决CJobSlotGrid控件闪烁问题
---
SourceCode/Bond/Servo/Servo.vcxproj | 2 +
SourceCode/Bond/Servo/Servo.vcxproj.filters | 2 +
SourceCode/Bond/Servo/ServoMemDC.cpp | 40 ++++++++++++++++++++
SourceCode/Bond/Servo/ServoMemDC.h | 20 ++++++++++
SourceCode/Bond/Servo/JobSlotGrid.cpp | 31 ++++++++++++++-
5 files changed, 92 insertions(+), 3 deletions(-)
diff --git a/SourceCode/Bond/Servo/JobSlotGrid.cpp b/SourceCode/Bond/Servo/JobSlotGrid.cpp
index 46551e6..32243a9 100644
--- a/SourceCode/Bond/Servo/JobSlotGrid.cpp
+++ b/SourceCode/Bond/Servo/JobSlotGrid.cpp
@@ -1,5 +1,6 @@
锘�#include "stdafx.h"
#include "JobSlotGrid.h"
+#include "ServoMemDC.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -221,13 +222,15 @@
void CJobSlotGrid::OnPaint() {
CPaintDC dc(this);
- DrawGrid(&dc);
+ CServoMemDC memDC(&dc);
+ DrawGrid(&memDC);
}
void CJobSlotGrid::DrawGrid(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
+ pDC->FillSolidRect(&rect, ::GetSysColor(COLOR_3DFACE)); // 瀹夊叏鑳屾櫙鑹诧紝浠呭唴瀛樼粯鍒�
if (m_nCols == 0 || m_nRows == 0) {
return;
@@ -257,10 +260,12 @@
// 閫夋嫨濉厖棰滆壊
COLORREF fillColor = m_vSlotStatus[i][j] ? m_colorHasJob : m_colorNoJob;
if (IsSlotClickable(i, j)) {
- if (bIsClicking)
+ if (bIsClicking) {
fillColor = COLOR_CLICK;
- else if (bIsHover)
+ }
+ else if (bIsHover) {
fillColor = COLOR_HOVER;
+ }
}
// 缁樺埗鑳屾櫙锛堥珮鏁堟浛浠� CBrush锛�
@@ -269,6 +274,26 @@
// 缁樺埗杈规
pDC->DrawEdge(&cellRect, EDGE_SUNKEN, BF_RECT);
+ // 濡傛灉鏄彲鐐瑰嚮鏍煎瓙锛屽湪宸︿笂瑙掔敾涓�涓皬鍦嗙偣
+ if (IsSlotClickable(i, j)) {
+ constexpr int DOT_RADIUS = 3;
+ int cx = cellRect.left + 5;
+ int cy = cellRect.top + 5;
+
+ // 淇濆瓨鏃х瑪鍜屽埛瀛�
+ CBrush brushDot(RGB(0, 120, 215));
+ CBrush* pOldBrush = pDC->SelectObject(&brushDot);
+ CPen penDot(PS_SOLID, 1, RGB(0, 120, 215));
+ CPen* pOldPen = pDC->SelectObject(&penDot);
+
+ // 缁樺埗鍦嗙偣
+ pDC->Ellipse(cx - DOT_RADIUS, cy - DOT_RADIUS, cx + DOT_RADIUS, cy + DOT_RADIUS);
+
+ // 鎭㈠
+ pDC->SelectObject(pOldBrush);
+ pDC->SelectObject(pOldPen);
+ }
+
// 鑾峰彇鏂囧瓧锛堝畨鍏級
CString strText;
if (i < m_vSlotText.size() && j < m_vSlotText[i].size()) {
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index a6f4ee0..6a9a993 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -319,6 +319,7 @@
<ClInclude Include="ServoCommo.h" />
<ClInclude Include="ServoDlg.h" />
<ClInclude Include="ServoGraph.h" />
+ <ClInclude Include="ServoMemDC.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TerminalDisplayDlg.h" />
@@ -444,6 +445,7 @@
<ClCompile Include="Servo.cpp" />
<ClCompile Include="ServoDlg.cpp" />
<ClCompile Include="ServoGraph.cpp" />
+ <ClCompile Include="ServoMemDC.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index f99065e..0ce3503 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -157,6 +157,7 @@
<ClCompile Include="CSlot.cpp" />
<ClCompile Include="CRobotTaskDlg.cpp" />
<ClCompile Include="PageTransferLog.cpp" />
+ <ClCompile Include="ServoMemDC.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AlarmManager.h" />
@@ -319,6 +320,7 @@
<ClInclude Include="CSlot.h" />
<ClInclude Include="CRobotTaskDlg.h" />
<ClInclude Include="PageTransferLog.h" />
+ <ClInclude Include="ServoMemDC.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/ServoMemDC.cpp b/SourceCode/Bond/Servo/ServoMemDC.cpp
new file mode 100644
index 0000000..d22e949
--- /dev/null
+++ b/SourceCode/Bond/Servo/ServoMemDC.cpp
@@ -0,0 +1,40 @@
+#include "stdafx.h"
+#include "ServoMemDC.h"
+
+CServoMemDC::CServoMemDC(CDC* pDC, const CRect* pRect)
+ : CDC(), m_pOldBitmap(nullptr), m_pDC(pDC), m_bMemDC(FALSE)
+{
+ ASSERT(pDC != nullptr);
+
+ if (pRect == nullptr)
+ pDC->GetClipBox(&m_rect);
+ else
+ m_rect = *pRect;
+
+ if (CreateCompatibleDC(pDC)) {
+ m_bMemDC = TRUE;
+ m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
+ m_pOldBitmap = SelectObject(&m_bitmap);
+ SetWindowOrg(m_rect.left, m_rect.top);
+ }
+}
+
+CServoMemDC::~CServoMemDC()
+{
+ if (m_bMemDC) {
+ // 将内存 DC 拷贝回原始窗口 DC
+ m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
+ this, m_rect.left, m_rect.top, SRCCOPY);
+ SelectObject(m_pOldBitmap);
+ }
+}
+
+CServoMemDC* CServoMemDC::operator->()
+{
+ return this;
+}
+
+CServoMemDC::operator CDC* ()
+{
+ return this;
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/ServoMemDC.h b/SourceCode/Bond/Servo/ServoMemDC.h
new file mode 100644
index 0000000..7717b1f
--- /dev/null
+++ b/SourceCode/Bond/Servo/ServoMemDC.h
@@ -0,0 +1,20 @@
+#pragma once
+#include <afxwin.h> // MFC 核心头文件
+
+// CServoMemDC:双缓冲绘图封装类(消除闪烁)
+class CServoMemDC : public CDC
+{
+public:
+ CServoMemDC(CDC* pDC, const CRect* pRect = nullptr); // 构造:传入目标 DC 和区域
+ ~CServoMemDC(); // 析构:自动拷贝到目标 DC
+
+ CServoMemDC* operator->();
+ operator CDC* ();
+
+private:
+ CBitmap m_bitmap; // 用于内存 DC 的位图
+ CBitmap* m_pOldBitmap; // 旧位图
+ CDC* m_pDC; // 原始绘图 DC(窗口)
+ CRect m_rect; // 绘图区域
+ BOOL m_bMemDC; // 是否启用了内存 DC(CreateCompatibleDC 成功)
+};
\ No newline at end of file
--
Gitblit v1.9.3