Во-первых, извините за длинный пост.
Есть ли какие-либо предложения относительно того, как я могу ограничить область публикации сообщения WM_DISPLAYCHANGE?
Сценарий:
Screen.AllScreens
возвращает массив координат и разрешений для всех мониторов, обнаруженных на клиенте.Если приложение запускается, когда рабочая станция заблокирована (во время перезапуска приложения на ночь), Screen.AllScreens
возвращает только один элемент, детализирующий один экран с размерами всех нескольких мониторов, как один.
Впоследствии в этомВ сценарии, когда пользователь разблокирует рабочую станцию и начинает использовать приложение, используемый элемент управления Infragistics (UltraWinDock) не позволяет перетаскивать плавающие окна за пределы основного экрана, поскольку свойство Screen.AllScreens
не возвращает истинную конфигурацию монитора длясистема.Элемент управления Infragistics фактически смотрит на Screen.PrimaryScreen.Bounds
, но свойство Screen.PrimaryScreen
в свою очередь вызывает кэшированный массив Screen.AllScreens
, который возвращает огромный первичный экран!
Когда приложение запускается нормально (с разблокированной рабочей станцией)), управление функционирует правильно.
Единственное средство, с помощью которого я вижу, что Screen.AllScreens
сбрасывается и может быть обновлено, - это происходит через событие SystemEvents.DisplayChanging
, после чего устанавливается внутреннее поле.к нулю.(Screen.AllScreens
подключается к этому событию.) Screen.AllScreens
будет заполнено при следующем вызове.
Из того, что я могу определить, событие SystemEvents.DisplayChanging
может быть вызвано с помощью сообщения WM_DISPLAYCHANGE
WMI.
Средство, с помощью которого я справился с обходным путем, - это вызов:
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int nIndex);
с параметром SM_CMONITORS , который представляет количество дисплеев в системе.По-видимому, это всегда возвращает фактическое количество присутствующих мониторов, независимо от того, заблокирована ли рабочая станция.
Затем я оцениваю, меньше ли длина массива Screen.AllScreens
, чем результат GetSystemMetrics(SM_CMONITORS)
, и еслия подключаюсь к статическому событию SystemEvents.SessionSwitch
и проверяю свойство SessionSwitchEventArgs.Reason
на значение SessionUnlock
.Когда рабочая станция разблокирована, это событие получено, и условие выполнено, поэтому я отправляю сообщение, используя метод P / Invoke
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);
со следующими аргументами:
PostMessage(HWND_BROADCAST, WM_DISPLAYCHANGE,UIntPtr.Zero,IntPtr.Zero)
Это работает очень хорошо, и желаемый результат достигнут! Screen.AllScreens
сбрасывается, и управление инфраструктурой работает правильно.
Мне кажется, что неясная ошибка с Screen.AllScreens
не переоценивает себякогда приложение запускается на заблокированной рабочей станции, а затем разблокируется.
Редкая проблема, я подтверждаю, но, тем не менее, проблема.
Для сообщения WM_DISPLAYCHANGE , lParamи wParam описываются как:
wParam
- Новая глубина изображения на дисплее, в битах на пиксель.
lParam
Я отправляю нулевые значения IntPtr.Zero
для этих аргументов, поскольку я не знаю, каковы действительные значения на момент отправки сообщения.
Меня беспокоит то, что я передаю сообщение WM_DISPLAYCHANGE
по всей системе с нулевыми аргументами и что могут быть запущенные процессы, которые используют WM_DISPLAYMESSAGE
и используют аргументы.Я хотел бы надеяться, что при отправке нулевых аргументов любые потребители проигнорируют аргументы, но это очень опасное предположение.
Существует ли способ отправить или опубликовать сообщение только в приложении ввопрос и устранить риск влияния на другие процессы?
Я пробовал следующее безрезультатно:
PostMessage(IntPtr.Zero, WM_DISPLAYCHANGE, UIntPtr.Zero, IntPtr.Zero)
PostMessage(this.Handle, WM_DISPLAYCHANGE, UIntPtr.Zero, IntPtr.Zero)
PostThreadMessage(AppDomain.GetCurrentThreadId(), WM_DISPLAYCHANGE, UIntPtr.Zero, IntPtr.Zero)
SendMessage(this.Handle, WM_DISPLAYCHANGE, UIntPtr.Zero, IntPtr.Zero)
ПРИМЕЧАНИЯ:
- У меня нет большого опыта работы с P / Invoke или WMI.
- Целевой платформой является .Net 3.5.
- Я пока не видел побочных эффектов от трансляции PostMessage метода
WM_DISPLAYCHANGE
. - Я уже скачал исходный код для Infragistics и точно определил, где проблема возникает в их коде,и подумал о перекомпиляции элемента управления, чтобы интегрировать исправление, но решил не делать этого.Я проинформировал Infragistics об этой проблеме, но не могу дождаться исправления и не рассматриваю ее как проблему Infragistics, поскольку она вызывает
Screen.AllScreens
. - Необходим перезапуск приложения в одночасье,и его нельзя изменить, чтобы дождаться, когда пользователь войдет в систему утром.
- Я создал тестовое приложение, которое блокирует рабочую станцию пользователя, перезапускает себя (приложение, а не рабочую станцию) и оценивает
Screen.AllScreens
свойство, когда приложение заблокировано, а затем еще один моментальный снимок после отправки метода WM_DISPLAYCHANGE
.Я хотел бы добавить скриншот, но я не могу, так как я являюсь новым пользователем StackOverflow !!!