裝飾你的Title Bar
發表時間:2024-05-15 來源:明輝站整理相關軟件相關文章人氣:
[摘要]Windows 98的發布給熱衷于UI的用戶帶來了福音,它內嵌的Plus!,動態彈出的菜單與ToolTip,更有那顏色漸變的Title Bar給我們增添了許多的樂趣。其實即便是在Windows 95下也能使你的程序的Title Bar更具有個人魅力,在Norton Utilities for 95...
Windows 98的發布給熱衷于UI的用戶帶來了福音,它內嵌的Plus!,動態
彈出的菜單與ToolTip,更有那顏色漸變的Title Bar給我們增添了許多的樂趣。
其實即便是在Windows 95下也能使你的程序的Title Bar更具有個人魅力,在
Norton Utilities for 95中就有了顏色漸變的Title Bar,在大量的Delphi 3.0
的第三方控件中更有提供了此類完整功能的控件。當然用控件可以快速開發漂亮的
程序,但對于爬鍵盤的人來說,了解程序內核的機理并且做出更Cool的Title Bar
才是最爽的事!本文列舉了用代碼裝飾你的Title Bar的幾種方法。
1、修改Registry庫
在Windows 9x的桌面中,進入Display Properties對話框中的Appearance屬性
頁,可以修改Title Bar的字體的寬度與顏色。實際上所有這些更改都進入了
Registry庫的HKEY-CURRENT-USER/Control Panel下。由于都是單純的數字,
對于字體是不好修改的,但若是單純修改顏色值,則在Control Panel的Colors下有
明顯的value Name與value Data的含義。例如在Windows 98中,value Name為
ActiveTitle,value Data為“0 0 128”;value Name為GradientActiveTitle,
value Data為“168 200 240”,即表示活動時的Title Bar顏色由深藍色漸變到淺
藍色。值的含義很明顯即為RGB的值。用Win32 SDK中的修改Registry庫的API修改各
項意義明顯的Color值,別忘了最后發送WM-SYSCOLORCHANGE消息給自己的窗口,
來驗證改變后的效果。
此種方法的好處是思路簡單,并且下次重啟Windows后,所有窗口均是改變后的
顏色,但是方法有些勉強且功能不強。
2、利用SetSystem Color函數
SetSystemColor的解釋請參考相應手冊,不再詳述。這里僅列出一段代碼片段,
示意將Windows背景改為黑色,將Windows中的文字改為綠色。
int aiDsp[2];
DWORD aRgb[2];
aiDsp[0]=COLOR-WINDOW;
aRgb[0]=RGB(0, 0, 0);
aiDsp[1]=COLOR-WINDOWTEXT;
aRgb[1]=RGB(0, 255, 0);
SetSysColors(2, aiDsp, aRgb);
SetSysColors會自動給所有Windows發送WM-SYSCOLORCHANGE消息向所有Window
聲名系統顏色改變,但是并不改變注冊庫,因為下次重啟Windows后,系統顏色又恢復原樣。
本方法實現簡單,但影響了其他窗口特性,且功能太少。
3、拿起你的刷(brush),握住你的筆(pen),在DC上盡情地想畫什么就畫什么
在Windows 98下用VC 5.0生成小的Demo,在Windows 95下運行也正常。 下面先了解一下Windows重畫非客戶區的過程。在處理WM-NCPAINT、WM-NCACTIVE、
WM-SYSCOMMAND、WM-SETTEXT消息之后,Windows調用缺省處理消息函數DefWindowProc,
在此函數中將對非客戶區進行重畫操作,故而在CWnd的虛函數DefWindowProc中,
重畫Title Bar,就可以達到我們的目的,但是若不對消息進行一定的過濾,勢必引
起過多的重畫,我們假定Title Bar上沒有System Menu,即沒有最大、最小和關閉按
鈕在Title Bar上(見代碼片段1)。這樣可以簡化操作。對消息的過濾與重畫操作見
代碼片段2。
代碼片段1:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style &=~WS-SYSMENU; //取消Title Bar上的按鈕
return CFrameWnd::PreCreateWindow(cs);
}
代碼片段2:
LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lrst=CFrameWnd::DefWindowProc(message, wParam, lParam);
if (!::IsWindow(m-hWnd))
return lrst;
if (message=WM-NCPAINT message=WM-NCACTIVATE message=WM-NOTIFY)
{
CDC pWinDC=GetWindowDC();
if (pWinDC)
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}
return lrst;
}
在DrawTitleBar函數中,我們將采用乾坤大挪移,將Icon畫到了右邊,將最小、
最大、關閉按鈕畫到了左邊,并畫上了顏色漸變的Title Bar,在中間寫了“My Own
Cool Title Bar!!!”的標題(見代碼片段3)。最后將最小、最大、關閉按鈕連上
了各自的消息(見代碼片段4)。
代碼片段3:
void CMainFrame::DrawTitleBar(CDC* pDC)
{
if (m-hWnd)
{
CRect rtWnd, rtTitle, rtButtons;
GetWindowRect(&rtWnd); //整個Window的相對于屏幕的矩形
//取得整個Title bar的矩形
rtTitle.left=GetSystemMetrics(SM-CXFRAME);
rtTitle.top=GetSystemMetrics(SM-CYFRAME);
rtTitle.right=rtWnd.right-rtWnd.left-GetSystemMetrics(SM-CXFRAME);
rtTitle.bottom=rtTitle.top+GetSystemMetrics(SM-CYSIZE);
//重畫顏色漸變的Title Bar;有DC,有矩形,想怎么畫就怎么畫
DrawGradientBar(pDC, rtTitle); //此函數源碼因篇幅略去
//重畫icon
HICON hIcon=(HICON)::GetClassLong(m-hWnd, GCL-HICON);
m-rtIcon.left=rtTitle.right-GetSystemMetrics(SM-CYSMICON);
m-rtIcon.top=rtTitle.top+1;
m-rtIcon.right=m-rtIcon.left+GetSystemMetrics(SM-CXSMICON);
m-rtIcon.bottom=m-rtIcon.top+GetSystemMetrics(SM-CYSMICON);
::DrawIconEx(pDC->m-hDC, m-rtIcon.left, m-rtIcon.top,hIcon, GetSystemMetrics
(SM-CXSMICON), GetSystemMetrics(SM-CYSMICON), 0, NULL,
DI-NORMAL);
m-rtIcon.OffsetRect(rtWnd.TopLeft()); //記錄Icon屏幕位置
//重畫最小button
int nButtHeight=GetSystemMetrics(SM-CYSMSIZE)-3;
rtButtons.left=rtTitle.left;
rtButtons.top=rtTitle.top+(GetSystemMetrics(SM-CYSIZE)-nButtHeight)/2;
rtButtons.right=rtButtons.left+GetSystemMetrics(SM-CXSMSIZE);
rtButtons.bottom=rtButtons.top+nButtHeight;
pDC->DrawFrameControl(&rtButtons, DFC-CAPTION, DFCS-CAPTIONMIN);
m-rtButtMin=rtButtons;
m-rtButtMin.OffsetRect(rtWnd.TopLeft()); //記錄最小button屏幕位置
//重畫最大或恢復button
rtButtons.left=rtButtons.right;
rtButtons.right=rtButtons.left+GetSystemMetrics(SM-CXSMSIZE);
pDC->DrawFrameControl(&rtButtons, DFC-CAPTION, IsZoomed() ?
DFCS-CAPTIONRESTORE : DFCS-CAPTIONMAX);
m-rtButtMax=rtButtons;
m-rtButtMax.OffsetRect(rtWnd.TopLeft());//記錄button屏幕位置
//重畫關閉button
rtButtons.left=rtButtons.right;
rtButtons.right=rtButtons.left+GetSystemMetrics(SM-CXSMSIZE);
pDC->DrawFrameControl(&rtButtons, DFC-CAPTION, DFCS-CAPTIONCLOSE);
m-rtButtExit=rtButtons;
m-rtButtExit.OffsetRect(rtWnd.TopLeft())//記錄關閉button屏幕位置;
//重畫caption
int nOldMode=pDC->SetBkMode(TRANSPARENT);
COLORREF clOldText=pDC->SetTextColor(RGB(0, 0, 0));
pDC->SelectStockObject(ANSI-FIXED-FONT); rtTitle.right-=GetSystemMetrics
(SM-CYSMICON); pDC->DrawText((LPSTR)″My Own Cool Title
Bar!!!″, -1, &rtTitle, DT-CENTER);
pDC->SetBkMode(nOldMode);
pDC->SetTextColor(clOldText);
}
}
代碼片段4:
void CMainFrame::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
//處理缺省操作,諸如雙擊Title Bar等其他動作
Default();
//檢測最小,最大和關閉按鈕是否按到
if (m-rtButtExit.PtInRect(point))
SendMessage(WM-CLOSE);
else if (m-rtButtMin.PtInRect(point))
SendMessage(WM-SYSCOMMAND, SC-MINIMIZE, MAKELPARAM(point.x, point.y) );
else if (m-rtButtMax.PtInRect(point))
{
if (IsZoomed())
SendMessage(WM-SYSCOMMAND, SC-RESTORE, MAKELPARAM(point.x, point.y));
else
SendMessage(WM-SYSCOMMAND, SC-MAXIMIZE, MAKELPARAM(point.x, point.y) );
}
}
這里需要補充一點,若要程序更健壯,需要監視WM-WININICHANGED消息,因
為用戶可能在別處動態地改變Title Bar的寬度及其他寬度,此時需要重新取得Title
Bar的各項新值,使得Title Bar重畫。
實際上有了DC,有了矩形,的確是可以隨心所欲了,但是有了獨創就一定有付出。
要完成徹底的乾坤大挪移,還需要在移動窗口后,更新最小、最大和關閉按鈕的位置;
模擬按鈕按下的動作;點擊Icon后生成System Menu,并彈出,代價是大了一些。
有了這種方法后,就完全沒有必要非要和Windows對著干了,你可以設計自己的
Title Bar、自己的最小、最大和關閉按鈕,在Title Bar上貼上喜歡的位圖,使
Title Bar完全個性化。現在握住你的筆(pen),拿起你的刷(brush),盡情地裝飾你
的Title Bar吧!