久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

無閃爍刷屏技術(shù)的實(shí)現(xiàn),VC技術(shù)文章,VC系列教程,VC

 wfsy1983 2010-10-26
當(dāng)我們需要在用戶區(qū)顯示一些圖形時(shí),,先把圖形在客戶區(qū)畫上,雖然已經(jīng)畫好但此時(shí)我們還無法看到,,還要通過程序主動(dòng)地刷新用戶區(qū),,強(qiáng)制Windows發(fā)送一條WM_PAINT消息,這將引發(fā)視類OnDraw函數(shù)簡(jiǎn)單地將所有的圖形對(duì)象重畫,,這樣才完成了圖形的顯示工作,,但在刷新的同時(shí)會(huì)引起較明顯的閃爍尤其是當(dāng)畫面面積較大、圖像元素過多時(shí)尤為明顯甚至達(dá)到無法正常工作的地步,。因此,,我們需要做相應(yīng)的處理。本文介紹了采用先在內(nèi)存中繪制圖形,,然后再把繪好的圖形以位圖方式從內(nèi)存拷貝到窗口客戶的消除刷屏閃爍的一種方法,。
一、 WM_PAINT消息和無效區(qū)
當(dāng)以下情況之一發(fā)生時(shí),,就要求應(yīng)用程序一定刷新其用戶區(qū)的一部分或全部:
1. 在用戶移動(dòng)窗口或顯示窗口時(shí),,窗口中先前被隱藏的區(qū)域重新可見。
2. 用戶改變窗口的大小,。
3. 滾動(dòng)窗口用戶區(qū),。
4. 程序調(diào)用InvalidateRect或InvalidateRgn函數(shù)顯式地發(fā)送一條WM_PAINT消息。
此時(shí)Windows會(huì)向窗口函數(shù)發(fā)送一條WM_PAINT消息,。另外,,當(dāng)Windows刪除覆蓋窗口部分區(qū)域的對(duì)話框或消息框時(shí)和菜單下拉出來又被釋放時(shí)窗口用戶區(qū)被臨時(shí)覆蓋,系統(tǒng)會(huì)試圖保存顯示區(qū)域,,但是不一定能成功,,可能向窗口函數(shù)發(fā)送一條WM_PAINT消息,要求應(yīng)用程序刷新其用戶區(qū),。需要說明的是:光標(biāo)或圖符穿過窗口用戶區(qū)時(shí),,也可能覆蓋顯示內(nèi)容,但這種情況下,,系統(tǒng)一定能保留并恢復(fù)被覆蓋的區(qū)域,,所以此時(shí)并不會(huì)發(fā)送WM_PAINT消息來要求應(yīng)用程序去刷新其顯示區(qū)。在Windows 應(yīng)用程序的窗口函數(shù)中,對(duì)WM_PAINT消息的處理就是刷新其用戶區(qū),,這是一種固定的程序結(jié)構(gòu),。為提高刷新效率,我們可以只刷新用戶區(qū)的一小部分,,其余沒有發(fā)生變化的我們可以不予刷新,,窗口函數(shù)可以通過調(diào)用函數(shù)InvalidateRect顯式地使用戶區(qū)內(nèi)的一個(gè)矩形無效。而且只有當(dāng)窗口客戶區(qū)的某一部分失效時(shí),,其窗口函數(shù)才會(huì)收到WM_PAINT消息,。
二、 刷屏閃爍的產(chǎn)生原因與解決方法
當(dāng)客戶區(qū)有所改動(dòng),,而又要將改動(dòng)顯示出來,,就必然要強(qiáng)制Windows發(fā)送一條WM_PAINT消息,從而引發(fā)OnDraw函數(shù)的重畫,,這樣雖完成了圖形的顯示,,卻也會(huì)引起較明顯的閃爍,當(dāng)畫面上數(shù)據(jù)不是很多時(shí)尚不明顯,,當(dāng)客戶區(qū)有成千上萬個(gè)點(diǎn)的時(shí)候刷新一次會(huì)引起整幅畫面的劇烈跳動(dòng),,尤其是對(duì)于許多實(shí)時(shí)監(jiān)控軟件和矢量電子地圖軟件,此類軟件通常在屏幕上都會(huì)動(dòng)輒幾千,、幾萬個(gè)要素點(diǎn),,很明顯單靠發(fā)送WM_PAINT 消息引發(fā)OnDraw 的重畫根本滿足不了實(shí)際需求。
為了解決上述問題,,我們需要做一些相應(yīng)的處理,。首先要先檢取無效區(qū),然后創(chuàng)建一個(gè)與原設(shè)備環(huán)境句柄pDC相兼容的內(nèi)存設(shè)備環(huán)境,,之后就可以采用在內(nèi)存中繪制圖形并把繪好的圖形以位圖方式從內(nèi)存拷貝到窗口客戶的方法來消除刷屏?xí)r引起的閃爍,。這還需要?jiǎng)?chuàng)建一個(gè)與原設(shè)備環(huán)境句柄pDC相兼容的、大小為整個(gè)客戶區(qū)的位圖,。然后再使新的設(shè)備環(huán)境dc與pDC具有同樣的映射關(guān)系,將位圖選入內(nèi)存環(huán)境,。再使dc的整個(gè)客戶區(qū)都成無效區(qū),,再"與上"所檢取的無效區(qū),使內(nèi)存環(huán)境與pDC檢取的無效區(qū)相等,。之后便可以進(jìn)行繪圖工作了,,繪圖完畢之后應(yīng)當(dāng)釋放所獲取的設(shè)備環(huán)境句柄pDC。否則會(huì)造成系統(tǒng)資源的浪費(fèi),。
三,、 程序示例
本示例程序通過打開任意存檔文件,將其ASCII碼碼值當(dāng)作要顯示的數(shù)據(jù),并通過一圖畫控件將其數(shù)據(jù)以圖形的形式依次顯示出來,。本程序要處理的數(shù)據(jù)量較大,,如不采用本文所述方法將會(huì)有很明顯的閃爍。
(1) 新建一基于CFormView的單文檔應(yīng)用程序WaveShower,。
(2) 在Form上添加一"picture"控件,設(shè)置其ID為IDC_SCREEN,、Type為Rectangle、Color為Black,。在"Extended Styles"屬性頁里選中Modal Frame檢查框,。
(3) 添加一菜單"打開數(shù)據(jù)文件",并生成其響應(yīng)函數(shù)OnOpenData(),。
(4) 在視類中添加如下成員變量:
int m_BufLen; //數(shù)據(jù)長(zhǎng)度
unsigned char* buffer; //數(shù)據(jù)緩存
int m_dx; //數(shù)據(jù)偏移量
int m_DY; //數(shù)據(jù)顯示區(qū)的幅度
CPoint* value; //將要顯示的數(shù)值
int m_DX; //數(shù)據(jù)顯示區(qū)的寬度
int m_Y0; //數(shù)據(jù)顯示區(qū)參照點(diǎn)位置
CRect rect; //數(shù)據(jù)顯示區(qū)矩形
(5) 在視類中添加函數(shù)GetScreenRect()用以獲取數(shù)據(jù)顯示區(qū)的大小及其他參數(shù),;添加函數(shù)CleanScreen()完成清除數(shù)據(jù)顯示區(qū)的功能;添加函數(shù)DrawPoint()以便在數(shù)據(jù)顯示區(qū)畫點(diǎn):
void CWaveShowerView::GetScreenRect()
{
CWnd* pStatic = GetDlgItem(IDC_SCREEN);
pStatic->GetWindowRect(&rect);
ScreenToClient(&rect);
rect.top+=4;
rect.left+=4;
rect.bottom-=4;
rect.right-=4;
m_Y0=(rect.bottom-rect.top)/2+rect.top;
m_DX=rect.Width();
m_DY=re ct.Height()/2;
value=new CPoint[m_DX];
}
void CWaveShowerView::CleanScreen()
{
CDC* pDC=GetDC();
CPen pen1(PS_SOLID,1,RGB(0,0,0));
CPen* oldPen1=pDC->SelectObject(&pen1);
for(int i=rect.top;i td>
{
pDC->MoveTo(rect.left,i);
pDC->LineTo(rect.right,i);
}
pDC->SelectObject(&oldPen1);
CPen pen2(PS_SOLID,1,RGB(0,0,255));
CPen* oldPen2=pDC->SelectObject(&pen2);
pDC->MoveTo(rect.left,m_Y0);
pDC->LineTo(rect.right,m_Y0);
pDC->SelectObject(&oldPen2);
ReleaseDC(pDC);
}
void CWaveShowerView::DrawPoint(CPoint pt, COLORREF color)
{
CDC* pDC=GetDC();
pDC->SetPixel(rect.left+pt.x,m_Y0-pt.y,color);
ReleaseDC(pDC);
}
(6) 在視類的OnInitialUpdate()初始化函數(shù)中添加代碼以進(jìn)行數(shù)據(jù)顯示的各項(xiàng)前期準(zhǔn)備工作,,并在"打開數(shù)據(jù)文件"菜單的響應(yīng)函數(shù)中添加代碼以讀取文件的內(nèi)碼,。
void CWaveShowerView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
GetScreenRect();
for(int i=0;i td>
value[i].x=value[i].y=0;
SetTimer(0,10,NULL);
}
void CWaveShowerView::OnOpenData()
{
CString FileName="";
CFile file;
CFileDialog dlg(TRUE,"*","*.*",
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
"所有文件(*.*)|*.*||",NULL);
if(dlg.DoModal()==IDOK)
{
KillTimer(1);
FileName=dlg.GetPathName();
file.Open(FileName,CFile::modeReadWrite);
m_BufLen=file.GetLength();
buffer= new unsigned char[m_BufLen+m_DX+10];
file.Read(buffer,m_BufLen);
file.Close();
SetTimer(1,10,NULL);
}
}
(7)下面添加的定時(shí)器響應(yīng)函數(shù)正是本文的重點(diǎn),為方便對(duì)比起見,,筆者寫了兩個(gè)OnTimer響應(yīng)函數(shù),,前一個(gè)是采用常規(guī)的普通方法描點(diǎn)的,運(yùn)行起來可以很明顯地看到畫面的閃爍跳動(dòng),。而后一種則是采用本文所述方法采用的內(nèi)存畫圖的方法,,運(yùn)行后幾乎畫面無閃爍。下面便是兩段對(duì)比代碼的原碼部分:
//代碼一:有閃爍的代碼
void CWaveShowerView::OnTimer(UINT nIDEvent)
{
if(nIDEvent==0)
{
CleanScreen();
for(int i=0;i td>
DrawPoint(value[i],RGB(0,255,0));
}
if(nIDEvent==1)
{
m_dx+=2;
for(int i=0;i td>
{
value[i].x=i;
if(m_dx+i<0)
buffer[m_dx+i]=128;
if(m_dx+i<-m_DX)
m_dx-=2;
if(m_dx+i>m_BufLen)
buffer[m_dx+i]=128;
if(m_dx+i>m_BufLen+m_DX)
m_dx-=2;
value[i].y=m_DY* (buffer[m_dx+i]-128)/256;
}
}
CFormView::OnTimer(nIDEvent);
}
//代碼二:無閃爍的代碼
void CWaveShowerView::OnTimer(UINT nIDEvent)
{
if(nIDEvent==0)
{
CDC* pDC=GetDC();
CDC dc;
CBitmap bitmap;
CBitmap* pOldBitmap;
CRect client;
pDC->GetCliPBox(client); //檢取無效區(qū)
//創(chuàng)建一個(gè)與pDC兼容的內(nèi)存設(shè)備環(huán)境
if(dc.CreateCompatibleDC(pDC))
{
//創(chuàng)建一與pDC兼容的位圖,,大小為整個(gè)客戶區(qū)
if(bitmap.CreateCompatibleBitmap(pDC,rect.Width(), rect.Height()))
{
//使dc與pDC具有同樣的映射關(guān)系
OnPrepareDC(&dc,NULL);
//將位圖選入內(nèi)存環(huán)境
pOldBitmap=dc.SelectObject(&bitmap);
//使dc的整個(gè)客戶區(qū)都成無效區(qū)
dc.SelectClipRgn(NULL);
//再"與上"檢取的無效區(qū),,使內(nèi)存環(huán)境與
//pDC檢取的無效區(qū)相等
dc.IntersectClipRect(client);
}
}
CleanScreen();
for(int i=0;i td>
DrawPoint(value[i],RGB(0,255,0));
dc.SelectObject(pOldBitmap);
ReleaseDC(pDC);
}
if(nIDEvent==1)
{
m_dx+=2;
for(int i=0;i td>
{
value[i].x=i;
if(m_dx+i<0)
buffer[m_dx+i]=128;
if(m_dx+i<-m_DX)
m_dx-=2;
if(m_dx+i>m_BufLen)
buffer[m_dx+i]=128;
if(m_dx+i>m_BufLen+m_DX)
m_dx-=2;
value[i].y=m_DY*(buffer[m_dx+i]-128)/256;
}
}
CFormView::OnTimer(nIDEvent);
}
(8)雖然通過上述幾步可以實(shí)現(xiàn)所有的功能,但為了防止內(nèi)存泄露和養(yǎng)成良好的編程習(xí)慣,,我們還須做些工作,,在視類的構(gòu)造函數(shù)中釋放我們?cè)?jīng)申請(qǐng)過的內(nèi)存以及定時(shí)器:
CWaveShowerView::~CWaveShowerView()
{
delete[] value;
KillTimer(0);
KillTimer(1);
}
四、 編譯運(yùn)行
編譯運(yùn)行此程序,,通過菜單選取需要顯示的文件(任意文件均可),,如在定時(shí)器響應(yīng)代碼中采用的是第一種代碼,則會(huì)看到數(shù)據(jù)顯示的同時(shí)伴隨著明顯的閃爍而采用后一種代碼編碼則會(huì)很平穩(wěn)的將數(shù)據(jù)顯示出來,。
結(jié)論:本文介紹的這種方法適用于各種牽扯到數(shù)組數(shù)據(jù)圖形顯示的程序,,比如監(jiān)控軟件、數(shù)據(jù)分析軟件,、測(cè)量軟件等等,,具有廣泛的應(yīng)用前景
文章出處:飛諾網(wǎng)(www.):http://dev./course/3_program/vc/vc_js/20100630/266084.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多