调用GetObject获取LOGFONT返回0,参数值全为-MAXINT,求排查
问题:GetObject获取LOGFONT失败返回0且值为-MAXINT
我在运行Windows 11的64位笔记本上使用VS2019 Community版本,尝试实现通用字体缩放函数,调整HFONT属性但效果有限,编写了如下代码:
//============================================================================== #include "stdafx.h" //X #include <ocidl.h> // PATH is C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\ocidl.h //============================================================================== // Function ScaleFont(). //============================================================================== HFONT ScaleFont( HFONT hFont , HWND hWnd , double PctAdjustmentSPEC ) { double PctAdjustment = min(max(PctAdjustmentSPEC,0.875),1.125); LOGFONT lf; int NumBytes = GetObject((HGDIOBJ)hFont,sizeof(lf),(void*)(&lf)); double WidthHeightRatio = double(lf.lfWidth)/double(lf.lfHeight); lf.lfHeight = LONG(floor(lf.lfHeight * PctAdjustment)); lf.lfWidth = LONG(floor(lf.lfWidth * PctAdjustment * WidthHeightRatio)); HDC hdc = GetDC(hWnd); DeleteObject((HGDIOBJ)hFont); hFont = (HFONT)CreateFontIndirect(&lf); SelectObject(hdc,hFont); ReleaseDC(hWnd,hdc); return hFont; }
当前问题出在语句int NumBytes = GetObject((HGDIOBJ)hFont,sizeof(lf),(void*)(&lf));,该语句返回NumBytes==0,且LOGFONT对象所有值等于-MAXINT,请问哪里出错了?
已尝试的方案:
- 使用IFont方法但编译失败;
- 用HANDLE替换HGDIOBJ可正常编译;
- 尝试用GetLogicalFont替代GetObject,但VS2019不识别该函数名。
问题原因及解决办法
无效句柄或类型不匹配:GetObject返回0最常见的原因是传入的
hFont无效,或者并非合法的GDI字体句柄。先确认调用ScaleFont时传入的hFont是通过CreateFont、CreateFontIndirect、GetStockObject或SendMessage(hWnd, WM_GETFONT, 0, 0)等方式正确获取的有效句柄,而非已被释放的句柄或COM接口指针。结构体初始化缺失:调用GetObject前未初始化LOGFONT结构体,内存中可能存在垃圾值,建议先执行
ZeroMemory(&lf, sizeof(lf))清空结构体,避免干扰后续判断。错误码定位问题:在GetObject返回0后,立即调用
GetLastError()获取具体错误码,比如:ERROR_INVALID_PARAMETER:说明传入的参数(如结构体大小、句柄类型)不匹配;ERROR_INVALID_HANDLE:说明hFont是无效句柄;
这能精准定位问题根源。
函数逻辑的潜在错误:
- 不要在函数内直接
DeleteObject(hFont),原字体句柄的生命周期应由调用方管理,否则会导致调用方后续使用该句柄时出现错误; - 调用
SelectObject(hdc, hFont)后未恢复DC的原字体,会导致DC状态异常,正确做法是保存原字体句柄并恢复:HDC hdc = GetDC(hWnd); HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); // 若需使用DC执行绘制操作,在此处完成 SelectObject(hdc, hOldFont); // 恢复DC的原字体 ReleaseDC(hWnd, hdc);
- 不要在函数内直接
内容的提问来源于stack exchange,提问作者The Bard of Chelsea
相关产品推荐
相关产品推荐

