Если вы хотите изменить размер окна, которым вы не владеете (и без использования каких-либо перехватчиков), вы можете использовать Windows SetWindowPos API с установленным флагом SWP_NOSENDCHANGING (0x0400):
BOOL WINAPI SetWindowPos(
__in HWND hWnd,
__in_opt HWND hWndInsertAfter,
__in int X,
__in int Y,
__in int cx,
__in int cy,
__in UINT uFlags // ** SWP_NOSENDCHANGING must be passed here **
);
Это предотвратит отправку сообщения WM_WINDOWPOSCHANGING, которое вызывает ограничение WM_GETMINMAXINFO. Любое другое изменение размера окна приведет к тому, что ограничение вернет окно к ограниченным размерам рабочего стола, так как сообщение будет отправлено и размер окна будет принудительно установлен.
Окно Resizer (C #)
Ниже приведен небольшой пример программы, которая изменит размер Блокнота на 6000x6000 (измените строку «Без названия - Блокнот» на заголовок окна, размер которого вы хотите изменить, или извлеките имя окна и желаемый размер из аргументов командной строки)
namespace Example
{
class Program
{
[DllImport("USER32.DLL")]
public static extern IntPtr FindWindow(String className, String windowName);
[DllImport("USER32.DLL", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int left, int top, int width, int height, uint flags);
static void Main(string[] args)
{
var TOP = new IntPtr(0);
uint SHOWWINDOW = 0x0040, NOCOPYBITS = 0x0100, NOSENDCHANGING = 0x0400;
var hwnd = FindWindow(null, "Untitled - Notepad");
SetWindowPos(hwnd, TOP, 0, 0, 6000, 6000, NOCOPYBITS | NOSENDCHANGING | SHOWWINDOW);
}
}
}
Ограничения и предостережения
Этот подход, как правило, функционален, но есть ряд ограничений, которые могут помешать изменению размера окна или изменению размера любым полезным способом.
Безопасность
Начиная с Windows Vista, Microsoft внедрила повышенную безопасность вокруг оконных сообщений. Исполняемый файл может взаимодействовать только с окнами в своем собственном контексте безопасности или ниже. Например, чтобы изменить размер окна «Управление компьютером» (которое всегда выполняется с повышенными правами), эта программа должна также работать с повышенными правами.
Исправлена логика Windows и макета
Размеры окна могут быть принудительно применены пассивно или активно программой. Окно с принудительно установленным размером пассивно устанавливает начальный размер и просто не предоставляет пользователю возможности изменять размер окна (например, не управляет размером захвата). Размер этих окон обычно можно изменить, отправив сообщение, как описано, но из-за отсутствия логики макета не покажет что-либо другое, кроме дополнительной пустой клиентской области.
Windows с active принудительно контролирует размер, либо перехватывая сообщения Windows, такие как WM_SIZE, либо в более сложной логике компоновки. Эти окна могут принимать сообщение, но ограничивают или ограничивают окончательный размер в своем собственном коде.
В любом случае в Windows с фиксированными размерами, как правило, отсутствует какая-либо логика компоновки, чтобы использовать преимущества больших размеров, поэтому, даже если вы можете ее форсировать, изменение их размера не дает никаких преимуществ.
WPF
Класс Window
в WPF имеет HwndSource
, который обрабатывает оконные сообщения, отправленные в окно WPF. Приватный метод LayoutFilterMessage
перехватывает сообщения WM_SYSCOMMAND
, WM_SIZING
, WM_WINDOWPOSCHANGING
и WM_SIZE
. В этом случае сообщение WM_SIZE
затем обрабатывается закрытым Process_WM_SIZE
, который фактически обходит флаг NOSENDCHANGING
и изменяет RenderSize
клиентской области WPF. Это часть общего процесса адаптации старых сообщений Win32 к событиям WPF.
Чистый эффект заключается в том, что размер окна Win32 host изменяется (если для параметра SizeToContent не установлено значение SizeToContent.WidthAndHeight), но область рендеринга WPF заблокирована для области рабочего стола, так как если флаг NOSENDCHANGING не был установлен. Когда приведенный выше пример кода запускается для приложения WPF, вы можете увидеть окно 6000x6000 в Aero Peek на панели задач или предварительный просмотр окна в переключателе Windows-Tab, но вы также можете увидеть, что содержимое WPF и логика макета обрезаны до область рабочего стола. Таким образом, окно WPF похоже на активно принудительное окно, но вместо принудительного применения определенного размера обеспечивает применение определенного максимального (для RenderArea) и не учитывает WM_WINDOWPOSCHANGING
сообщение.
Если это ваше собственное приложение и вы размещаете WPF в окне Windows Forms (через ElementHost
), вы можете изменить размер окна, и содержимое WPF будет соответствовать большему окно формы Windows для рабочего стола.
Другие рамки
Другие структуры, такие как GTK и Qt, могут или не могут применять поведение и ограничения размера, и могут иметь различные обходные пути, позволяющие преодолеть эти ограничения. Любая данная программа может игнорировать, переписывать или обходить оконное сообщение, и инфраструктура может применять его ко всему классу приложений, например, с WPF выше.
Подробнее об API SetWindowPos:
Справочный источник для Process_WM_SIZE
метод HwndSource
:
http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Interop/HwndSource.cs,da4aa32ad121c1b9,references