 |
1樓
巨大八爪鱼
2015-12-27 18:19
最終效果:無論怎麼選擇,ListBox都永遠不會顯示灰色的虛線框。  在響應WM_DRAWITEM消息的函數中,switch (lpDis->itemAction)下響應ODA_FOCUS事件,並在其中執行:DrawFocusRect(lpDis->hDC, &lpDis->rcItem); 其中lpDis->rcItem表示的就是將要出現的選擇框的位置的大小。
|
 |
2樓
巨大八爪鱼
2015-12-27 18:20
最終代碼:  其中選中的那行是重點。
|
 |
3樓
巨大八爪鱼
2015-12-27 23:22
【補充】 ODA_DRAWENTIRE部分採用GDI+雙緩衝後的代碼: /* ** Draw the bitmap and text for the list box item. ** Draw a rectangle around the bitmap if it is selected. **/ void Dlg2_DrawItem(HWND hDlg, LPARAM lParam) { LPDRAWITEMSTRUCT lpDis = (LPDRAWITEMSTRUCT)lParam; switch (lpDis->itemAction) { case ODA_SELECT: case ODA_DRAWENTIRE: if (lpDis->itemID != -1) { // Create compatible graphic int width = lpDis->rcItem.right - lpDis->rcItem.left; int height = lpDis->rcItem.bottom - lpDis->rcItem.top; Bitmap bmpMem(width, height); Graphics gpMem(&bmpMem);
// Main Drawing int color; if (lpDis->itemState & ODS_SELECTED) color = COLOR_HIGHLIGHT; // when selected else color = COLOR_WINDOW; // when not selected character.Display(&gpMem, lpDis->itemID, 0, 0, 0, color, ICON_PADDING_H, ICON_PADDING_V);
// Copy to screen Graphics graphics(lpDis->hDC); graphics.DrawImage(&bmpMem, lpDis->rcItem.left, lpDis->rcItem.top, width, height); } // If there are no list box items, skip break; case ODA_FOCUS: DrawFocusRect(lpDis->hDC, &lpDis->rcItem); break; } } 【Character類】 #include "stdafx.h" #include "Character.h"
Character::Character(void) { width = height = 32; }
Character::~Character(void) { }
void Character::Close(void) { width = height = 32; }
void Character::Display(Graphics *graphics, int row, int column, int x, int y) { graphics->DrawImage(image, x, y, column * width, row * height, width, height, UnitPixel); }
void Character::Display(Graphics *graphics, int row, int column, int x, int y, COLORREF color, int horizontalPadding, int verticalPadding) { Color colorObj; colorObj.SetFromCOLORREF(color); SolidBrush brush(colorObj); graphics->FillRectangle(&brush, x, y, width + 2 * horizontalPadding, height + 2 * verticalPadding); Display(graphics, row, column, x + horizontalPadding, y + verticalPadding); }
void Character::Display(Graphics *graphics, int row, int column, int x, int y, int sysColor, int horizontalPadding, int verticalPadding) { COLORREF color = GetSysColor(sysColor); Display(graphics, row, column, x, y, color, horizontalPadding, verticalPadding); }
UINT Character::GetHeight(void) { return height; }
UINT Character::GetWidth(void) { return width; }
void Character::Open(LPTSTR filename) { Open(wstring(filename)); }
void Character::Open(wstring filename) { fileName = filename; image = Image::FromFile(filename.c_str()); fileWidth = image->GetWidth(); fileHeight = image->GetHeight(); width = fileWidth / IMG_COUNT_H; height = fileHeight / IMG_COUNT_V; }
|
 |
順便提一下,在Windows的更改圖標的對話框中,就有未消除灰色選擇框的bug: 
|
 |
在Win7的shell32.dll中我沒找到更改圖標的對話框。但在Windows XP的shell32.dll中就有這個對話框,它也是用ListBox控制項+自繪來實現的。 如果電腦上只有Win7系統又沒有XP的shell32.dll文件,可以去網上下載。
|
 |
我在響應WM_DRAWITEM消息的時候,返回的值是FALSE,所以才會出現灰色的矩形框。 如果返回TRUE就沒有灰色矩形框了。
|
 |
【更簡單的方法】 直接在WM_DRAWITEM消息處理中return TRUE case WM_DRAWITEM: pDlgCls->DrawItem(lParam); return TRUE; // Important! Return true to remove the default focus rect
|
 |
異或運算有一個非常重要的運算定律:對於任意的兩個整數a和b,始終滿足a ^ b ^ b = a。 因此,當屏幕上任意一種顏色a與虛線框顏色b進行兩次異或運算後,都能還原為最初的顏色a。
|