Установка Windows формируется, чтобы быть самой нижней

Некоторый фон

Один из моих текущих клиентов выполняет цепочку интернет-точек, где клиенты доступ сеть через PC:s, настроенный как "киоски" (сделанное на заказ приложение "блокирует" компьютер, пока пользователь не регистрировался, и репортаж, в большой степени ограничиваются через групповую политику Windows). В настоящее время каждый компьютер выполняет Windows XP и использует Active Desktop для отображения рекламных объявлений в фоновом режиме. Однако, так как у моего клиента есть проблемы с Active Desktop, отказывающим ежедневно (в дополнение к общему замедлению компьютера), меня попросили разработать приложение, которое заменяет его.

Проблема

Я пытаюсь заняться расследованиями, возможно ли создать приложение форм Windows (использующий C#), который всегда остается в фоновом режиме. Приложение должно лечь выше рабочего стола (так, чтобы это покрыло любые значки, файлы и т.д.), но всегда позади всех других запущенных приложений. Я предполагаю, что действительно ищу a BottomMost свойство Form класс (который не существует, конечно).

Любые подсказки или указатели о том, как достигнуть этого, высоко ценились бы.

14
задан Anders Fjeldstad 8 January 2010 в 12:53
поделиться

4 ответа

Пусть значение по умолчанию рассматривается как «никогда»

-121--4648628-

Я считаю null подходящим. Это ясно указывает на «не набор».

В зависимости от того, насколько сложно вы хотите получить, вы можете иметь перечисление и иметь некоторое состояние, как 'NeverExpires' в качестве 'UserState' (или что бы вы ни представляли). Это, вероятно, предпочтительнее, но может быть бесполезно сложным, в зависимости от того, что ваша система.

-121--4648627-

Это не поддерживается непосредственно классом .NET Form, поэтому у вас есть два параметра:

1) Используйте функцию Win32 API SetWindowPos .

pinvoke.net показывает, как объявить это для использования в C #:

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_NOACTIVATE = 0x0010;

Так что в вашем коде, вызов:

SetWindowPos(Handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

Как вы прокомментировали, это перемещает форму в нижнюю часть z-порядка, но не сохраняет его там. Единственный способ решения этой проблемы - вызвать события SetWindowPos из Form _ Load и Form _ Activate . Если ваше приложение максимизировано, и пользователь не может переместить или минимизировать форму, то вам может сойти с рук такой подход, но это все еще что-то вроде взлома. Кроме того, пользователь может увидеть небольшое «мерцание», если форма будет выведена на передний план z-порядка перед вызовом SetWindowPos .


2) подкласс формы , переопределить функцию WndProc и перехватить сообщение WM _ WINDOWPOSCHANGING Windows, установив флаг SWP_NOZORDER (взято с этой страницы ).

18
ответ дан 1 December 2019 в 12:52
поделиться

Да, функция SetWindowPos с флагом HWND_BOTTOM должна помочь вам. Но, по моему опыту, даже после вызова SetWindowPo в результате некоторых пользовательских операций ваше окно может оказаться перед глазами.

0
ответ дан 1 December 2019 в 12:52
поделиться

подклассифицируют форму, переопределяют функцию WndProc и перехватывают сообщения Windows, которые отвечают за перемещение их вверх по z-порядку при их активации.

0
ответ дан 1 December 2019 в 12:52
поделиться

Сделайте ваше окно дочерним окном рабочего стола («Диспетчер программ» или « прогман "процесс). Мне удалось использовать этот метод в Windows XP (x86) и Windows Vista (x64).

Я наткнулся на этот метод, когда искал способ сделать так, чтобы заставка отображалась как обои. Оказывается, это как бы встроено в системный обработчик .scr. Вы используете screensaver.scr / p PID , где PID - это идентификатор процесса другой программы, к которой нужно подключиться. Итак, напишите программу для поиска дескриптора программы, а затем вызовите.scr с этим аргументом / p, и у вас есть обои для заставки!

Проект, с которым я сейчас играю, - это отображение состояния рабочего стола (показывает время, некоторые задачи, подключенные диски и т. Д.), И он построен на Strawberry Perl и простом Win32 APIS (в основном Win32 :: GUI и Win32 :: Модули API), поэтому код легко переносить на любой динамический язык или понимать его с похожими привязками Win32 API или доступом к хосту сценариев Windows (например, ActivePerl, Python, JScript, VBScript). Вот соответствующая часть класса, который создает окно:

do { Win32::API->Import(@$_) or die "Win32::API can't import @$_ ($^E)" } for
    [user32 => 'HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)'],
    [user32 => 'HWND SetParent(HWND hWndChild, HWND hWndNewParent)'],

sub __screen_x {
    Win32::GUI::GetSystemMetrics(SM_CXSCREEN)
}
sub __screen_y {
    Win32::GUI::GetSystemMetrics(SM_CYSCREEN)
}
sub _create_window { # create window that covers desktop
    my $self = shift;
    my $wnd = $$self{_wnd} = Win32::GUI::Window->new(
        -width   => __screen_x(), -left => 0,
        -height  => __screen_y(), -top  => 0,
    ) or die "can't create window ($^E)";

    $wnd->SetWindowLong(GWL_STYLE,
        WS_VISIBLE
        | WS_POPUP # popup: no caption or border
    );
    $wnd->SetWindowLong(GWL_EXSTYLE, 
        WS_EX_NOACTIVATE # noactivate: doesn't activate when clicked
        | WS_EX_NOPARENTNOTIFY # noparentnotify: doesn't notify parent window when created or destroyed
        | WS_EX_TOOLWINDOW # toolwindow: hide from taskbar
    );
    SetParent($$wnd{-handle}, # pin window to desktop (bottommost)
        (FindWindow('Progman', 'Program Manager') or die "can't find desktop window ($^E)")
    ) or die "can't pin to desktop ($^E)";
    Win32::GUI::DoEvents; # allow sizing and styling to take effect (otherwise DC bitmaps are the wrong size)
}

Эта программа буферизует вывод для предотвращения мерцания, что вы, вероятно, тоже захотите сделать. Я создаю DC (контекст устройства) и PaintDesktop для него (вы можете использовать любое растровое изображение только с парой строк - CreateCompatibleBitmap, читать в файле и выбирать дескриптор растрового изображения как кисть), затем создаю буфер хранения, чтобы сохранить чистая копия этого фона и рабочий буфер для сборки частей - в каждом цикле копируйте в фон, затем рисуйте линии и растровые изображения кистью и используйте TextOut - который затем копируется в исходный DC, после чего он появляется на экран.

3
ответ дан 1 December 2019 в 12:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: