Подтвердить что ты не робот

Может ли окно всегда находиться над одним другим окном?

В Windows можно установить окно A таким, что оно всегда находится над окном B, но разрешить другим окнам работать как обычно и отображаться поверх обоих, когда они активны.

Другими словами, мне нужны отношения между родителями и дочерними элементами между двумя окнами. Можно ли это сделать, не делая окно A дочерним элементом окна B, MDI-стиля? Окно B не мое (Internet Explorer) и закручивает мой диалог. Графика вверх, когда я пытаюсь достичь этого с помощью SetParent.

Мне показалось, что я взломал эту идею из сообщения MSDN форума, но, увы, окна A все еще всегда на высоте, не только окно B.

// Place window A on top
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
// Place window B underneath it
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);

Возможно ли это?

4b9b3361

Ответ 1

Не создавали бы отношения собственности, трюк?

SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner)

Окна могут быть в разных процессах, и вы можете вызывать это из любого процесса. Это гарантирует, что дочернее окно всегда находится над окном владельца. Это отличается от SetParent, который фактически создает отношения родителя/ребенка. Прочитайте эту статью (ее с 1993 года, но в основном правильнее), чтобы увидеть различие между владением и родительством.

Ответ 2

Когда ваш Z-порядок окна (или размер или позиция) изменяется, он должен получить сообщение WM_WINDOWPOSCHANGING. Если вы обрабатываете это сообщение, у вас есть возможность изменить окончательный Z-порядок (или размер или положение), на которое перемещается окно.

Чтобы проиллюстрировать в процедуре окна hWndA:

case WM_WINDOWPOSCHANGING:
    DefWindowProc(hWnd, msg, wParam, lParam);
    WINDOWPOS *p = (WINDOWPOS*)lParam;
    p->hwndInsertAfter = hWndB;
    p->flags &= ~SWP_NOZORDER;
    return 0;

следует вставить hWndA после hWndB в Z-порядке в любое время, когда изменится позиция hWndA.

Ответ 3

До Vista одним из способов сделать это было бы использование SetWindowsHookEx, и зацепить крюк WH_CBT или WH_CALLWNDPROC, а затем предпринять соответствующие действия при обнаружении изменения порядка Z. Однако это не работает с Vista (насколько я могу судить по googling).

Единственное другое решение, о котором я могу думать, - настроить таймер на огонь каждые несколько секунд, а затем, когда вы получите WM_TIMER, вы допросите систему, используя GetNextWindow, чтобы узнать, какое окно находится за вашим. Если это не IE, тогда позвоните SetWindowPos, чтобы разместить ваше окно над IE (я предполагаю, что у вас есть HWND для окна IE, о котором вы заботитесь, - помните, что может быть несколько окон IE).

Это вызовет проблемы, если люди попытаются вывести ваше окно на передний план - он вернется к тому, чтобы быть чуть выше IE. В этом случае в вашем коде вы можете обрабатывать WM_ACTIVATE и попытаться изменить Z-порядок окна IE, чтобы он находился под вашим окном (вызовите SetWindowPos, чтобы переместить окно IE, чтобы оно было выше окна, которое сейчас находится под вашим окном), Это решение может быть сопряжено с проблемами, поскольку Windows может попытаться помешать вам возиться с окнами другого процесса по соображениям безопасности. С другой стороны, в документах MSDN для SetWindowPos явно не упоминается, что вы не можете манипулировать окнами другого процесса. Однако могут быть и неясные ограничения.

Даже при этом взломе таймера у вас будет эффективный цикл ожидания ожидания в приложении (с частыми сообщениями WM_TIMER), и это обычно означает bad, особенно для время автономной работы ноутбуков и т.д. (потому что вы не позволяете процессору перейти в состояние ожидания и т.д.).

Я бы сказал, что нет хорошего способа сделать это, и все, что вы, вероятно, получите, будет хрупким и вызовет проблемы. Я настоятельно рекомендую не пытаться это сделать. Возможно ли сделать вашу программу в виде своего плагина или панели инструментов для IE?

NB Особо следует знать, что SetWindowsHookEx накладывает ограничение производительности на уровне всей системы, если вы идете по этому маршруту.

Ответ 4

Ответ Мориса - лучший из того, что здесь, но отсутствует важный шаг. Когда вы вызываете шоу в своем окне, которое вы хотите в качестве наложения, вам нужно вызвать метод show с параметром. Вам нужно определить класс, который реализует интерфейс IWin32Window, и просто создать новый экземпляр этого. Единственное, что касается интерфейса - это Handle, поэтому просто установите его в дескриптор окна IE, и он должен работать довольно хорошо.

Ответ 5

Можете ли вы получить доступ к Z-порядку окон?

Я не могу вспомнить по умолчанию z-порядок окон, но я думаю, что это 1. Вы могли бы установить IE в -1 и ваше приложение на 0.

Ответ 6

Попробуйте следующее:

// Place window A on top of window B
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);

Второй параметр дескриптора окна указывает следующее окно в порядке Z.

Обратите внимание, что это фактически не изменяет отношения родитель-потомок окна, но вы можете имитировать его.

Ответ 7

Если отношения родитель-ребенок выполняются самостоятельно с помощью функции SetWindowPos(), ваше желание может быть реализовано.