2016-10-19 3 views
0

Я работаю над кодовой базой (1999), у которой есть раздражающая ошибка, при которой прокрутка в некоторых элементах GUI неправильно перерисовывается, когда окно помещается на непервичное монитор.Создание зависимого от окна DeviceContext на нескольких мониторах

Насколько я могу разобраться (не очень хорошо знакомы с API-интерфейсами Windows), проблема заключается в том, что код извлекает 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, относящийся к клиентской области моего окна (возможно, путем настройки DC из CreateDC)? Я понимаю, что это, вероятно, сломается, если окно оседлает два монитора, но это, по крайней мере, менее разрушено, чем текущее состояние вещей.

UPDATE:

мне удалось запустить код рендеринга дважды, используя EnumDisplayMonitors, но врезается в странных отношениях (что, скорее всего, проблема SmallTalk, компилятор старый и своеобразных, но отладки кода это глубоко в стеке проблематично).

Чтобы ответить на комментарии: Я думаю, что код в принципе хочет рисовать на окнах, да. Объекты SmallTalk, представляющие различные элементы GUI, несут вокруг оконных дескрипторов, которые используются для создания контроллеров домена с GetDC(hwnd), так что это достаточно просто. Так звучит GetDC(hwnd)должно получить DC, который делает правильные вещи, в данном случае; может быть, что ST-код кэширует DC-файлы где-то, и GetDC вернет другой DC, когда окно будет перемещено на другой экран (что звучит правдоподобно из моего поверхностного знания об этом).

+0

Похоже, вы хотите нарисовать какое-то окно. Используйте 'FindWindow' для получения дескриптора окна или используйте утилиту Spy ++ в Visual Studio, чтобы найти дескриптор окна. Создайте DC: 'HDC hdc = GetDC (hwnd)' и вызовите 'ReleaseDC (hwnd, hdc)' по завершении. Но это, конечно, дешевый взлом, ваши рисунки будут удалены очень быстро. Почему бы вам не сделать это правильно, создав собственное окно? –

+0

Я не думаю, что проблема связана с самим GetDC. Возможно, есть также код, который использует GetClientRect/GetWindowRect, и координаты берутся относительно основного экрана. – VuVirt

ответ

0

Похоже, что проблема была в самом деле кешированием DC, созданной GetDC. Я взломал код рендеринга, чтобы не использовать кеши (более или менее, код немного запутался), и с первого взгляда похоже, что это трюк.

Для потомков, на случай, если кто-то подойдет для Visual Smalltalk Enterprise и найдет этот ответ, я сделал, чтобы отредактировать GraphicsTool>>ifNilHandle:, чтобы на самом деле не проверить, является ли дескриптор нулевым, но всегда запускайте блок, чтобы получить новый дескриптор и вернуть true в конце. Таким образом, свежие контроллеры домена выбираются каждый раз.

UPDATE:

Это устраняет непосредственную проблему я пытался исправить, но, к сожалению, ломает пару других вещей (особенно WindowBuilder Pro, графический интерфейс Станкостроение-комплект). Проблема явно чрезмерная кэширования DC-ов где-то в коде, но его нужно исправлять гораздо более сосредоточенным образом, чем метод кувалды выше.