我正在开发一个遗留的(1999)代码库,它有一个恼人的错误,当窗口放在非主监视器上时,某些GUI元素的滚动不能正确重绘。
据我所知(不熟悉Windows的API)问题是代码提取DeviceContext以使用GetDC(hwnd)
绘制,这可以从文档中获取仅适用于主监视器的DC(但文档并不十分清楚,TBH)。
我设法在屏幕上画画,基本上使用:
RECT rect;
GetWindowRect(hwnd, &rect);
HMONITOR monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY);
MONITORINFOEX minfo;
minfo.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &minfo);
HDC = CreateDC(NULL, minfo.szDevice, NULL, NULL);
这会将事物绘制到正确的监视器上,但应用程序显然需要一些与窗口相关的东西,因为所有内容都会在桌面的左上角而不是在窗口中结束。
现在,我的谷歌搜索似乎表明使用EnumDisplayMonitors(GetDC(), &rect, PaintCallback, NULL)
运行两次绘画代码应该做正确的事情。不幸的是,我的代码不是C或C ++。这是一个SmallTalk图像(支持在15年左右结束,因此对供应商的抱怨已经结束),我只是不确定油漆处理是否发生在我可以访问的代码中,或者它是否足够深入我不能理解SmallTalk的内容。
因此我的问题是:是否可以创建一个与我的窗口客户区相关的DC(也许是通过从CreateDC调整DC)?我意识到,如果窗户横跨两个监视器,这可能会破坏,但这至少比目前状态更糟糕。
更新:
我设法使用EnumDisplayMonitors
运行渲染代码两次,但是以奇怪的方式崩溃(这很可能是一个SmallTalk问题;编译器是旧的和特殊的,但调试代码在堆栈有问题)。
回答评论:我认为代码基本上是想在Windows上绘图,是的。表示各种GUI元素的SmallTalk对象带有窗口句柄,用于创建GetDC(hwnd)
的DC,因此这很容易。所以听起来像GetDC(hwnd)
应该得到一个做正确事情的DC,在这种情况下;可能是ST代码正在某处缓存DC,GetDC
会在窗口移动到不同的屏幕时返回不同的DC(这听起来似乎是我对此的粗略了解)。
答案 0 :(得分:0)
看起来问题确实是GetDC
创建的DC的缓存。我修改了渲染代码,不使用缓存(或多或少,代码有点纠结),从第一眼看起来就像是诀窍。
对于后人,如果有人谷歌搜索Visual Smalltalk Enterprise并找到这个答案,我所做的就是编辑GraphicsTool>>ifNilHandle:
以不实际检查句柄是否为零,但总是运行块来获得一个新的句柄并在最后返回true。这样,每次都会获取新的DC。
更新:
这解决了我试图解决的直接问题,但不幸的是打破了其他一些事情(最值得注意的是WindowBuilder Pro,GUI构建工具套件)。问题显然是在代码中某处对DC过度急切的缓存,但需要以比上述大锤方法更加集中的方式进行修复。