[英]How to change looks of a disabled button and edit control?
已啟用
殘障人士
當我禁用按鈕(使用BS_BITMAP樣式標志創建)時,它會改變外觀(請參見上圖),編輯控件也會發生同樣的情況。
禁用后如何使控件不變?
我可以通過對控件進行子類化來實現,但是有沒有更簡單的方法?
如果可能的話,我不想僅僅為此子類化控件。
您無需為此子類化控件即可,盡管我會說它會更干凈。 設置BS_OWNERDRAW
樣式並處理WM_DRAWITEM
消息的替代方法。 這意味着您要接管所有圖形,但這沒關系,因為您始終不希望它看起來像普通按鈕。
我完全同意Jonathan Potter的觀點 ,即無法向用戶指示哪些按鈕已啟用,哪些按鈕未啟用,這是非常糟糕的UI設計。 有多種方法可以做到這一點,但不這樣做是不可行的選擇。 幸運的是,使用WM_DRAWITEM
很容易,因為它告訴您按鈕的當前狀態。
因此,使WM_DRAWITEM
消息處理程序看起來像這樣(在父窗口的窗口過程中):
case WM_DRAWITEM:
{
const DRAWITEMSTRUCT* pDIS = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
// See if this is the button we want to paint.
// You can either check the control ID, like I've done here,
// or check against the window handle (pDIS->hwndItem).
if (pDIS->CtlID == 1)
{
// Load the bitmap.
const HBITMAP hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
// Draw the bitmap to the button.
bool isEnabled = (pDIS->itemState & ODS_DISABLED) == 0;
DrawState(pDIS->hDC,
nullptr,
nullptr,
reinterpret_cast<LPARAM>(hBmp),
0, 0, 0, 0, 0,
DST_BITMAP | (isEnabled ? DSS_NORMAL : DSS_DISABLED));
// Delete the bitmap.
DeleteObject(hBmp);
// Draw the focus rectangle, if applicable.
if ((pDIS->itemState & ODS_FOCUS) && ((pDIS->itemState & ODS_NOFOCUSRECT) == 0))
{
DrawFocusRect(pDIS->hDC, &pDIS->rcItem);
}
// Indicate that we handled this message.
return TRUE;
}
break;
}
當然,您可以通過一次加載位圖並將其緩存在全局對象中來進一步優化此代碼,而不是每次按鈕需要繪制時都加載並銷毀它。
請注意,我使用了DrawState
函數 ,該函數可以以“正常”( DSS_NORMAL
)或“禁用”( DSS_DISABLED
)狀態繪制位圖。 這大大簡化了代碼,並使我們能夠輕松地處理禁用狀態,但不幸的是,結果看起來有點難看。 這是因為DrawState
函數會在應用除正常效果之外的任何效果之前將位圖轉換為單色。
您可能不喜歡這種效果,因此您需要做其他事情。 例如,使用兩個單獨的圖像,一個用於啟用狀態,另一個用於禁用狀態,然后繪制適當的圖像。 或將正常的彩色圖像轉換為灰度 ,然后將其繪制為禁用狀態。
而且,如果自定義繪圖代碼運行得太慢,則可以通過檢查pDIS->itemAction
的值並僅重新繪制必要的部分來進一步優化它。
然后,一旦您認為所有功能都經過完善和高效,不可避免的錯誤報告將開始出現。例如,不支持鍵盤加速器。 然后,一旦添加了對這些功能的支持,就需要在用戶界面中進行說明。 對於已經包含文本的位圖,這將是困難的; 帶下划線的字母的唯一方法是自己繪制文本。 這一切都證明所有者抽取是太多的工作。 只是讓Windows以正常方式繪制控件,不要僅僅因為某些設計師認為它“看起來很酷”就為您的用戶破壞了一切。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.