windows - 为什么使用自定义笔时 GetLogPen 会失败?

标签 windows mfc gdi

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::GetExtLogPensizeof(EXTLOGPEN) 传递给 GetObject 调用,而不是其真实大小论证。


注:A bug report已提交至 Microsoft Connect。

关于windows - 为什么使用自定义笔时 GetLogPen 会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37381898/

相关文章:

Windows 版 PHP 5.5 中缺少 php_zip.dll

c - 从内核驱动程序到达内核 session 空间

c++ - 在 CComboBox (MFC) 中通过文本设置选择

c++ - 工作线程中的 GDI 打印机设备上下文随机失败

c - 绘画代码在我的 WM_COMMAND 消息处理程序中无法正常工作

c++ - 从 DLL 动态导入 C++ 类

windows - 获取正在运行的进程列表

javascript - 如何转换 JavaScript 对象以从 C++ 访问其数据?

c++ - OpenGL 程序中奇怪的 CPU 使用率

C++ BitBlt 显示棋盘和偏色