使用PictureBox时的性能问题 [英] Performance issue while using PictureBox

查看:229
本文介绍了使用PictureBox时的性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Visual Studio 2010中编写一个应用程序,我在C ++ / CLI中编码。

在我以前的问题中,我遇到了来自串行端口的数据系列问题。现在它似乎确定,现在我试图绘制它们。

我不想使用图表,所以我想使用手工制作使用类 Graphics 的函数。为了测试我的代码,我创建了两个数组:第一个数组填充了来自高斯的值。第二个用随机数填充。

当我绘制值时,我想看到我的情节正在增长和更新,就像示波器。第二个 Do_Plot 设法通过BackColor绘制它们的删除点。
所有的代码工作原理,但我遇到问题的性能。如果我在我的PC上运行代码,我的系列是每500/700毫秒绘制。

有时它会减慢到1500毫秒,然后它回来更快。

我试图运行我的同事Pc和我注意到系列是每170ms绘制在第一个,而系列绘制每950ms在第二个。
这是代码:

I'm working on an application in Visual Studio 2010 and I'm coding in C++/CLI.
In my previous questions I had issue with data series from a serial port. Now it seems ok and now I'm trying to plot them.
I don't want to use Chart, so I would like to use handmade functions that use the class Graphics. In order to test my code, I created two arrays: the first one is filled with values coming from a Gaussian. The second one is filled with random numbers.
When I plot the values, I would like to see my plot growing and updating just like an oscilloscope. The second Do_Plot manages to "remove point" plotting them by the BackColor. All the code works as intended but I'm experiencing problem with performances. If I run the code on my Pc, my series is plotted every 500/700 ms.
Sometimes it slows down to 1500ms and then it comes back faster.
I tried to run the code on my coworkers' Pc and I noticed the series is plotted every 170ms on the first one, whereas the series is plotted every 950ms on the second one. This is the code:

System::Void Form1::button1_Click(System::Object^  sender, System::EventArgs^  e) {
    button1->Enabled = false;

    array<float,1>^ Gauss = gcnew array<float,1>(1001);

    array<float,1>^ Rumore = gcnew array<float,1>(1001);


     /*Some useful variables*/
     Random^ generatore = gcnew Random;
     float a = safe_cast<float>(Math::Round(5/(SIGMA*Math::Sqrt(2*PI)), 2));
     float b = safe_cast<float>(2*(SIGMA*SIGMA));

      /*Start */


      float portante; 
      float r;
      float s;

      int convX =1000/1000;
      int convY =500/2;  

      /*time variables */  

      int bias = 50;
      int dif =600;  

      /*Gap between drawing and removing*/  

      int k = 3; 
      int e1 = 0;


     for ( ; ; ) {

          /*Start*/
          clock_t Start = clock();

          if(textBox1->Text==""){
            portn = 5;
          }
          else
            portn = float::Parse(textBox1->Text);

          /*temp variables to go out the for cycle */
          portante = portn;
          r = rand;
          s = sig;

          /ckeck state is OK */
          check = 0;


            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));
                bool clipSup = ClipSup(2, Gauss[i]+Rumore[i]);

                if(clipSup==true) {
                    Gauss[i] = 1.99f;
                    Rumore[i] = 0;
                }
                Do_Plot(g, disegna, i-1, Gauss[i-1]+Rumore[i-1], i, Gauss[i]+Rumore[i], convX, convY);


                e1 =(k+i)%1000;
                Do_Plot(g, rimuovi, e1, Gauss[e1]+Rumore[e1], e1+1, Gauss[e1+1]+Rumore[e1+1], convX, convY);




                /*Ckeck if go out for cycle*/
                if(check == CODE_1 ) {
                    portante = portn;
                    break;
                }
                if(check == CODE_2 ) {
                    r = rand;
                    break;
                }
                if(check == CODE_3 ) {
                    s = sig;
                    break;
                }

            }

             clock_t Stop = clock();
             int Diff = Stop-Start;
             label8->Text = Convert::ToString(Diff);
             int tempDiff = (Stop-Start)+bias;
             if(tempDiff>dif)
             {

                //Do_Axes(g);           /*Do Axes*/
                //Do_Grid(g);           /*Do Grid */
                Application::DoEvents();
                dif = 600;
                bias = 0;
            }
            else
                bias +=50; //Else bias grows
      }


}

Do_Plot 是:

void Do_Plot(Graphics^ g, Pen^ penna, int Xi, float Yi, int Xf, float Yf, int convX, int convY) {


    g->DrawLine(penna, (convX*Xi+50), safe_cast<int>(500-(Yi*convY)+50), 
        (convX*Xf+50), safe_cast<int>(500-(Yf*convY)+50)); 
}

我已宣布 Graphics ^ g 这里:

public ref class Form1 : public System::Windows::Forms::Form
{
Graphics^ g; 
public:
    Form1(void) 
    {
        InitializeComponent();
        //
        //TODO: aggiungere qui il codice del costruttore.
        //
        g = pictureBox1->CreateGraphics();

    }



至少我不知道为什么我的代码工作如此不同当它运行在另一个Pc。我认为问题是 g = pictureBox1-> CreateGraphics(); 但我只是做一些假设。任何种类的帮助将真正感谢因为我从上一周卡在这一个!

非常感谢

Emiliano

Onestly I don't know why my code works so differently when it runs on another Pc. I think the problem is g = pictureBox1->CreateGraphics(); but I'm just doing some hypothesis. Any kind of help would be really appreciated cause I'm stuck on this one since the previous week!!
Thanks a lot!
Emiliano

推荐答案

我将给你c / c ++中的代码。然后将在c ++ / cli中找到如何做它

I am going to give you the code in c/c++. Will then find how to do it in c++/cli

首先初始化我们将使用的对象(button_click的开始):

First initialize the objects we will use (begining of button_click):

RECT rt = {0, 0, 1200, 600};
HBITMAP hBitmap = NULL;
HPEN hLinePen = NULL;
HDC hdcPctrBox = NULL, hdc = NULL, hdcMemTempImage = NULL;
HBRUSH hBrush = NULL;
POINT arrayPnt[1000]; //array of points

hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
hdcMemTempImage = CreateCompatibleDC(hdc);

hBitmap = CreateCompatibleBitmap(hdc, 1200, 600);  
SelectObject(hdcMemTempImage, hBitmap);  

hLinePen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); //width of pen = 1,and color (255, 0, 0)
SelectObject(hdcMemTempImage, hLinePen);

hBrush = CreateSolidBrush(RGB(100, 100, 255)); //color of picturebox

然后:

for ( ; ; ) {
    /*Start*/
    clock_t Start = clock();

    FillRect(hdcMemTempImage, &rt, hBrush); //clear the hdcMemTempImage with the picturebox color
    //your code continues...

for(int i = 1; i <= 1000; i ++)中一次添加一个点:

arrayPnt[i - 1].x = X; //calculate X
arrayPnt[i - 1].x = Y; ////calculate Y

最后我们绘制它,在for循环之后,clock_t Stop (我们不需要Do_Plot()):

And finaly we draw it, after the for loop and before the clock_t Stop (we dont need the Do_Plot()):

Polyline(hdcMemTempImage, &arrayPnt, 1000);
BitBlt(hdcPctrBox, 0, 0, 1200, 600, hdcMemTempImage, 0, 0, SRCCOPY);

clock_t Stop = clock();
//your code continues...

编辑:使用您的原始代码>您不需要 Do_Plot()添加此代码,而不需要 rt,hBitmap,hBrush,hdcMemTempImage,arrayPnt和hdc

use your original code(you dont need rt, hBitmap, hBrush, hdcMemTempImage, arrayPnt and hdc) and instead of calling Do_Plot() add this code:

//create two pens, one with the color you want hLinePen, and another with the color of picturebox hLinePenErase
//inside for(int i = 1; i<=1000; i++)
(some code...)
if(clipSup==true) {
    Gauss[i] = 1.99f;
    Rumore[i] = 0;
}

SelectObject(hdcPctrBox, hLinePen); //the pen to draw the line
MoveToEx(hdcPctrBox, xStart, yStart, NULL); //start point of line
LineTo(hdcPctrBox, xEnd, yEnd); //end point of line

SelectObject(hdcPctrBox, hLinePenErase); //the pen to erase the line
MoveToEx(hdcPctrBox, xStartErase, yStartErase, NULL); //start point of line to erase
LineTo(hdcPctrBox, xEndErase, yEndErase); //end point of line to erase
(code continues...)

您的资源:

HPEN hLinePen = NULL, hLinePenErase = NULL, originalPen = NULL;
HDC hdcPctrBox = NULL;

hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
originalPen = SelectObject(hdcPctrBox, GetStockObject(DC_PEN));
//create the two pens

//in the end release resources
SelectObject(hdcPctrBox, originalPen);
DeleteObject(hLinePen);
DeleteObject(hLinePenErase);
ReleaseDC(hwndPctrBox, hdcPctrBox);

valter

这篇关于使用PictureBox时的性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆