Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 15.05.18 17:11
Оценка:
Как переместить окно на другой монитор?

Собственно, такая проблема.
Есть аплликуха, которая болтается на другом мониторе.
Для некоторых вещей, она грузит DLL, которая создает свой диалог. А основная аплликуха передает ей HWND парента для этого диалога, и координаты.
Дык вот, когда это проделывается, то DLL показывается свой диалог все равно на первом (видимо основном) мониторе.
Как такое может происходить в толк не возьму. Вроде как у диалога HWND парента все равно из основной аппликухи со второго монитора. Каким образом диалог оказывается на первом, вообще не понимаю. Но тем не менее.

Отсюда и вопрос: как переместить окно на другой монитор?
Нагуглил вот это

Но непонятно что такое HWND монититора в параметрах void MoveWindowToMonitor(HWND hwnd, HWND hwndMon, BOOL fWork)… Кто такой HWND монитора я не знаю, должно же по идее быть HMONITOR?

Что за вызовы в теле GetMonitorRect(hwnd, &rc_mon, fWork);
Кто такая GetMonitorRect? Ничего не гуглится по названию, и даже не мсдниться….

Коллеги, просветите, куда копать?
Aml Pages Home
Re: Как переместить окно на другой монитор?
От: Aniskin  
Дата: 15.05.18 18:05
Оценка: 6 (1)
Здравствуйте, Carc, Вы писали:

C>Как переместить окно на другой монитор?


C>Собственно, такая проблема.

C>Есть аплликуха, которая болтается на другом мониторе.
C>Для некоторых вещей, она грузит DLL, которая создает свой диалог. А основная аплликуха передает ей HWND парента для этого диалога, и координаты.
C>Дык вот, когда это проделывается, то DLL показывается свой диалог все равно на первом (видимо основном) мониторе.
C>Как такое может происходить в толк не возьму. Вроде как у диалога HWND парента все равно из основной аппликухи со второго монитора. Каким образом диалог оказывается на первом, вообще не понимаю. Но тем не менее.

Imho HWND парента и монитор, на котором будет показано окно, ни как не связаны.

Я решил точно такую же проблему у себя таким образом: Перед вызовом функции из dll, отображающей окно, я ставлю хук на WH_CALLWNDPROCRET. Если в хуке приходит WM_SHOWWINDOW (или CM_ACTIVATE — это дельфовая специфика), то проверяю монитор, если он отличается, то ручками двигаю окно на правильный монитор.
Re[2]: Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 15.05.18 18:16
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Здравствуйте, Carc, Вы писали:


C>>Как переместить окно на другой монитор?


A>Imho HWND парента и монитор, на котором будет показано окно, ни как не связаны.

О как? Я как то думал что взаимосвязанные вещи, все таки дочерний же диалог!?!

A>Я решил точно такую же проблему у себя таким образом: Перед вызовом функции из dll, отображающей окно, я ставлю хук на WH_CALLWNDPROCRET. Если в хуке приходит WM_SHOWWINDOW (или CM_ACTIVATE — это дельфовая специфика), то проверяю монитор, если он отличается, то ручками двигаю окно на правильный монитор.

Дык судя по найденной функции они как-то так и делают. Я только не понял что такое HWND hMon — что за HWND монитора? HWND что ли парента, который в моем случае на втором мониторе? Может так? Там в гугловой ссылке плохо то, что функция дернута из контекста, а ссылка на MSDNЪ, которая ссылается на полную статью в лучших традициях Microsoft больше не существует…

И как Вы вычисляете насколько двигать и собственно как двигаете? Можно небольшой кусочек кода?
Aml Pages Home
Re[3]: Как переместить окно на другой монитор?
От: Aniskin  
Дата: 15.05.18 19:08
Оценка: 6 (1)
Здравствуйте, Carc, Вы писали:

A>>Я решил точно такую же проблему у себя таким образом: Перед вызовом функции из dll, отображающей окно, я ставлю хук на WH_CALLWNDPROCRET. Если в хуке приходит WM_SHOWWINDOW (или CM_ACTIVATE — это дельфовая специфика), то проверяю монитор, если он отличается, то ручками двигаю окно на правильный монитор.

C>Дык судя по найденной функции они как-то так и делают. Я только не понял что такое HWND hMon — что за HWND монитора? HWND что ли парента, который в моем случае на втором мониторе? Может так? Там в гугловой ссылке плохо то, что функция дернута из контекста, а ссылка на MSDNЪ, которая ссылается на полную статью в лучших традициях Microsoft больше не существует…

C>И как Вы вычисляете насколько двигать и собственно как двигаете?


Использую MonitorFromWindow для определения мониторов родительского и дочернего окон, GetMonitorInfo для получения размеров и позиции монитора, SetWindowPos(AWindow, 0, Left, Top, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOZORDER) для перемещения. Куда двигать — можно двигать в центр правильного монитора, но я двигаю в центр родительского окна с учетом того, что бы окно не вылезло за рамки монитора.

Если пойдешь по пути использования хуков, то нужно помнить, что WM_SHOWWINDOW будет приходить для всех окон, включая вложенные кнопки. Я проверяю наличие WS_POPUP, и включаю обработанное окно в список обработанных окон, и больше его не трогаю.

C>Можно небольшой кусочек кода?


Небольшой не получится, слишком много кода, и действий он производит чуть больше, чем описано, но думаю, смысл ясен из описания.
Re: Как переместить окно на другой монитор?
От: CEMb  
Дата: 16.05.18 06:29
Оценка: 6 (1)
Здравствуйте, Carc, Вы писали:

C>Как переместить окно на другой монитор?


C>Коллеги, просветите, куда копать?


Можно попробовать Multiple Display Monitors Functions, MonitorFromWindow, потом GetMonitorInfo и там получить размеры и координаты монитора, где лежит родительское окно
Re[2]: Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 16.05.18 06:59
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Carc, Вы писали:


C>>Как переместить окно на другой монитор?


C>>Коллеги, просветите, куда копать?


CEM>Можно попробовать Multiple Display Monitors Functions, MonitorFromWindow, потом GetMonitorInfo и там получить размеры и координаты монитора, где лежит родительское окно

Спасибо , это я первым делом покопал. Но я как-то так и понял примерно по тем полурезанным примерам… Но проблема в другом: ну нет у меня под рукой 2-ух мониторов — так что протестить не получается. Дык я и пытаюсь понять, чего там делать с арифметикой: кого куда с кем складывать…

Судя по присланным скриншотам от пользователя, такое ощущение что диалог как раз аккурат ровно встает — топ, лефт верные на глазок относительно родительского окна, но на соседнем мониторе. А вот чего с этим делать, неясно. Понятно, что GetMonitorInfo даст мне RECT монитора соседнего, а дальше чего!?! Какие значения там будут!?? Microsoft как всегда в документации не очень внятно пишет, где-что как по смыслу…
Aml Pages Home
Re[4]: Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 16.05.18 07:01
Оценка:
Здравствуйте, Aniskin, Вы писали:

C>>И как Вы вычисляете насколько двигать и собственно как двигаете?


A>Использую MonitorFromWindow для определения мониторов родительского и дочернего окон,

А MonitorFromWindow с каким флагом зовете? MONITOR_DEFAULTTONEAREST?
Aml Pages Home
Re[3]: Как переместить окно на другой монитор?
От: CEMb  
Дата: 16.05.18 07:33
Оценка: 9 (1)
Здравствуйте, Carc, Вы писали:

CEM>>Можно попробовать Multiple Display Monitors Functions, MonitorFromWindow, потом GetMonitorInfo и там получить размеры и координаты монитора, где лежит родительское окно

C>Спасибо , это я первым делом покопал. Но я как-то так и понял примерно по тем полурезанным примерам… Но проблема в другом: ну нет у меня под рукой 2-ух мониторов — так что протестить не получается. Дык я и пытаюсь понять, чего там делать с арифметикой: кого куда с кем складывать…

У тебя телевизор дома есть? Я телевизором проверял HDMI-шнур в лаптоп (думаю, в случае с десктопом любая видеокарта сейчас поддерживает второе гнездо HDMI) и в телек. В настойках у тебя появятся 2 монитора (по-моему это в Personalization) ты можешь мышкой перетащить второй монитор по отношению к первому.

C>Судя по присланным скриншотам от пользователя, такое ощущение что диалог как раз аккурат ровно встает — топ, лефт верные на глазок относительно родительского окна, но на соседнем мониторе. А вот чего с этим делать, неясно. Понятно, что GetMonitorInfo даст мне RECT монитора соседнего, а дальше чего!?! Какие значения там будут!?? Microsoft как всегда в документации не очень внятно пишет, где-что как по смыслу…


Там будут значения относительно твоего первого монитора, как в обычной системе координат, с центром в верхнем-левом углу первого монитора. К примеру, второй монитор слева — у него будут отрицательные координаты X. Сверху — отрицательные Y. Если первый монитор у тебя шириной 1600, то у монитора справа левый край будет иметь координату X == 1600, а верхний == 0. По идее, ты можешь второй монитор "поставить" с любым смещением относительно первого.
Re[5]: Как переместить окно на другой монитор?
От: Aniskin  
Дата: 16.05.18 07:59
Оценка: 6 (1)
Здравствуйте, Carc, Вы писали:

A>>Использую MonitorFromWindow для определения мониторов родительского и дочернего окон,

C>А MonitorFromWindow с каким флагом зовете? MONITOR_DEFAULTTONEAREST?

Да.
Re[3]: Как переместить окно на другой монитор?
От: uuuser  
Дата: 16.05.18 22:42
Оценка:
Здравствуйте, Carc, Вы писали:

C> Но проблема в другом: ну нет у меня под рукой 2-ух мониторов — так что протестить не получается.


так надо купить, пойдёт любая убитая пятнашка за несколько сотен деревянных

C> Дык я и пытаюсь понять, чего там делать с арифметикой: кого куда с кем складывать…


без реальных тестов будет сложно, так как другие мониторы могут быть и в отрицательных координатах
Re[4]: Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 18.05.18 11:41
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Там будут значения относительно твоего первого монитора, как в обычной системе координат, с центром в верхнем-левом углу первого монитора. К примеру, второй монитор слева — у него будут отрицательные координаты X. Сверху — отрицательные Y. Если первый монитор у тебя шириной 1600, то у монитора справа левый край будет иметь координату X == 1600, а верхний == 0. По идее, ты можешь второй монитор "поставить" с любым смещением относительно первого.


Дык я так и пытался. Ан фиг!
1) DLL получает клиентские координаты относительно своего парента HWND, ну и сам HWND парента. То бишь в DLL приходит параметрами HWND парента, и X,Y в клиентских координатах относительно парента, где показать диалог из DLL.

2)Потом DLL начинает проверять, сколько мониторов и если мониторов боле чем один, тогда как ты и описал

2) MonitorFromWindow — с HWND парента, чтобы получить монитор на котором парент.

3) Потом соответственно GetMonitorInfo с полученным монитором, чтобы получить его (монитора) RECT

4) Ну а потом к этим X,Y пришедшим в DLL в качестве параметра где показать диалог, в клиентских координатах относительно парента
добавляет top,left полученного RECT монитора.

По идее, если основная аппликуха находится на втором мониторе (справа) у него будут положительный left, и нулевой top.
Соответственно, вроде должно сместиться — но нифига. Пользователь говорит, что воз и ныне там — диалог из DLL, липнет к правому краю основного монитора. То бишь старается максимально "приблизиться" к аппликухе на втором мониторе справа, но все равно остается на первом мониторе…
Aml Pages Home
Отредактировано 18.05.2018 11:51 Carc . Предыдущая версия . Еще …
Отредактировано 18.05.2018 11:43 Carc . Предыдущая версия .
Re[5]: Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 18.05.18 11:42
Оценка:
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, CEMb, Вы писали:


CEM>>Там будут значения относительно твоего первого монитора, как в обычной системе координат, с центром в верхнем-левом углу первого монитора. К примеру, второй монитор слева — у него будут отрицательные координаты X. Сверху — отрицательные Y. Если первый монитор у тебя шириной 1600, то у монитора справа левый край будет иметь координату X == 1600, а верхний == 0. По идее, ты можешь второй монитор "поставить" с любым смещением относительно первого.


C>Дык я так и пытался. Ан фиг!

C>1) DLL получает клиентские координаты относительно своего парента HWND, ну и сам HWND парента. То бишь HWND парента, и X,Y в клиентских координатах относительно парента, где расположиться диалогу из DLL…

C>2)Потом DLL начинает проверять, сколько мониторов и если мониторов боле чем два, тогда как ты и описал


C>2) MonitorFromWindow — с HWND парента, чтобы получить монитор на котором парент.


C>3) Потом соответственно GetMonitorInfo с полученным монитором, чтобы получить его (монитора) RECT


C>4) Ну а потом к этим X,Y пришедшим в DLL в качестве параметра где показать диалог, в клиентских координатах относительно парента

C>добавляет top,left полученного RECT монитора.

C>По идее, если основная аппликуха находится на втором мониторе (справа) у него будут положительный left, и нулевой top.

C>Соответственно, вроде должно сместиться — но нифига. Пользователь говорит, что воз и ныне там — диалог из DLL, липнет к правому краю основного монитора. То бишь старается максимально "приблизиться" к аппликухе на втором мониторе справа, но все равно остается на первом мониторе…
Aml Pages Home
Re[5]: Как переместить окно на другой монитор?
От: Aniskin  
Дата: 18.05.18 22:55
Оценка: 6 (1)
Здравствуйте, Carc, Вы писали:

C>Дык я так и пытался. Ан фиг!

C>1) DLL получает клиентские координаты относительно своего парента HWND, ну и сам HWND парента. То бишь в DLL приходит параметрами HWND парента, и X,Y в клиентских координатах относительно парента, где показать диалог из DLL.

C>2)Потом DLL начинает проверять, сколько мониторов и если мониторов боле чем один, тогда как ты и описал


C>2) MonitorFromWindow — с HWND парента, чтобы получить монитор на котором парент.


C>3) Потом соответственно GetMonitorInfo с полученным монитором, чтобы получить его (монитора) RECT


C>4) Ну а потом к этим X,Y пришедшим в DLL в качестве параметра где показать диалог, в клиентских координатах относительно парента

C>добавляет top,left полученного RECT монитора.

C>По идее, если основная аппликуха находится на втором мониторе (справа) у него будут положительный left, и нулевой top.

C>Соответственно, вроде должно сместиться — но нифига. Пользователь говорит, что воз и ныне там — диалог из DLL, липнет к правому краю основного монитора. То бишь старается максимально "приблизиться" к аппликухе на втором мониторе справа, но все равно остается на первом мониторе…

Какая то сложная система. Dll чья? Твоя или сторонняя? Я вообще не понимаю, для чего эти пляски с мониторами. Если в dll передаются координаты, то не проще ли в dll просто получить положение родительского окна каким нибудь GetWindowRect и просто прибавить к ним переданное смещение?
Re[6]: Как переместить окно на другой монитор?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 19.05.18 05:36
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Какая то сложная система. Dll чья? Твоя или сторонняя?

DLL моя.

A>Я вообще не понимаю, для чего эти пляски с мониторами. Если в dll передаются координаты, то не проще ли в dll просто получить положение родительского окна каким нибудь GetWindowRect и просто прибавить к ним переданное смещение?

1) Дык от неопытности и спрашиваю… А GetWindowRect мне даст координаты с учетом координат монитора? Ну, там, к примеру, положительный top-left верхнего угла монитора, если он справа от основного!?!

2) Про пляски с монитором: я не могу просто прибавить GetWindowRect, если монитор один — всё поплывет… А хочется какой-то унификации кода…

Если честно, я уже сам запутался — то ли лыжи не едут, то ли я… Если диалог позиционируется по клиентским координатам относительно парента, то какого винда его вовсе куда-то ни туда, ни в тот монитор пихает? Сама то она точно знает, как соотносятся клиентские координаты относительно парента, в том смысле что парент на другом мониторе?

В любом случае, спасибо за помощь. Она как-то меня сподвигает понять в какую сторону копать, коль мой якобы "правильный" способ не приводит к нужному результату.
Aml Pages Home
Re[7]: Как переместить окно на другой монитор?
От: Aniskin  
Дата: 19.05.18 06:11
Оценка:
Здравствуйте, Carc, Вы писали:

C>Здравствуйте, Aniskin, Вы писали:


A>>Какая то сложная система. Dll чья? Твоя или сторонняя?

C>DLL моя.
И еще вопрос, на чем dll написана?

C>GetWindowRect мне даст координаты с учетом координат монитора?

GetWindowRect даст правильные координаты. Просто прибавляешь смещение к полученным координатам и получишь правильное положение дочерного окна без плясок с определением монитора. И еще нужно учесть, какое смещение ты передаешь в dll — от верхнего левого угла окна, или от верхнего левого угла клиентской части окна. Если второе, то вместо GetWindowRect можно использовать ClientToScreen(Parent, (0, 0)). Для твоей задачи тебе вообще не нужно знать ничего про мониторы и их положение.

C>я не могу просто прибавить GetWindowRect, если монитор один — всё поплывет…

Ничего не понял. А как ты отображаешь диалог на одном мониторе?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.