載入png圖片按鈕GdipButton按鈕類
介紹
這個網站上有幾個自繪按鈕,但是我找不到一個容易支援PNG檔案透明度的按鈕,所以我建立了這個類。由於這個類使用GDI +,它實際上支援許多影象格式,但是現在更好的質量按鈕現在是PNG而不是ICO,所以這裡就是一個。
更新:我的樣式工具包(譯者:這篇文章有翻譯,請點選)中有這個類的擴充套件版本。如果你想要的是使用按鈕上的影象,這個類可能更簡單的使用。
背景
GDI +是Microsoft Windows SDK的一部分,需要在應用程式啟動時進行初始化。如果您以前沒有使用GDI +,請檢視演示專案的原始碼並閱讀本文:
特徵
- 灰度影象
- 該類將自動從載入的資源建立一個灰度影象。當按鈕設定為禁用狀態時,將顯示灰度影象。
- 該類將自動從載入的資源建立一個灰度影象。當按鈕設定為禁用狀態時,將顯示灰度影象。
- 突出顯示影象
- 該類將自動從載入的資源建立一個突出顯示的影象。當滑鼠懸停在按鈕邊界上時,顯示突出顯示的影象。
- 替代影象
- 您可以選擇新增備用影象。當通過功能呼叫設定時,或者單擊按鈕並啟用切換模式時,將顯示備用影象。
- 切換模式
- 啟用時,按鈕會在標準影象和備用影象每次按下之間切換。
- 按鈕狀態
- 當按下按鈕時,影象向下移動1畫素。
- 工具提示
- 可以選擇新增工具提示。
頁面頂部的影象顯示三種不同狀態的播放按鈕。從左到右,它們是:正常,突出顯示和禁用。另外兩個按鈕就是更酷的例子。
從圖片可能不太明顯,第二個按鈕處於突出顯示狀態。這是按設計,我不想大幅改變形象。高亮狀態只是增加了亮度和對比度。當您將滑鼠移動到其上時,顯然是足夠的。
下圖顯示了切換狀態下的播放按鈕,應該很明顯,為什麼會想要這樣的功能。退出按鈕處於突出顯示狀態,工具提示顯示在此影象中。
使用GDI +僅在初始化期間被使用,所以沒有效能損失。在建立時,影象將轉換為點陣圖,並且在需要使用點陣圖時重新繪製控制元件。
使用程式碼
步驟1 - 將這些檔案新增到您的專案
步驟2 - 新增資源,成員變數和影象
使用資源編輯器在對話方塊中新增一個按鈕,設定資源ID,然後在Caption框中刪除文字。您可以將樣式設定為Owner Draw,但不需要,因為程式碼將自動設定此樣式。
使用類嚮導,新增一個變數到您剛剛建立的ID。在此示例中,我將ID設定為IDC_PLAY
,並將變數名稱設定為m_cPlay
。編輯對話方塊的.h檔案,並將控制元件更改CButton
為CGdiButton
。不要忘記包含檔案“ GdipButton.h ”。
在資源編輯器中,從res資料夾匯入.png檔案,並將資源型別設定為PNG。使用PNG只是慣例,只要程式碼與命名相同,它就可以是任何東西。右鍵單擊IDR_PNG1,選擇屬性,並將其重新命名為有用的東西,IDR_PNG1
IDR_PLAY
在此示例中。
步驟3 - 新增LoadStdImage()函式
現在,我們只需要在初始化時將影象載入到按鈕。在該OnInitDialg()
功能中,在底部附近新增以下程式碼:
BOOL CTestGdipButtonDlg::OnInitDialog() { CDialog::OnInitDialog(); /// a bunch of stuff here m_cPlay.LoadStdImage(IDR_PLAY, _T("PNG")); return TRUE; }
步驟4 - 構建和執行
您現在應該能夠執行它,並看到您的新的PNG按鈕!如果它在這裡崩潰,可能是因為你沒有初始化GDI +。檢視本文的背景部分。
演示專案
這是在測試程式中建立按鈕所需的所有程式碼:
// load the standard image and alternate image m_cPlay.LoadStdImage(IDR_PLAY, _T("PNG")); m_cPlay.LoadAltImage(IDR_PAUSE, _T("PNG")); m_cPlay.EnableToggle(TRUE); // just to show highlight state for article m_cPlayHi.LoadStdImage(IDR_PLAY, _T("PNG")); // set as disabled m_cPlayDis.LoadStdImage(IDR_PLAY, _T("PNG")); m_cPlayDis.EnableButton(FALSE); // show a larger button type m_cGear.LoadStdImage(IDR_GEAR, _T("PNG")); // replace the OK button with something m_cShutDn.LoadStdImage(IDR_EXIT, _T("PNG")); m_cShutDn.SetToolTipText(_T("Close Program"));//(譯者:這裡應該是m_cShutDn.SetToolTipText(_T("Close Program"),TRUE);)
VC6和VS2005版本都包含在演示專案中。
透明影象問題
按鈕控制元件不知道它下面的背景應該是什麼; 它從與當前DC相關聯的點陣圖獲取此資訊。在大多數情況下,這樣做很好,背景是控制畫面之前的螢幕。但是,應用程式在啟動時可能不是最多的。總是在頂級應用程式,如工作管理員可能會阻礙,所以當它獲取背景影象,這是錯誤的資料。通過SetBkGnd()
實際建立背景的程式碼呼叫函式來克服這個問題。
設定父項OnEraseBkgnd()
功能中的所有按鈕背景。演示程式使用以下程式碼:
BOOL CTestGdipButtonDlg::OnEraseBkgnd(CDC* pDC) { CDialog::OnEraseBkgnd(pDC); CRect rect; GetClientRect(rect); CMemDC pDevC(pDC, rect); // fill in the back ground with something 譯者:請注意,在demo中,這裡有一段if (m_hBitmap) { pDevC->SelectObject(m_hBitmap); }沒有的話對話方塊背景是黑色的 SetButtonBackGrounds(pDevC); return TRUE; } void CTestGdipButtonDlg::SetButtonBackGrounds(CDC *pDC) { m_cPlay.SetBkGnd(pDC); m_cPlayHi.SetBkGnd(pDC); m_cPlayDis.SetBkGnd(pDC); m_cShutDn.SetBkGnd(pDC); }
由於傳遞的DC是一個記憶體DC,所以其他應用程式可能正在做的事情並不重要。上面的程式碼假設你想要使用除了預設背景之外的東西; 否則,您可能只需使用預設的crummy按鈕。
VC6構建問題
VC6需要一些額外的東西才能正確編譯,將以下內容新增到stdafx.h檔案中。還要將SDK include和lib路徑新增到您的環境中。
隱藏 複製程式碼// VC6 #if defined(_MSC_VER) && _MSC_VER == 1200 #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #endif #include <spanclass="code-keyword"><Specstrings.h></span> #include <spanclass="code-keyword"><gdiplus.h></span> #pragma comment(lib, "gdiplus.lib") using namespace Gdiplus; // VS2005 #else #include <spanclass="code-keyword"><gdiplus.h></span> #pragma comment(lib, "gdiplus.lib") using namespace Gdiplus; #endif