对 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 中的错误实现:
int CPen::GetExtLogPen(EXTLOGPEN* pLogPen) { return ::GetObject(m_hObject, sizeof(EXTLOGPEN), pLogPen); }
该实现会忽略 EXTLOGPEN 中尾部可变大小的 DWORD
数组。结构。该结构定义为:
typedef struct tagEXTLOGPEN { DWORD elpPenStyle; DWORD elpWidth; UINT elpBrushStyle; COLORREF elpColor; ULONG_PTR elpHatch; DWORD elpNumEntries; DWORD elpStyleEntry[1]; } EXTLOGPEN, *PEXTLOGPEN;
如果elpStyleEntry数组的长度最多为一个元素,则对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::GetExtLogPen
将 sizeof(EXTLOGPEN)
传递给 GetObject
调用,而不是其真实大小论证。
注:A bug report已提交至 Microsoft Connect。
关于windows - 为什么使用自定义笔时 GetLogPen 会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37381898/