Перестань быть самым верхним окном

Мое окно должно быть поверх определенного "целевого" окна, которое я не могу контролировать.

Когда целевое окно активировано, я звоню SetWindowPos с HWND_TOPMOST поместить мое окно поверх него, в то время как цель все еще может быть активным окном.

Когда целевое окно больше не является окном переднего плана, я хочу, чтобы мое окно по-прежнему находилось сверху целевого окна, но больше не было верхним, чтобы другие окна не закрывались им.

У меня было две идеи:

  • Вызов SetWindowPos с hWndInsertAfter быть только что активированным окном. Это терпит неудачу, когда только что активированное окно является самым верхним, потому что мое окно не теряет статус самого верхнего. Другая проблема с этим: если только что активированное окно - рабочий стол, то мое окно помещено ниже целевого окна.

  • Вызов SetWindowPos с HWND_NOTOPMOST потерять высший статус. Однако это приводит мое окно к вершине всех не верхних окон, поэтому оно охватывает только что активированное окно. Чтобы это исправить, я должен снова поднять только что активированное окно с другим SetWindowPos с HWND_TOP, Это похоже на неправильный способ сделать это и может вызвать мерцание.

Возможно ли, чтобы окно просто перестало быть самым верхним и помещало его ниже текущего переднего окна?

1 ответ

Решение

Единственный автоматический метод создания окна поверх другого, вне зависимости от того, является ли целевое окно самым верхним или нет, это отношение владелец / владелец. Вы можете попробовать использовать SetParent чтобы создать эти отношения, но обратите внимание, что Рэймонд Чен говорит, что это не рекомендуется.

Предполагая, что вы как-то отслеживаете активацию окна, я думаю, что ваш SetWindowPos Идея (первая) - это способ сделать это со следующей модификацией:

  • Когда целевое окно активно, установите ваше окно на HWND_TOPMOST
  • Когда цель теряет активацию, вставьте свое окно после непосредственного предшественника целевого окна в z-порядке (то есть фактически все еще сверху целевого окна, но не сверху).

Что-то вроде этого псевдо-кода:

if (foregroundwindow == targetwindow)
   SetWindowPos(my_window, HWND_TOPMOST, ...);
else
{
    HWND hwndPred = GetWindow(targetwindow, GW_HWNDPREV);
    if (!hwndPred)
    {
        // no predecessor so my_window will still be on top, just not top-most any more
        if (GetWindowLong(targetwindow, GWL_EXSTYLE) & WS_EX_TOPMOST)
            hwndPred = HWND_NOTOPMOST;
    }
    SetWindowPos(my_window, hwndPred, ...);
}
Другие вопросы по тегам