Есть у меня один очень древний проект. Программка, которая выводит небольшое окно со списком всех подключенных дисков со свободным местом на них (и обновляет его каждые N секунд).
Написана на Delphi очень давно. Сейчас я на Delphi уже давно не пишу (она даже не установлена и устанавливать не хочу). Посмотрел на её код - ужаснулся и решил переписать нормально на православном C
. Я просто подумал, что программка очень простая. По-этому, там никакое ООП и вот это вот всё не нужно. Да и работать она так будет максимально быстро. Собственно, переписать-то её получилось. Но возникла проблема.
У меня по HDMI подключен телевизор как второй монитор. Если перетащить программу на него и выключить его (телевизор), то винда автоматически перебрасывает программу, написанную на Delphi, на основной монитор. А программу на C
- нет. Она так и остаётся на прежних координатах где-то за пределами экрана. Я сразу понял, что дело в стилях окна.
Программа на C
создаёт окно вот так:
DWORD styleEx = isStayOnTop ? WS_EX_TOOLWINDOW | WS_EX_TOPMOST : WS_EX_TOOLWINDOW;
hMainWindow = CreateWindowEx(styleEx,
wndClassEx.lpszClassName, MY_TITLE,
WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP,
CW_USEDEFAULT, CW_USEDEFAULT, windowWidth, windowHeight,
NULL, NULL, selfInstance, NULL);
А Delphi так:
Application.Initialize;
Application.MainFormOnTaskbar := False;
Application.CreateForm(TForm1, Form1);
Application.Run;
На WinAPI
за скрытие кнопки с панели задач отвечает, кажется, стиль WS_POPUP
. Если его указать - кнопка окна с панели задач пропадает. А в Delphi VCL
окно TForm
и кнопка на панели задач - это два независимых окна. Главное окно (и не-главные окна) это класс TForm
, а кнопка на панели задач - класс TApplication
. Как это сделано - я не очень понимаю. Но отключается кнопка строчкой Application.MainFormOnTaskbar := False;
. При этом, как я понял, стили главного окна не меняются. То есть, ковыряться в стилях окон WinAPI
бесполезно.
В результате, программа на Delphi видна в диспетчере задач как окно. Программа на C
отображается в подгруппе “фоновые процессы”. Но сегодня, пока писал этот пост, обнаружил, что программа вообще перестала отображаться в диспетчере. Видно только её процесс. Наверное, надо комп перезагрузить и тогда она снова появится в фоновых процессах.
Но факт очевиден. Если кнопка окна скрыта флагом WS_POPUP
, винда думает, что это фоновый процесс (окно скрыто) и по-этому его не переносит.
Конечно, можно перехватывать сообщение WM_DISPLAYCHANGE
и вручную перемещать окно куда надо. Но в 11 винде добавили какую-то странную фишку. Винда стала запоминать положение окна для обоих мониторов. То есть. Когда телевизор выключен, ставишь окно в какое-нибудь место (назовём это позиция1
), потом включаешь телевизор и вручную переносишь окно на него (позиция2
). Потом вкл/выкл/вкл/выкл телевизор и окно само скачет между этими двумя позициями. Программа на C
так не делает.
Вручную сделать такое будет проблематично. А тут оно вдруг само как-то стало работать
Можно как-то сделать такое же поведение на WinAPI
, не пиша(руззкий язык!) много кода?
Ну, то есть, чтобы кнопки на панели задач не было и программа отображалась в диспетчере как не-фоновый процесс. Думаю, причина в этом.