вторник, 30 марта 2010 г.

Как мне перекрыть панель задач окном во весь экран?

Это перевод How do I cover the taskbar with a fullscreen window? Автор: Реймонд Чен.

Почему-то, люди стараются идти сложным путём. Если вы хотите создать окно во весь экран, которое закроет панель задач - то просто создайте такое окно и панель задач сама уйдёт с вашего пути. Не надо её искать и скрывать; просто позвольте ей делать свою работу.

Как обычно, создайте пустое VCL приложение и добавьте в него:
uses
  MultiMon;

procedure TForm1.Button1Click(Sender: TObject);

  function CreateFullscreenWindow(const AWnd: HWND): HWND;
  var
    hmon: HMONITOR;
    mi: TMonitorInfo;
  begin
    hmon := MonitorFromWindow(AWnd, MONITOR_DEFAULTTONEAREST);
    FillChar(mi, SizeOf(mi), 0);
    mi.cbSize := SizeOf(mi);
    if not GetMonitorInfo(hmon, @mi) then
      Exit(0);
    Result := CreateWindow('static', 'Тут может происходить что-то интересное', WS_POPUP or WS_VISIBLE, mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, AWnd, 0, HInstance, nil);
  end;

begin
  CreateFullscreenWindow(Handle);
end;
Заметьте, что эта экспериментальная программа не закрывает и не удаляет окно и даже позволяет пользователю создать больше одного окна. В конце концов, это просто пример. Этот эксперимент показывает, что панель задач сама уходит с экрана для полноэкранных приложений.

Сначала мы используем функцию MonitorFromWindow, чтобы определить, на каком мониторе мы запущены (и на какой монитор нам размещать наше полноэкранное окно). Заметьте, что на машине с несколькими мониторами это может быть не тот монитор, на котором расположена панель задач. К счастью, нам не нужно об этом волноваться - панель задач сама во всём разберётся.
Примечание переводчика: если вы хотите разместить VCL-форму на весь экран, сделайте так:
procedure TForm1.FormCreate(Sender: TObject);
var
  hmon: HMONITOR;
  mi: TMonitorInfo;
begin
  hmon := MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST);
  FillChar(mi, SizeOf(mi), 0);
  mi.cbSize := SizeOf(mi);
  if GetMonitorInfo(hmon, @mi) then
    BoundsRect := mi.rcMonitor;
end;
Заметьте, что при этом стиль окна не должен позволять изменение его размеров (логично, не правда-ли?). Иными словами, BorderStyle может быть равен чему угодно, но только не bsSizeable и bsSizeToolWin (конечно же, при условии, что вы руками не играетесь со стилями окон).
Я видел как люди охотятся на окно панели задач, чтобы потом сделать ему ShowWindow(hwndTaskbar, SW_HIDE). Это сумасшедствие по многим причинам.

Во-первых, когда вы делаете такие трюки, вы должны всегда проводить мысленный эксперимент: "что если две программы попробуют сделать этот трюк?". Тогда у вас будет две программы, каждая из которых считает себя ответственной за панель задач, и ни одна из них не координирует свои действия с другой программой. В результате вы получаете хаос. Первая программа скрывает панель задач, затем это делает вторая программы, потом первая решает, что она закончила работу и показывает панель задач назад, но вторая программа ещё не закончила работать, поэтому она получает видимую панель задач, хотя она считает, что панель задач скрыта.

Во-вторых, что если ваша программа вылетит или зависнет до того, как она вернёт панель задач на место? Панель задач теперь скрыта навсегда и пользователю придётся выйти из системы и зайти снова, чтобы вернуть их панель задач. Это не очень-то вежливо.

В-третьих, что если у вас вообще нет панели задач? Это частый случай в сценариях с сервером терминалов по запуску программ без Проводника. В этой конфигурации у вас нет ни Проводника, ни панели задач. Или может быть вашу программу запустили на какой-то будущей версии Windows, в которой панель задач заменили на другой механизм. Что тогда будет делать ваша программа?

Не надо так играть с панелью задач. Просто создавайте окна, как вам нужно и позвольте панели задач выполнять свою работу.

5 комментариев:

  1. Кроме того, на экране могут ведь быть и другие панели, окромя панели задач. Код, скрывающий только панель задач, пропустит такие панели. Так что надо просто правильно создать окно - и всё.

    ОтветитьУдалить
  2. Наконец, пользователь может вообще использовать не стандартный Microsoft Explorer, а какой-либо другой GUI (Talisman Desktop etc.)

    ОтветитьУдалить
  3. Нет. Не прокатывает в Win7pro sp1 и Lazarus 1.2.0.

    ОтветитьУдалить
    Ответы
    1. Работает. Win7pro sp1 + Delphi7
      Но проще использовать глобальную переменную Screen (из модуля Forms) с ее методом MonitorFromWindow(Handle). Метод возвращает объект класса TMonitor и можно использовать его свойства (BoundsRect) для получения размера экрана.

      Удалить
    2. Это перевод, поэтому код оставлен "как есть": на WinAPI.

      Удалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.