GetLogPen()GetExtLogPen()的调用均失败。他们返回零...

CBrush Brush;
Brush.CreateSolidBrush( COLOR_MINORSELECTION );
Brush.GetLogBrush( &lBrush );
DWORD Style[] = { 3, 1 };
CPen CustomPen;
CustomPen.CreatePen( PS_USERSTYLE, 1, &lBrush, 2, Style );
CPen *pOldPen = pDC->SelectObject( &CustomPen );
LOGPEN LogPen;
if( CustomPen->GetLogPen( &LogPen ) == 0 )
{
    EXTLOGPEN ExtLogPen;
    if( CustomPen->GetExtLogPen( &ExtLogPen ) == 0 )
        return;
}

失败似乎是由于笔样式使用了PS_USERSTYLE。如果我使用PS_SOLID笔执行此操作,则会按预期填充LogPen结构。

有什么想法吗?

最佳答案

这是CPen::GetExtLogPen实现中的错误:



该实现将忽略EXTLOGPEN结构中尾随大小可变的DWORD数组。此结构定义为:



如果elpStyleEntry数组的长度最多为1个元素,则对CPen::GetExtLogPen的调用成功。除具有PS_USERSTYLE笔样式的笔外,所有笔都适用。使用PS_USERSTYLE笔样式时,elpStyleEntry条目将至少具有2个条目。

对于使用PS_USERSTYLE笔样式的笔,解决方法是使用Windows API GetObject调用,并规避MFC的实现:

// Query for required buffer size
int sizeRequired = ::GetObject(CustomPen.m_hObject, 0, nullptr);
// Allocate buffer (may not be properly aligned)
std::vector<byte> buffer(sizeRequired);
// Retrieve the entire EXTLOGPEN structure
int ret = ::GetObject(CustomPen.m_hObject, static_cast<int>(buffer.size()), buffer.data());
assert(ret == static_cast<int>(buffer.size());
// Cast to const ref for convenient access
const EXTLOGPEN& elp = *reinterpret_cast<const EXTLOGPEN*>(buffer.data());

不幸的是,solution posted by Mark Ransom不能解决问题,因为CPen::GetExtLogPensizeof(EXTLOGPEN)传递给GetObject调用,而不是其参数的真实大小。

注意:bug report已提交到Microsoft Connect。

08-27 02:01