为什么使用自定义笔时 GetLogPen 失败?
Why does GetLogPen fail with a custom pen?
对GetLogPen()
和GetExtLogPen()
的调用都失败了。他们 return 零...
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
结构。
有什么想法吗?
EXTLOGPEN
结构只为一个样式参数定义了 space,但最多允许 16 个。不清楚 GetExtLogPen
如何确定有多少 space 可用。试试这个,看看是否有帮助。
struct EXTLOGPEN16 : public EXTLOGPEN
{
DWORD elpStyleMore[15];
public:
EXTLOGPEN16()
{
elpNumEntries = 16;
}
};
EXTLOGPEN16 ExtLogPen;
if (CustomPen->GetExtLogPen(&ExtLogPen) == 0)
// ...
这是 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());
不幸的是, 没有解决问题,因为 CPen::GetExtLogPen
将 sizeof(EXTLOGPEN)
传递给 GetObject
调用,而不是其参数的真实大小。
注意:bug report 已提交至 Microsoft Connect。
对GetLogPen()
和GetExtLogPen()
的调用都失败了。他们 return 零...
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
结构。
有什么想法吗?
EXTLOGPEN
结构只为一个样式参数定义了 space,但最多允许 16 个。不清楚 GetExtLogPen
如何确定有多少 space 可用。试试这个,看看是否有帮助。
struct EXTLOGPEN16 : public EXTLOGPEN
{
DWORD elpStyleMore[15];
public:
EXTLOGPEN16()
{
elpNumEntries = 16;
}
};
EXTLOGPEN16 ExtLogPen;
if (CustomPen->GetExtLogPen(&ExtLogPen) == 0)
// ...
这是 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());
不幸的是,CPen::GetExtLogPen
将 sizeof(EXTLOGPEN)
传递给 GetObject
调用,而不是其参数的真实大小。
注意:bug report 已提交至 Microsoft Connect。