2009-08-19 60 views
2

我以前沒有繪製winform的經驗,我想繪製心電圖的一種形式。或者讓一個特定區域的正弦波或任何波函數,但我正在做的是心電圖。其餘的形式將與按鈕和標籤的正常形式,在Winforms中繪製心電圖

任何人都可以很好地通過一個教程

:)

回答

2

你有幾個選擇,您可以編寫自己的控制,將處理數據並對其進行渲染。對於更復雜的情節,這可能有點複雜,但基本總是相同的,設置X和Y值範圍,然後用GDI從左到右畫一條線,沒有什麼奇特。因爲這對於更高級的功能可能會有點複雜,您可以使用一些製圖控件,我會閱讀this文章或查看codeproject.com,我記得,我看到很少有人試圖寫一些像樣的製圖控件,它們是開源,新的文章可能會在WPF中編碼,但你應該找到更老的東西。
編輯:
,你可以找到一些有用的鏈接:Graph plotting lib that's main goal is to simulate ECGanother graph plotting lib

+0

感謝很多:) – Moon 2009-08-20 04:31:26

1

您需要創建一個自定義的控制。

public class MyECGDrawer : Control{} 

在裏面,你重寫OnPaint事件

protect override OnPaint(PaintEventArgs pe){} 

然後在漆功能,您繪製的圖形,你想要的方式,讓我們說的sin(x)

// refresh background 
pe.Graphics.FillRectangle(Brushes.White, 0, 0, Width, Height); 
int prevX = -1, prevY = -1; 
for(int x = 0; x < Width; x++) 
{ 
    if(prevX >= 0) 
    { 
     pe.Graphics.DrawLine(Pens.Black, prevX, prevY, x, Math.sin(x)); 
    } 
    prevX = x; 
    prevY = Math.sin(x); 
} 

要強制重新繪製ECG,請調用控件上的.Invalidate()函數。您應該能夠從設計器中拖放表單中的控件。

最終,類會是什麼樣子

公共類MyECGDrawer:控制{}

在裏面,你重寫OnPaint事件

public class MyECGDrawer : Control 
{ 
protect override OnPaint(PaintEventArgs pe) 
{ 
    // refresh background 
    pe.Graphics.FillRectangle(Brushes.White, 0, 0, Width, Height); 
    int prevX = -1, prevY = -1; 
    for(int x = 0; x < Width; x++) 
    { 
     if(prevX >= 0) 
      pe.Graphics.DrawLine(Pens.Black, prevX, prevY, x, Math.sin(x)); 
     prevX = x; 
     prevY = Math.sin(x); 
    } 
} 
} 
+0

感謝很多:) – Moon 2009-08-20 04:28:15

0

除非你是做這個作爲學習經驗,您可能需要考慮在這裏查看免費的Microsoft Chart Controls for .NET。

http://www.microsoft.com/downloads/details.aspx?FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c&displaylang=en#QuickInfoContainer

話雖這麼說,我想,如果你想推出自己提出了以下原則。

  1. 創建一個用戶控件來封裝繪圖渲染,而不是直接在窗體上渲染。
  2. 在你的控制中,公開屬性來獲取/設置你想要渲染的數據並添加任何你想控制渲染的屬性(縮放,平移,顏色等)
  3. 在你控制中,覆蓋OnPaint方法或爲Paint事件創建事件處理程序。這些方法將有一個PaintEventArgs對象傳遞給它們,它包含一個Graphics對象作爲屬性。 Graphics對象的方法用於在需要繪製時將控制點,線條等渲染到控件上。大多數繪圖操作需要一支筆(輪廓/線條)或畫筆(填充區域)。您可以使用庫存對象進行這些操作(例如Pens.Black或Brushes.Red),或者您可以創建自己的(請參閱文檔)。如果您創建自己的對象,請確保在使用它們之後處理它們(例如,使用「using」語句或通過調用Dispose)。

上有GDI +一對夫婦的好書。如果你深入研究,我建議選擇一個。

+0

感謝很多:) – Moon 2009-08-20 04:34:04

1

我寫下了以下內容並進行了測試。它似乎是做你想做的事情,但請注意,它只是簡單地將sin(x)繪製在一個循環中,沒有任何延遲 - 即sin(x)的繪圖流很快就會很快看不到它。但是,您可以在循環內的任何一行中放置一箇中斷,然後使用F5逐步循環以查看其效果 - 大概您的流式心電圖數據只能以某種固定速度到達,所以這不應該成爲您實施時的問題。

在下面,monitor是一個WinForms窗體上的PictureBox。其他一切都是本地的。

private void drawStream(){ 
    const int scaleX = 40; 
    const int scaleY = 40; 
    Point monitorTopLeft = new Point(0, 0); 
    Point MonitorTopLeftMinus1 = new Point(-1, 0); 

    int halfX = monitor.Width/2; 
    int halfY = monitor.Height/2; 
    Size size = new Size(halfX + 20, monitor.Height); 

    Graphics g = monitor.CreateGraphics(); 
    g.TranslateTransform(halfX, halfY); 
    g.ScaleTransform(scaleX, scaleY); 
    g.Clear(Color.Black); 
    g.ResetClip(); 

    float lastY = (float)Math.Sin(0); 
    float y = lastY; 
    Pen p = new Pen(Color.White, 0.01F); 
    float stepX = 1F/scaleX; 

    for (float x = 0; x < 10; x += stepX) { 
    g.CopyFromScreen(monitor.PointToScreen(monitorTopLeft), MonitorTopLeftMinus1, size, CopyPixelOperation.SourceCopy); 
    y = (float)Math.Sin(x); 
    g.DrawLine(p, -stepX, lastY, 0, y); 
    lastY = y; 
    } 
} 

一些額外的信息可能會有所幫助:

  1. 在一個圖片框的原點開始 出在左上角。 TranslateTransform允許您將 翻譯(即移動)原點。 在這個例子中,我翻譯了它的一半圖片框的寬度和 一半高度的 。
  2. ScaleTransform改變了圖框的放大倍數 - 請注意,它甚至放大了用於在圖框上繪製的筆的寬度 - 這就是爲什麼筆的寬度設置爲0.01。
  3. CopyFromScreen執行一個bitblt。它的源點是相對於屏幕,目標是相對於圖片框和移動矩形的大小無視任何轉換(如我們添加的縮放和轉換轉換)。
  4. 注意,X座標在DrawLine的方法是-stepx和0所有的繪製基本上發生右y軸(即,X = 0),然後CopyFromScreen移動引出部向左側以使其「流」關往左邊。
+0

@克里斯法官:大多數美國心電圖的是25mm /秒和海外,你可以得到50毫米/ S(或在心臟重症監護病房或遙測美國地板)。所以,如果你在〜10ms(大概40-50ms)內進行睡眠,那麼假設96dpi的速率大概是正確的。 – user7116 2009-08-20 14:44:46