【发布时间】:2014-04-27 21:25:17
【问题描述】:
我正在使用 VisualStudio 2010,使用 C++/CLI 进行编码,并通过 GDI 完成所有图形。我有一个小应用程序,可以连续绘制添加了一些噪声的高斯曲线。就像我在post 中指出的那样,每个点都是实时添加的。
现在,我的任务是创建一个小的彩色区域,我可以缩小和增加它以选择部分情节并进行一些数学运算。
这种任务由MouseMove 事件管理,就像这样:
System::Void Form1::pictureBox1_MouseMove(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) {
//Recalculate the position of the area,
//clean up the old one and redraw a new.
}
它确实有效,但我遇到了一些图形“错误”。
如您所见,当我移动该区域时,它下面的所有内容都被删除了。网格在这里只是因为它是静态的,每次重绘绿色区域时我都会刷新它。
实际上它不是一个错误,肯定它必须这样。对我来说,这有点明显。我这样称呼它是因为它不是我所期望的。
我在问是否有通往绿色区域的方法,就好像它在不同的图层上一样。这样,我就可以在情节运行时移动绿色区域而不会被擦除。
我尝试处理 2 个HDC 变量并在第一个变量上绘制图形和网格,在第二个变量上绘制绿色区域,但它似乎不起作用。
你有什么好主意来克服这种(对我来说)糟糕的行为——也许是一些多层的东西或其他一些奇特的解决方案——还是我应该放弃并等待重新绘制?
谢谢大家给我答复! :)
编辑: 这是我绘制数据系列的方式:
for(int i = 1; i<=1000; i++ ) {
Gauss[i] = safe_cast<float>(Math::Round( a*s*Math::Exp(-Math::Pow(((0.01*1*(i))-portante), 2)/b), 2));
Rumore[i] = safe_cast<float>(Math::Round(r*generatore->NextDouble(), 2));
SelectObject(hdcPictureBox, LinePen);
MoveToEx(hdcPictureBox, i-1+50, 500-convY*(Gauss[i-1]+Rumore[i-1])+50, NULL);
LineTo(hdcPictureBox, i+50, 500-convY*(Gauss[i]+Rumore[i])+50);
e1 = (i+k)%1000; //Buffer
if(i>DXX-54 && i<SXX-54) {
//ErasePen1 = CreatePen(PS_SOLID, 1, RGB(216,191,216));
label1->Text = Convert::ToString(i);
label1->Refresh();
SelectObject(hdcPictureBox, ErasePen1);
}
else {
SelectObject(hdcPictureBox, ErasePen);
}
//HPEN ErasePen1 = CreatePen(PS_SOLID, 1, RGB(216,191,216));
MoveToEx(hdcPictureBox, e1+50, 500-convY*(Gauss[e1]+Rumore[e1])+50, NULL);
LineTo(hdcPictureBox, e1+1+50, 500-convY*(Gauss[e1+1]+Rumore[e1+1])+50);
}
DXX 和 SXX 是区域的 X 坐标 - DXX 开始,SXX 结束。
这就是我处理MouseMove 的方式。 Do_Chan 和 Do_Clean 本质上是一回事。 Do_Clean 使用背景颜色绘制更大的区域以擦除旧区域并允许 Do_Chan 绘制新区域。
System::Void Form1::pictureBox1_MouseMove(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) {
if(e->Button == System::Windows::Forms::MouseButtons::Left) {
double span100 = (SXX-DXX)*85/100;
if (e->X > DXX+((SXX-DXX)/2)-15 && e->X < DXX+((SXX-DXX)/2)+15 && (e->Y >30 && e->Y <50)
|| e->X >DXX+((SXX-DXX)/2)-span100/2 && e->X < DXX+((SXX-DXX)/2)+span100/2 && (e->Y >50 && e->Y <550)) {
HBRUSH brush = CreateSolidBrush(RGB(245,255,250));
Do_Clean(hdcPictureBox, DXX, SXX, brush);
double spawn = SXX-DXX;
DXX = e->X - spawn/2;
SXX = e->X + spawn/2;
if(DXX < 50) {
DXX = 51;
}
if(SXX >1050 ) {
SXX = 1049;
}
spawn = SXX - DXX;
CXX = DXX + spawn/2;
HBRUSH brush1 = CreateSolidBrush(RGB(166,251,178));
Do_Chan(hdcPictureBox2, DXX, SXX, brush1);
int k = 4;
int e1 = 0;
for(int i = 1; i<=1000; i++) {
SelectObject(hdcPictureBox, LinePen);
MoveToEx(hdcPictureBox, i-1+50, 500-250*(Gauss[i-1]+Rumore[i-1])+50, NULL);
LineTo(hdcPictureBox, i+50, 500-250*(Gauss[i]+Rumore[i])+50);
e1 = (i+k)%1000; //Buffer
if(i>DXX-54 && i<SXX-54) {
//ErasePen1 = CreatePen(PS_SOLID, 1, RGB(216,191,216));
SelectObject(hdcPictureBox, ErasePen1);
}
else {
SelectObject(hdcPictureBox, ErasePen);
}
//HPEN ErasePen1 = CreatePen(PS_SOLID, 1, RGB(216,191,216));
MoveToEx(hdcPictureBox, e1+50, 500-250*(Gauss[e1]+Rumore[e1])+50, NULL);
LineTo(hdcPictureBox, e1+1+50, 500-250*(Gauss[e1+1]+Rumore[e1+1])+50);
}
}
}
}
如您所见,在我绘制了新区域之后,我重新绘制了数组 Gauss+Rumore 的所有点。 这就是 Do_Chan(Do_Clean 相同)的工作原理:
void Do_Chan(HDC hdc, int dx, int sx, HBRUSH brush) {
//i = 250, y = 50
int y = 50;
int spawn = sx - dx;
HPEN pen = CreatePen(PS_SOLID, 1, RGB(245, 255, 250));
HPEN penC = CreatePen(PS_DOT, 1, RGB(0, 0, 0));
/*Fai il rettangolo */
SelectObject(hdc, pen);
SelectObject(hdc, brush);
POINT punti[4];
punti[0].x = dx;
punti[0].y = y;
punti[1].x = dx +spawn;
punti[1].y = y;
punti[2].x = dx + spawn;
punti[2].y = y+500;
punti[3].x = dx;
punti[3].y = y+500;
Polygon(hdc, punti, 4);
Ellipse(hdc, dx-10, y-20, dx+10, y);
SelectObject(hdc, penC);
MoveToEx(hdc, dx+spawn/2, 50,NULL);
LineTo(hdc, dx+spawn/2, 550);
SelectObject(hdc, pen);
SelectObject(hdc, brush);
Ellipse(hdc, dx-10+spawn/2, y-20, dx+10+spawn/2, y);
SelectObject(hdc, pen);
SelectObject(hdc, brush);
Ellipse(hdc, dx-10+spawn, y-20, dx+10+spawn, y);
//Plot the axis and the grid
}
【问题讨论】:
-
使用计时器并在那里进行所有绘图。您正在尝试以 2 种不同的方式访问同一个 hdc,这会给您带来这种效果
-
嗨!感谢您的回答!。你的意思是this计时器吗?
-
发布您的代码。我们来解决问题
-
我想我找到了解决方案。每次触发 MouseMove 时,我都会清理旧区域,绘制新区域并重新绘制我的系列。这可能是一个解决方案吗?
-
视情况而定。你是怎么画这个系列的?