程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> VC++部件庫中浮動菜單部件的解析及應用

VC++部件庫中浮動菜單部件的解析及應用

編輯:關於VC++

圖象的漸顯/漸隱是十分重要的圖象效果,廣泛運用於圖象處理和多媒提娛樂軟件。漸顯/漸隱算法設計的最大困難是速度控制,包括定時和快速改變圖象中各象素的顏色。如采用普通的全圖掃描算法,則速度較慢,很難真正體現漸顯/漸隱效果。

利用Windows(3.x.95/98/NT)操作系統特殊的調色板管理和時間碼定時機制能設計出有效的圖象漸顯/漸隱算法。Windows提供一種被稱為調色板動畫(paletteanimation)的顏色處理技術,它通過快速改變顏色調色板中所選取的表項中的顏色能模擬顏色的變化。設置時間碼,定時調用該技術使圖象顏色漸變就能實現圖象的漸顯和漸隱。

一、調色板動畫

在VisualC++中實現調色板動畫依賴於MFC類庫提供的CPalette類和CDC類中的若干成員函數,其基本步驟如下:

調用CPalette::CreatePalette(LPLOGPALETTElpLogPalette)函數創建邏輯調色板,注意將參數LPLOGPALETTE所指向的各顏色表項結構的peFlags域設置為PC_RESERVED,以防止其它窗口同該調色板匹配顏色。調用CDC::SelectPalette和CDC::RealizePalette函數選擇和實現所創建的邏輯調色板;調用CPalette::AnimatePalette函數改變顏色,實現調色板動畫;動畫完成後應恢復系統調色板。

CPalette::AnimatePalette是其中最關鍵的函數,其原型如下:

void AnimatePalette( UINT nStartIndex, //起始的表項號 UINT nNumEntries,//變化的表項數 LPPALETTEENTRY lpPaletteColors ); //邏輯調色板表項指針——lpPaletteColors為指向PALETTEENTRY結構的指針,其中存儲著邏輯調色板將要更新的顏色信息。PALETTEENTRY結構定義如下:typedef struct tagPALETTEENTRY { // pe
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;

peRed、peGreen、peBlue分別表示邏輯調色板項的R、G、B顏色分量值。peFlags應被置為PC_RESERVED。

nStartIndex為lpPaletteColors中將變化的起始表項號,nNumEntries

為lpPaletteColors中將變化的表項數。

二、時間碼定時

CWnd::SetTimer函數可設置一個系統時間碼,並指定每經過一定的時間間隔使Windows系統發送一個WM_TIMER消息到窗口的消息隊列中。窗口在每當接收到相應的WM_TIMER消息時做一定的處理,便實現了定時處理。

通常應在窗口的消息循環中接受和處理WM_TIMER消息,這樣將很難編制通用的定時操作。通用的定時操作應將定時處理封裝在一個函數中,而不與其它的代碼糾纏在一起。筆者實現這一技術的技巧是,在循環操作中截獲窗口消息,如消息為指定的時間碼消息,則進行定時處理;否則分發消息給窗口消息處理機制。如果定時操作已結束,則修改循環標志,退出循環。具體的代碼如下:....................................
//設置時間碼,pWnd為處理定時操作的窗口對象指針
pWnd- >SetTimer(0x100, uTimeOut, NULL);
//屏蔽鼠標操作,使定時操作不受影響
pWnd- >SetCapture();
//開始定時操作
BOOL bDone = FALSE;
MSG msg;
while (! bDone)
{
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_TIMER && msg. WParam == 0x100)
{
.......................
定時操作代碼
.......................
//如定時操作完成,則設置循環標志,結束操作
if (定時操作完成)
bDone = TRUE;
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
//釋放鼠標
::ReleaseCapture();
//刪除時間碼
pWnd- >KillTimer(0x100);
................................

函數PeekMessage截獲窗口消息,TranslateMessage和DispatchMessage函數解釋和分發除指定時間碼消息之外的所有消息,以避免丟失消息。

三、漸顯

漸顯就是將顯示顏色由黑色(RGB(0,0,0))逐漸變化為圖象各象素的顏色的過程。開始時調用CPalette::GetPaletteEntries函數保存圖象調色板的

各邏輯表項信息,然後調用CPalette::SetPaletteEntries函數將邏輯調色板中各邏輯表項的peRed、peGreen、peBlue置為0,定時調用CPalette::Anima-tePalette,每次將各邏輯表項的peRed、peGreen、peBlue值增加一個變化量,直到它們分別等於圖象邏輯調色板中各邏輯表項的peRed、peGreen、peBlue值。

下面的函數FadeIn通過對調色板顏色表項中的各顏色分量值先設為0,然後進行遞增,直到所有顏色值都恢復成原調色板中顏色值來實現漸顯。  // 圖象漸顯效果
// 參數:
// pWnd -顯示圖象的窗口
// pPal -調色板指針
// nDeta -各顏色分量的減小量
// uTimeOut -時間的變化量
void FadeIn(CWnd *pWnd, CPalette *pPal, int nDeta, UINT uTimeOut)
  {
//保留原來的調色板顏色表項
int nTotalColors = pPal- >GetEntryCount();
PALETTEENTRY PaletteColors0[256];
pPal- >GetPaletteEntries(0, nTotalColors, PaletteColors0);
  //先將調色板表項中各顏色分量置為0
PALETTEENTRY PaletteColors1[256];
for (int i=0; i< nTotalColors; ++i)
{
PaletteColors1[i].peRed = 0;
PaletteColors1[i].peGreen = 0;
PaletteColors1[i].peBlue = 0;
PaletteColors1[i].peFlags = PC_RESERVED;
}
pPal- >SetPaletteEntries(0, nTotalColors, PaletteColors1);
pPal- >AnimatePalette(0, nTotalColors, PaletteColors1);
  //設置時間碼
pWnd- >SetTimer(0x100, uTimeOut, NULL);
  //開始漸顯
pWnd- >SetCapture();
BOOL bDone = FALSE;
MSG msg;
while (! bDone)
{
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_TIMER && msg.wParam == 0x100)
{
CClientDC dc(pWnd);
CPalette *pOldPal = dc.SelectPalette(pPal, FALSE);
dc.RealizePalette();
  //遞增各顏色分量
PALETTEENTRY PaletteColors[256];
pPal- >GetPaletteEntries(0, nTotalColors, PaletteColors);
BOOL bRedZero=FALSE;
BOOL bGreenZero=FALSE;
BOOL bBlueZero=FALSE;
for (int i=0; i< nTotalColors; ++i)
{
if (PaletteColors[i].peRed + nDeta <
PaletteColors0[i].peRed)
{
PaletteColors[i].peRed += nDeta;
bRedZero = FALSE;
}
else if (PaletteColors[i].peRed + 1 <
PaletteColors0[i].peRed)
{
PaletteColors[i].peRed++;
bRedZero = FALSE;
}
else
bRedZero = TRUE;
if (PaletteColors[i].peGreen + nDeta <
PaletteColors0[i].peGreen)
{
PaletteColors[i].peGreen += nDeta;
bGreenZero = FALSE;
}
else if (PaletteColors[i].peGreen + 1 <
PaletteColors0[i].peGreen)
{
PaletteColors[i].peGreen++;
bGreenZero = FALSE;
}
else
bGreenZero = TRUE;
  if (PaletteColors[i].peBlue + nDeta <
PaletteColors0[i].peBlue)
{
PaletteColors[i].peBlue += nDeta;
bBlueZero = FALSE;
}
else if (PaletteColors[i].peBlue +1 <
PaletteColors0[i].peBlue)
{
PaletteColors[i].peBlue++;
bBlueZero = FALSE;
}
else
bBlueZero = TRUE;
}
//直到恢復原始值結束
bDone = bRedZero && bGreenZero && bBlueZero;
//使系統改變調色板
pPal- >AnimatePalette(0, nTotalColors, PaletteColors);
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
::ReleaseCapture();
pWnd- >KillTimer(0x100);
  //恢復原始調色板
pPal- >SetPaletteEntries(0, nTotalColors, PaletteColors0);
pPal- >AnimatePalette(0, nTotalColors, PaletteColors0);
}

四、漸 隱

漸隱就是將顯示顏色由圖象各象素的顏色逐漸變化為黑色(RGB(0,0,0))的過程,即定時調用CPalette::AnimatePalette,每次將各邏輯表項的peRed、peGreen、peBlue值減小一個變化量,直到它們都為0。

下面的函數FadeOut通過對調色板顏色表項中的各顏色分量值進行遞減,直到所有顏色值都變成0(即黑色)來實現漸隱。// 圖象漸隱效果
// 參數:
// pWnd -顯示圖象的窗口
// pPal -調色板指針
// nDeta -各顏色分量的減小量
// uTimeOut -時間的變化量
void FadeOut(CWnd *pWnd, CPalette *pPal, int nDeta, UINT uTimeOut)
{
//保留原來的調色板顏色表項
int nTotalColors = pPal- >GetEntryCount();
PALETTEENTRY PaletteColors0[256];
pPal- >GetPaletteEntries(0, nTotalColors, PaletteColors0);
//設置時間碼
pWnd- >SetTimer(0x100, uTimeOut, NULL);
//開始漸隱
pWnd- >SetCapture();
BOOL bDone = FALSE;
MSG msg;
while (! bDone)
{
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_TIMER && msg.wParam == 0x100)
{
CClientDC dc(pWnd);
CPalette *pOldPal = dc.SelectPalette(pPal, FALSE);
dc.RealizePalette();
PALETTEENTRY PaletteColors[256];
pPal- >GetPaletteEntries(0, nTotalColors, PaletteColors);
BOOL bRedZero=FALSE;
BOOL bGreenZero=FALSE;
BOOL bBlueZero=FALSE;
//遞減顏色分量
for (int i=0; i< nTotalColors; ++i)
{
if (PaletteColors[i].peRed > nDeta)
{
PaletteColors[i].peRed -= nDeta;
bRedZero = FALSE;
}
else if (PaletteColors[i].peRed > 1)
{
PaletteColors[i].peRed--;
bRedZero = FALSE;
}
else
bRedZero = TRUE;
if (PaletteColors[i].peGreen > nDeta)
{
PaletteColors[i].peGreen -= nDeta;
bGreenZero = FALSE;
}
else if (PaletteColors[i].peGreen > 1)
{
PaletteColors[i].peGreen--;
bGreenZero = FALSE;
}
else
bGreenZero = TRUE;
if (PaletteColors[i].peBlue > nDeta)
{
PaletteColors[i].peBlue -= nDeta;
bBlueZero = FALSE;
}
else if (PaletteColors[i].peBlue > 1)
{
PaletteColors[i].peBlue--;
bBlueZero = FALSE;
}
else
bBlueZero = TRUE;
}
//如所有顏色分量都為0,則結束漸隱
bDone = bRedZero && bGreenZero && bBlueZero;
//使系統改變調色板
pPal- >AnimatePalette(0, nTotalColors, PaletteColors);
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
::ReleaseCapture();
pWnd- >KillTimer(0x100);
//恢復原始調色板
pPal- >SetPaletteEntries(0, nTotalColors, PaletteColors0);
pPal- >AnimatePalette(0, nTotalColors, PaletteColors0);
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved