0

MFC を使用してインタラクティブなグラフを作成する必要があります

これはイコライザー コントロールのようなもので、ユーザーはイコライザー上のポイントをクリックしてドラッグし、y 軸の値を変更できるはずです。

私もMFCを学び始めたばかりです

ここまでは、ダイアログ ボックスにグラフを描画する関数を使用CPaintDCしてきました。OnPaint()今のところ、グラフは非常に単純で、四角形の境界が白で塗りつぶされ、グラフ上に 4 つの点があります。OnMouseMove()カーソルがグラフ領域内にあるかどうかを知るために関数を使用OnLButtonDown()し、ユーザーがクリックした場所を知るために関数を使用します。ユーザーがその位置でグラフ ポイントの y 軸の値を変更したいことを意味する位置をクリックした場合は、内部を使用Invalidate()して呼び出して図を再描画します。OnPaint()OnLButtonDown(). ただし、グラフを更新する必要があるたびに、ちらつきが見られます。今は問題ありませんが、このグラフを拡張して、少なくとも 64 個の変更可能なポイントがあり、移動したい場所をクリックするだけでなく、ドラッグしてポイントの y 軸の値を変更できるようにする必要があります。ポイントの数を増やし、グラフの外観を複雑にすると、ちらつきの問題は増えますか? グラフには、後で軸、グリッド線、ラベルなどが必要になります。ちらつきは気にする必要がありますか?それを防ぐ方法はありますか?

----UPDATE ----
これは、CodeDreamerの提案をどのように理解したかに応じて、OnPaint()関数を更新した方法です

void Cgraph_on_dlgboxDlg::OnPaint()
{
     CPaintDC dc_blt(this);
     CDC dc;
     CBitmap bmpDC;

     CRect rcClient;
     GetClientRect(rcClient);

    if (IsIconic())
    {
        // CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }

     dc.CreateCompatibleDC(&dc);
     bmpDC.CreateCompatibleBitmap(&dc, theGraph.width,theGraph.height );
     dc.SelectObject(&bmpDC);

    CPen pen;
    COLORREF pencolour = RGB(0, 0, 0);
    COLORREF brushcolour = RGB(0, 0, 255);
    COLORREF graphColour = RGB(0, 0, 150);

    // Draw boarder
    pen.CreatePen(PS_SOLID, 3, pencolour);
    // CBrush brush(HS_CROSS, brushcolour);
    dc.SetBkMode(TRANSPARENT);
    dc.SetMapMode(MM_TEXT);
    dc.SetViewportOrg(theGraph.x1, theGraph.y1);
     dc.SelectObject(&pen);

    // Draw graph boundary
    CPoint point1(0,0);
    point1.x = 0;
    point1.y = 0;
    CPoint point2(0,0);
    point2.x = point1.x + theGraph.width;
    point2.y = point1.y + theGraph.height;
    dc.Rectangle(CRect(point1, point2));
    pen.DeleteObject();

    // Draw Horizontal at 0
    pen.CreatePen(PS_SOLID, 1, pencolour);
    dc.SelectObject(&pen);
    dc.MoveTo(0, theGraph.height - ORG_DIST_FROM_BOTTOM);
    dc.LineTo(theGraph.width, theGraph.height - ORG_DIST_FROM_BOTTOM);
    pen.DeleteObject();

    dc.SetViewportOrg(theGraph.x1, theGraph.y1 + theGraph.height - ORG_DIST_FROM_BOTTOM); // dc.SetViewportOrg() always works relative to the clinet origin

    // Draw graph line
    pen.CreatePen(PS_SOLID, 2, graphColour);
    dc.SelectObject(&pen);
    for(int i = 0; i<NUM_OF_SECTIONS_IN_GRAPH; i++){
        dc.MoveTo(graphSamplePoints[i].x, graphSamplePoints[i].y);
        dc.LineTo(graphSamplePoints[i+1].x, graphSamplePoints[i+1].y);
    }

    // draw circles at graph sample points
    for(int i = 0; i<NUM_OF_POINTS_IN_GRAPH; i++){
        CIRCLE(dc, graphSamplePoints[i].x, graphSamplePoints[i].y, GRP_SMP_RAD);        
    }

    // dc_blt.BitBlt(0,0,rcClient.Width(), rcClient.Height(), &dc, 0, 0, SRCCOPY);
    dc_blt.BitBlt(theGraph.x1,theGraph.y1,theGraph.width, theGraph.height, &dc, 0, 0, SRCCOPY);

}

ビューポートの原点を何度も変更する必要がありますが、これがエラーの原因の 1 つになっている可能性があります。どんな提案でも大歓迎です。
これは私の出力がダブルバッファリングなし
ここに画像の説明を入力
でどのように見えるかです これは私のダブルバッファリングの試みでどのように見えるかです

ここに画像の説明を入力

4

2 に答える 2

2

この場合、一般的な解決策は「ダブル バッファリング」です。あらかじめ描画用の互換メモリdcを作成しておき、描画が終了したら画面dcに出力するのが原則です。

コードサンプルを以下に示します。

//in OnPaint() function
CPaintDC dc(this);    
CDC dcMem;
CBitmap bmpDC;

CRect rcClient;
GetClientRect(&rcClient);

dcMem.CreateCompatibleDC(pDC);
bmpDC.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height());
dcMem.SelectObject(&bmpDC);

CRect rect(0, 0, 100, 200);
dcMem.Rectangle(rect);

dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);

いくつかの参考文献を以下に示します。

前書き

別の参照

これが少し役立つことを願っています。

于 2013-07-04T07:45:54.647 に答える
0

CMemDC MFC クラスを試してください。

OnPaintFunction では、次のようになります。

  CPaintDC   DC(this);
  CMemDC mDC(&DC, this);
  // now use mDC instead of DC

また、より多くのサンプルと説明については、こちらをご覧ください。

于 2013-07-04T08:57:02.767 に答える