对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
按照我的预期填充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());
不幸的是, 由Mark Ransom发布的解决方案没有解决问题,因为CPen::GetExtLogPen
将sizeof(EXTLOGPEN)
传递给GetObject
调用,而不是其参数的真实大小。
注意:一个错误报告已经提交给Microsoft Connect。
EXTLOGPEN
结构仅为一个样式参数定义了空间,但最多允许为16个。不清楚GetExtLogPen
如何确定有多少可用空间。 试试这个,看看是否有帮助。
struct EXTLOGPEN16 : public EXTLOGPEN { DWORD elpStyleMore[15]; public: EXTLOGPEN16() { elpNumEntries = 16; } }; EXTLOGPEN16 ExtLogPen; if (CustomPen->GetExtLogPen(&ExtLogPen) == 0) // ...