gpt4 book ai didi

c++ - 在 C++ MFC 应用程序中绘制图形

转载 作者:行者123 更新时间:2023-11-30 02:34:04 31 4
gpt4 key购买 nike

我正在编写 C++ MFC 应用程序来控制制造环境中的机器。此应用还需要在非常短的周期时间内分析大量信息。

出于测试目的和长期维护,我需要能够在控制台上绘制来自传感器的数据。我可能完全忽略了一个选项(请随意提出其他选项),但我的研究让我使用图片控件。

我通过使用 OnPaint() 成功地在这个控件中绘制。我的问题是我需要每隔几秒重新绘制一张新图像,而且我不能重复调用 OnPaint() 或向它传递数据。

如何创建一个可用于在图片控件上重复绘制的新函数?此外,这是我第一次涉足 MFC 应用程序,因此请在适当的级别上进行解释。谢谢!

class CPicture : public CStatic
{
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
};


BEGIN_MESSAGE_MAP(CPicture, CStatic)
ON_WM_PAINT()
END_MESSAGE_MAP()


void CPicture::OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SelectStockObject(BLACK_BRUSH);
dc.Rectangle(5, 50, 1000, 51);
}

我想问题是如何以及在哪里访问它

//Picture
class CPicture : public CStatic
{
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
vector<Coordinates> GraphData;
};

void CPicture::OnPaint()
{
// device context for painting
CPaintDC dc(this);

// save current brush
CBrush *pOldBrush = (CBrush*)dc.SelectStockObject(BLACK_BRUSH);

int NumPoints = GraphData.size() - 1;

for (int N = 0; N <= NumPoints; N++) {
dc.Rectangle(GraphData[N].x, GraphData[N].y, GraphData[N].x, GraphData[N].y);
}

// select original brush into device contect
dc.SelectObject(pOldBrush);
}

最佳答案

您可以调用Invalidate()当新数据到达时由您控制,或使用 RedrawWindow()强制立即重绘:

CPicture myPicture;

myPicture.Invalidate();

myPicture.RedrawWindow();

I cannot call OnPaint() repetitively or pass data to it.

要传递数据,可以在 CPicture 类(或程序中的其他地方)中声明包含数据的结构,然后可以从 OnPaint( ):

struct myData {
int value1;
int value2; // or an array, or some other data structure
}

class CPicture : public CStatic
{
DECLARE_MESSAGE_MAP()
public:

myData m_data;
afx_msg void OnPaint();
};

OnPaint()中(你也应该选择原来的刷回设备上下文以避免资源泄漏):

void CPicture::OnPaint()
{
CPaintDC dc(this); // device context for painting

// save current brush
CBrush *pOldBrush = (CBrush*)dc.SelectStockObject(BLACK_BRUSH);
// check pOldBrush - could be NULL

// dc.Rectangle(5, 50, 1000, 51);
// access m_data here, for example
dc.Rectangle(m_data.value1, m_data.value2, 1000, 51);

// select original brush into device contect
dc.SelectObject(pOldBrush);
}

更新(使用线程):

假设如下(来自评论):

  • 对于主线程,您有一个对话框 CLongbowDlg

  • 对于图形,您有一个派生自 CStaticPicControl,并且该控件位于对话框中。

  • 从主线程开始,工作线程开始读取数据。

PicControl and CLongbowDlg are defined in the same header, but are independent of each other. I need to be able to call Invalidate() or RedrawWindow() from inside CLongbowDlg's functions because they represent the primary thread.

我将尝试在这里对其中一种可能性进行简短描述,因为这实际上应该是一个单独的问题。

首先,PicControl 的对象必须是 CLongbowDlg 的成员,我假设是这种情况(我们称它为 m_PicControl) - 因此,在 CLongbowDlg 类中:

PicControl m_PicControl;

对于数据(我将使用上面的 myData 作为示例数据):在您的主线程(对话框)中,创建一个 myData 类型的变量: m_data(对于更大的数据,您可以在堆上分配空间,或使用 CArray 或其他一些容器):

myData m_data;

PicControl中创建一个类型为myData*的成员变量,并在PicControl构造函数中将其设置为NULL。

myData *m_pData;

OnInitDialog()(主对话框)中,为 m_picControl 提供指向数据的指针(或者最好在 PicControl 中创建一个函数来执行此操作):

m_picControl.m_pData = &m_data;

启动工作线程时,还为其提供指向 m_data 的指针和/或指向对话框本身的指针 (this)。

确保使用临界区保护数据。

当数据进来时,工作线程可以通过提供的指针写入数据。

PicControl::OnPaint()中,可以通过m_pData访问相同的数据。

要启动重绘,有几种方法:

  • PicControl 或主对话框中使用计时器,并在每次计时器触发时调用 Invalidate()

  • 为了控制工作线程的重绘(例如,当一定数量的新数据到达时),可以使用 PostMessage() 将消息发布到主对话框(使用启动线程时提供的指针 - this 指针)。

    要接收消息,您必须在主对话框中创建一个消息处理程序,然后从那里调用 m_picControl 上的 Invalidate()(您也可以发布一个直接向 PicControl 发送消息,但我更喜欢通过主窗口执行此操作)。

关于c++ - 在 C++ MFC 应用程序中绘制图形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34858622/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com