none
兩個Form的PictureBox更新顯示延遲問題 RRS feed

  • 問題

  • 各位好

    我想做一個監視系統畫面,有分成兩個視窗,左邊MainForm這個是顯示兩個大監視畫面,右邊是由MainForm new 出來的MultiForm顯示各個監視畫面

    每個視窗的顯示都是使用PictureBox,一直帶入監視器給的Bmp檔來做畫面更新,解析度也一樣是640*480

    但遇到了一個問題是,當MainForm設定選擇A、B畫面,並點MainForm讓他不反灰,MultiForm的A、B畫面會變遲鈍顯示,如果選擇MultiForm變成MainForm的A、B畫面顯示遲鈍,請問這是為什麼?謝謝各位!


    2019年8月20日 上午 01:06

所有回覆

  • 預設在 Windows Client 會略為加速主視窗,Windows Server 則不會。

    你的 Multi Form 如果不是串流直接更新 (你說是更新 Bmp) ,則更新前先關閉螢幕更新,更新完後再啟用螢幕更新。

    參考這篇:

    https://tlcheng.wordpress.com/2015/02/28/vbnet-%e5%bf%ab%e9%80%9f%e5%91%88%e7%8f%be%e7%b8%ae%e6%94%be%e9%81%b8%e6%93%87%e6%a1%86/


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年8月20日 下午 03:52
  • 預設在 Windows Client 會略為加速主視窗,Windows Server 則不會。

    你的 Multi Form 如果不是串流直接更新 (你說是更新 Bmp) ,則更新前先關閉螢幕更新,更新完後再啟用螢幕更新。

    參考這篇:

    https://tlcheng.wordpress.com/2015/02/28/vbnet-%e5%bf%ab%e9%80%9f%e5%91%88%e7%8f%be%e7%b8%ae%e6%94%be%e9%81%b8%e6%93%87%e6%a1%86/


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    謝謝回答,我有嘗試著停用面更新,DoubleBuffer,記憶體繪圖,但沒辦法改善我點選哪個Form哪個Form就比較流暢這個問題,請問還有什麼方法可以嘗試嗎?謝謝
    2019年8月22日 上午 02:58
  • 那篇的重點在 SuspendLayout 跟相關指令。

    跟 DoubleBuffer / 記憶體繪圖 沒啥關係


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年8月22日 上午 11:00
  • 想要快速解决问题或得到针对性的回复,最佳的做法是提供你现有的代码或可以重现问题的demo,只描述现象是很难得到帮助的。

    感謝提醒。以下是我的程式碼

    首先我會將攝影機的資料透過下面的Code做處理

    public void Copy(IntPtr data)
            {
                //Console.WriteLine("copy on.....");            
                mu.WaitOne();
                SRCdata = SRCImage.LockBits(SRCImageRect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
                SRCPtr = SRCdata.Scan0;
    
                if (ImageBand == 1)
                    OriSRCdata = OriSRCImage.LockBits(OriSRCImageRect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
                else
                    OriSRCdata = OriSRCImage.LockBits(OriSRCImageRect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
    
                OriSRCPtr = OriSRCdata.Scan0;
                OverlapPicdata = OverlapPic.LockBits(OverlapPicRect, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
                OverlapPicPtr = OverlapPicdata.Scan0;
    
                if (ImageBand == 1)
                {
                    //iLength = ImageWidth * ImageHeight;
                    unsafe
                    {
                        byte* src = (byte*)data;
                        byte* dst = (byte*)SRCPtr;
                        byte* dst2 = (byte*)OriSRCPtr;
                        byte* Judge = (byte*)OverlapPicPtr;
    
                        k = 0;
                        for (int i = 0; i < iLength; i++)
                        {
                            //B
                            *(dst + k) = *(src + i);
                            k++;
                            //G
                            *(dst + k) = *(src + i);
                            k++;
                            //R
                            *(dst + k) = *(src + i);
                            k++;
    
                            *(dst2 + i) = *(src + i);
                        }
                    }
                }
                else if (ImageBand == 3)
                {
                    //iLength = ImageWidth * ImageHeight ;
                    unsafe
                    {
                        byte* src = (byte*)data;
                        byte* dst = (byte*)SRCPtr;
                        byte* dst2 = (byte*)OriSRCPtr;
                        byte* Judge = (byte*)OverlapPicPtr;
    
                        k = 0;
                        q = 0;
                        for (int i = 0; i < iLength; i++)
                        {
                            //B
                            if (*(Judge + i) == 0)//黑色區塊
                            {
                                *(dst + k) = *(src + (q + 2));
                                //byte a = *(dst + k);
                                //byte b = *(src + (q + 2));
                            }
                            else if (*(Judge + i) == 255)//白色區塊                        
                                *(dst + k) = 46;                                                
                            *(dst2 + k) = *(src + (q + 2));
                            k++;
                            //G
                            if (*(Judge + i) == 0)
                            {
                                *(dst + k) = *(src + (q + 1));
                                //byte a = *(dst + k);
                                //byte b = *(src + (q + 1));
                            }
                            else if (*(Judge + i) == 255)
                                *(dst + k) = 46;
                            *(dst2 + k) = *(src + (q + 1));
                            k++;
                            //R
                            if (*(Judge + i) == 0)
                            {
                                *(dst + k) = *(src + (q));
                                //byte a = *(dst + k);
                                //byte b = *(src + q);
                            }
                            else if (*(Judge + i) == 255)
                                *(dst + k) = 255;
                            *(dst2 + k) = *(src + (q));
                            k++;
    
                            ////Alpha
                            //if (*(Judge + i) == 0)
                            //    *(dst + k) = 255;//255=全透明,0=不透明
                            //else if (*(Judge + i) == 255)
                            //    *(dst + k) = 255;
                            //k++;
                            q = q + 3;
                        }
                    }
                }
    
                OriSRCImage.UnlockBits(OriSRCdata);
                SRCImage.UnlockBits(SRCdata);
                OverlapPic.UnlockBits(OverlapPicdata);
                Invalidate();
                mu.ReleaseMutex();
    
                //GC.Collect();
            }

    觸發OnPaint去重繪

    protected override void OnPaint(PaintEventArgs pe)
            {
                UpdateFinalImage();
                base.OnPaint(pe);
            }

    private void UpdateFinalImage()
            {
                mu.WaitOne();
    
                //BitmapOverlap(OverlapPic);
    
                if (magnification == Magn._fit)
                {
                    //0,0是畫在console的起始XY座標
                    graImage.DrawImage(SRCImage, 0, 0, Image.Width, Image.Height);
                }
                else if (magnification == Magn._025)
                {
                    graImage.DrawImage(SRCImage, ConsRect, cropRectx025, GraphicsUnit.Pixel);
                }
                else if (magnification == Magn._05)
                {
                    graImage.DrawImage(SRCImage, ConsRect, cropRectx05, GraphicsUnit.Pixel);
                }
                else if (magnification == Magn._one)
                {
                    graImage.DrawImage(SRCImage, ConsRect, cropRectx1, GraphicsUnit.Pixel);
                }
                else if (magnification == Magn._double)
                {
                    graImage.DrawImage(SRCImage, ConsRect, cropRectx2, GraphicsUnit.Pixel);
                }
                else if (magnification == Magn._four)
                {
                    graImage.DrawImage(SRCImage, ConsRect, cropRectx4, GraphicsUnit.Pixel);
                }
    
                mu.ReleaseMutex();
    
                //畫中心大十字
                if (CenCross != null && OVCenterCrossShow)
                    CenCross.Draw(graImage);
    
                //畫十字標定            
                foreach (Rect obj in list_Obj)
                {
                    DrawRect(obj);
                }
    
                //畫線            
                foreach (Line obj in list_Line)
                {
                    DrawLine(obj);
                }
    
                //HitRect visible為true才畫上去
                if (HitRect.Visible)
                    HitRect.Draw(graImage);
    
                
                if (bMaskVisible)
                {
                    foreach (BaseOV obj in list_Mask)
                    {
                        obj.Draw(graImage);
                    }
                }
            }

    再麻煩各位幫我看看,為什麼這樣更新會有延遲的問題,感謝!


    • 已編輯 魏高個 2019年8月26日 上午 01:04
    2019年8月26日 上午 01:03
  • 那篇的重點在 SuspendLayout 跟相關指令。

    跟 DoubleBuffer / 記憶體繪圖 沒啥關係


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    再麻煩大大幫我看一下我這樣的寫法有什麼問題,感謝!
    2019年8月26日 上午 01:05
  • 非必要不要用 OnPaint 事件,因為隨便一個遮罩動作,例如滑鼠從上方移過,就會持續觸發 OnPaint ,會很吃效能。

    先確認你甚麼時候要重繪,如果是定時重繪,在 Timer 事件處理,不要動 OnPaint 。

    不在 OnPaint 事件處理時,繪圖就可能被滑鼠洗掉,所以就要改記憶體繪圖,繪完後再指給 PictureBox

    你要疊圖固定內容的話,可以先準備好 emf ,直接用 DrawImage 疊上去,或是固定不變的內容,先畫成 32 bits Bitmap 後,用 DrawImage 疊上去。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年8月26日 下午 12:18