Я создаю глобальную горячую клавишу, чтобы показать окно с помощью PInvoking RegisterHotKey()
. Но для этого мне нужно это окно HWND
, которое не существует до тех пор, пока окно не будет загружено, это означает, что показано в первый раз. Но я не хочу показывать окно, прежде чем я могу установить горячую клавишу. Есть ли способ создать HWND
для этого окна, которое невидимо для пользователя?
Загрузка окна WPF без его отображения
Ответ 1
Если вы настроили таргетинг на .NET 4.0, вы можете использовать новый метод EnsureHandle
, доступный в WindowInteropHelper
:
public void InitHwnd()
{
var helper = new WindowInteropHelper(this);
helper.EnsureHandle();
}
(спасибо Томасу Левеску за указав это.)
Если вы ориентируетесь на более раннюю версию .NET Framework, самый простой способ - показать окно, чтобы перейти к HWND, установив несколько свойств, чтобы убедиться, что окно невидимо и не крадет фокус:
var window = new Window() //make sure the window is invisible
{
Width = 0,
Height = 0,
WindowStyle = WindowStyle.None,
ShowInTaskbar = false,
ShowActivated = false
};
window.Show();
Как только вы захотите отобразить фактическое окно, вы можете установить контент, размер и изменить стиль обратно в обычное окно.
Ответ 2
Это грязный хак, но он должен работать и не имеет недостатков в изменении непрозрачности:
- установите
WindowStartupLocation
вManual
- установите свойства
Top
иLeft
где-то вне экрана - установите
ShowInTaskbar
в false, чтобы пользователь не понимал, что есть новое окно -
Show
иHide
окно
Теперь вы можете получить HWND
EDIT: еще один вариант, возможно, лучше: установите ShowInTaskbar
на false и WindowState
на Minimized
, а затем покажите его: он вообще не будет отображаться
Ответ 3
Вы также можете изменить окно в так называемое окно только для сообщений. Поскольку этот тип окна не поддерживает графические элементы, он никогда не будет показан. В основном это сводится к вызову:
SetParent(hwnd, (IntPtr)HWND_MESSAGE);
Либо создайте выделенное окно сообщений, которое всегда будет скрыто, либо используйте реальное окно графического интерфейса пользователя и верните его в обычное окно, когда вы хотите его отобразить. См. Приведенный ниже код для более полного примера.
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hwnd, IntPtr hwndNewParent);
private const int HWND_MESSAGE = -3;
private IntPtr hwnd;
private IntPtr oldParent;
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
if (hwndSource != null)
{
hwnd = hwndSource.Handle;
oldParent = SetParent(hwnd, (IntPtr)HWND_MESSAGE);
Visibility = Visibility.Hidden;
}
}
private void OpenWindowMenuItem_Click(object sender, RoutedEventArgs e)
{
SetParent(hwnd, oldParent);
Show();
Activate();
}
Для меня решение установить ширину, высоту на ноль и стиль на ни один не получилось, так как оно все еще показало крошечное окно с раздражающей тенью того, что кажется границей окна 0x0 (проверено на Windows 7). Поэтому я предоставляю этот альтернативный вариант.
Ответ 4
Я уже опубликовал ответ на этот вопрос, но я нашел лучшее решение.
Если вам просто нужно убедиться, что HWND создан, без фактического отображения окна, вы можете сделать это:
public void InitHwnd()
{
var helper = new WindowInteropHelper(this);
helper.EnsureHandle();
}
(на самом деле метод EnsureHandle
недоступен, когда вопрос был опубликован, он был введен в .NET 4.0)
Ответ 5
Я никогда не пытался делать то, что вы делаете, но если вам нужно показать окно, чтобы получить HWND, но не хотите его показывать, установите Opacity Opacity равным 0. Это также предотвратит любой удар тестирование происходит. Тогда у вас может быть открытый метод в окне, чтобы изменить непрозрачность до 100, когда вы хотите сделать его видимым.
Ответ 6
Я ничего не знаю о WPF, но вы могли бы создать только окно сообщения, используя другие средства (например, PInvoke) для получения WM_HOTKEY сообщение? Если да, то после получения WM_HOTKEY вы можете запустить окно WPF.
Ответ 7
Класс WindowInteropHelper должен позволить вам получить HWND для окна WPF.
MyWindow win = new MyWindow();
WindowInteropHelper helper = new WindowInteropHelper(win);
IntPtr hwnd = helper.Handle;
Ответ 8
Другим вариантом в аналогичном ключе для установки непрозрачности 0 является установка размера 0 и установка позиции на экране. Для этого не требуется AllowsTransparency = True.
Также помните, что как только вы показали его, как только сможете, спрячьте его и получите hwnd.
Ответ 9
Сделайте размер окна 0 x 0 px, поместите ShowInTaskBar в значение false, покажите его, а затем измените его размер по мере необходимости.
Ответ 10
Я создал метод расширения для отображения невидимого окна, следующие Show
вызовы будут вести себя нормально.
public static class WindowHelper
{
public static void ShowInvisible(this Window window)
{
// saving original settings
bool needToShowInTaskbar = window.ShowInTaskbar;
WindowState initialWindowState = window.WindowState;
// making window invisible
window.ShowInTaskbar = false;
window.WindowState = WindowState.Minimized;
// showing and hiding window
window.Show();
window.Hide();
// restoring original settings
window.ShowInTaskbar = needToShowInTaskbar;
window.WindowState = initialWindowState;
}
}