我在picture control控制元件里面作圖,通過從串口里面獲得的x、y坐標把點實時畫在picture control控制元件里面。我開始畫圖的時候發現最小化之后以前畫的圖就沒有了,所以才通過看孫鑫老師的視頻,通過用ptrArray的方式,把坐標實時增加到里面,然后每次畫圖都遍歷里面的點進行畫圖。結果發現畫圖延遲太高了,得等好大一會才會顯示出來,并且cpu占用率由原來的6%左右猛增到30%左右,請問這是問什么呢?謝謝大家!
我所有的畫圖都是在on paint 程式里面執行的
void CComElvesDlg::OnPaint()
{
//extern int x_lc;
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (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
{
int rgb1, rgb2, rgb3;
CDialog::OnPaint();
CRect rect;
CWnd *pWin = GetDlgItem(IDC_PIC);//獲取該控制元件的指標,就可以對該控制元件直接操作了
pWin->GetClientRect(rect);//把控制元件的長寬、坐標等資訊保存在rect里
CDC *pDc = pWin->GetDC();//獲取該控制元件的畫布
//有了畫布,下面可以自由的畫圖了,想怎么畫就怎么話,
//設定字體
pDc->SetBkMode(TRANSPARENT); //設定背景透明
CFont *pFont = GetFont();
CPen cu;
cu.CreatePen(PS_SOLID, 5, RGB(0, 0, 0));//紅色,5像素寬
CPen* oldPen = pDc->SelectObject(&cu);
pDc->SelectObject(oldPen);
cu.DeleteObject();
for (int i = 0;i < m_ptrArray.GetSize();i++)
{
if (1 == ((CGraph*)m_ptrArray.GetAt(i))->m_color)
{
rgb1 = 0;
rgb2 = 0;
rgb3 = 255;
}
if (0 == ((CGraph*)m_ptrArray.GetAt(i))->m_color)
{
rgb1 = 255;
rgb2 = 0;
rgb3 = 0;
}
CPen huatu;
huatu.CreatePen(PS_SOLID, 5, RGB(rgb1, rgb2, rgb3));//紅色,5像素寬
pDc->SelectObject(&huatu);
pDc->MoveTo(((CGraph*)m_ptrArray.GetAt(i))->m_xLocation, ((CGraph*)m_ptrArray.GetAt(i))->m_yLocation + 1);
pDc->LineTo(((CGraph*)m_ptrArray.GetAt(i))->m_xLocation, ((CGraph*)m_ptrArray.GetAt(i))->m_yLocation);
pDc->SelectObject(oldPen);
huatu.DeleteObject();
}
//畫X坐標軸
CPen x_zuobiao;
x_zuobiao.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//藍色,2像素寬
pDc->SelectObject(&x_zuobiao);
pDc->MoveTo(0, rect.bottom);
pDc->LineTo(rect.right+20, rect.bottom);
pDc->SelectObject(oldPen);
x_zuobiao.DeleteObject();
//畫Y坐標軸
CPen y_zuobiao;
y_zuobiao.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//藍色,2像素寬
pDc->SelectObject(&y_zuobiao);
pDc->MoveTo(0, rect.bottom);
pDc->LineTo(0, -20);
pDc->SelectObject(oldPen);
y_zuobiao.DeleteObject();
//
//畫X箭頭
CPen x_jiantou;
x_jiantou.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//藍色,2像素寬
pDc->SelectObject(&x_jiantou);
pDc->MoveTo(rect.right + 20, rect.bottom);
pDc->LineTo(rect.right + 10, rect.bottom-5);
pDc->MoveTo(rect.right + 20, rect.bottom);
pDc->LineTo(rect.right + 10, rect.bottom + 5);
pDc->SelectObject(oldPen);
x_jiantou.DeleteObject();
kedumingcheng_font(pDc, pFont); //選定字體
pDc->TextOut((rect.right) / 2, rect.bottom + 30, _T("水平位置"));
pDc->SelectObject(pFont);//恢復原來字體
//畫Y箭頭
CPen y_jiantou;
y_jiantou.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//藍色,2像素寬
pDc->SelectObject(&y_jiantou);
pDc->MoveTo(0, -20);
pDc->LineTo(-5, -10);
pDc->MoveTo(0, -20);
pDc->LineTo(5,-10);
pDc->SelectObject(oldPen);
y_jiantou.DeleteObject();
//畫X刻度
CPen x_kedu;
x_kedu.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//藍色,2像素寬
pDc->SelectObject(&x_kedu);
for (int i = 0; i <= rect.right; i=i+30)
{
CString str1;
str1.Format(_T("%d"), i);
kedu_font(pDc, pFont); //指定字體
pDc->TextOut(i-5, rect.bottom + 10, str1);
pDc->SelectObject(pFont);//恢復原來字體
pDc->MoveTo(i , rect.bottom);
pDc->LineTo(i , rect.bottom+5);
}
pDc->SelectObject(oldPen);
x_kedu.DeleteObject();
//畫Y軸刻度
CPen y_kedu;
y_kedu.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//藍色,2像素寬
pDc->SelectObject(&y_kedu);
for (int i = rect.bottom; i >= 0; i = i - 30)
{
CString str1;
str1.Format(_T("%d"), rect.bottom - i);
kedu_font(pDc, pFont); //指定字體
pDc->TextOut(- 20, i, str1);
pDc->SelectObject(pFont);//恢復原來字體
pDc->MoveTo(0, i);
pDc->LineTo(-5, i);
}
pDc->SelectObject(oldPen);
y_kedu.DeleteObject();
ReleaseDC(pDc);
}
}
下面是串口接收部分
LRESULT CComElvesDlg::OnReceive(WPARAM ch, LPARAM port)
{
if (port <= 0 || port > 4)
return -1;
m_RCount++; //接收的位元組計數
CString strTemp;
strTemp.Format("%ld",m_RCount);
strTemp="RX:"+strTemp;
m_ctrlRCount.SetWindowText(strTemp); //顯示接收計數
if (1000 == m_RCount)
{
m_rData.Empty();
}
if(!m_bShow) //如果選擇了“停止顯示”接收資料,則回傳
return -1; //注意,這種情況下,計數仍在繼續,只是不顯示
/*if(m_CRData.GetLineCount()>400)
{
m_rData.Empty();
m_rData="https://bbs.csdn.net/topics/***The Length of the Text is too long, Emptied Automaticly!!!***/r/n";
UpdateData(FALSE);
}*/
//如果選擇了"十六進制顯示",則顯示十六進制值
CString str;
CString str2;
CString str3;
CString str4;
CString str5;
if(m_bRHex)
str.Format("%02X ",ch);
else
str.Format("%c",ch);
//以下是將接收的字符加在字串的最后,這里費時很多
//但考慮到資料需要保存成檔案,所以沒有用List Control
int nLen=m_CRData.GetWindowTextLength();
m_CRData.SetSel(nLen, nLen);
m_CRData.ReplaceSel(str);
nLen+=str.GetLength();
UpdateData(true);
str1 = str1 + str;
int x_intResult;
int y_intResult;
int c_intResult;
if ("\n" == str)
{
str2 = str1.GetAt(0);
}
if ("d"==str2)
{
str3 = str1.Mid(1);
x_intResult = atoi(str3);
x_lc = x_intResult;
if ("p" == str2)
{
str4 = str1.Mid(1);
y_intResult = atoi(str4);
y_lc = y_intResult;
}
if ("s" == str2)
{
str5 = str1.Mid(1);
c_intResult = atoi(str5);
c_lc = c_intResult;
}
str1 = "";
}
// CGraph graph(x_lc, y_lc, c_lc);
// m_ptrArray.Add(&graph);
CGraph *pGraph=new CGraph(x_lc, y_lc, c_lc);
m_ptrArray.Add(pGraph);
SaveRMod();
SetDlgItemText(IDC_PIC, NULL);
CRect rect;
GetDlgItem(IDC_PIC)->GetWindowRect(&rect);
ScreenToClient(&rect);
InvalidateRect(&rect, FALSE);
UpdateWindow();
return 0;
}
uj5u.com熱心網友回復:
加一個點的同時 畫出這個點而CGraph *pGraph=new CGraph(x_lc, y_lc, c_lc);
m_ptrArray.Add(pGraph);
這個m_ptrArray 是為 repaint 準備的,
你現在 是 加一個點 pic 重合 一次 ?
uj5u.com熱心網友回復:
這個東西很難了,下載一些虛擬示波器的代碼吧,里面講究的東西非常多。uj5u.com熱心網友回復:
我明白您說的什么意思了,我應該只在最小化之后的重繪那個函式里才呼叫這個ptrarray,其余時候只需要挨個點畫就可以了。那請問一下,我需要把這個m_ptrArray寫在哪個函式里呢?謝謝您了!uj5u.com熱心網友回復:
我想在最小化之后呼叫的那個函式里面來寫我的重繪內容,請問應該在哪一個函式里面寫呢?uj5u.com熱心網友回復:
InvalidateRect 后 就不要再 UpdateWindow,如果資料很多, 建議只繪制最后的部分資料
uj5u.com熱心網友回復:
只繪制最后部分的話前面的就消失了,還是達不到效果,我這部分需要重繪的內容最好放在哪里面呢?uj5u.com熱心網友回復:
m_ptrArray 是給 OnPaint 用的 ,可以放 pic 的 OnPaint 中。// Pic 派生至 Cstatic你 現在的代碼 是 在 主 對話框 中 畫 Pic ,所以才有
int rgb1, rgb2, rgb3;
CDialog::OnPaint(); // 對話框 默認 才用
uj5u.com熱心網友回復:
點多了,自然就慢了。如果多想想辦法,還有可以變通的。我提過一個思路:
為了容易描述問題,把已經畫好的部分稱作A,后面一邊接收一邊畫的稱為B
在重繪視窗之前,將A的影像保存為記憶體影像
重繪后,即時將記憶體影像A貼圖(注意橫坐標通常需要壓縮一下),接著畫B部分。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/147872.html
標籤:基礎類
上一篇:求幫助!怎么能先用(MM_HIMETRIC)模式畫出1:200的一條豎線。然后再用MM_ANISOTROPIC可以調節大小
