 |
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。
|