Если вы хотите изменить размер окна, которым вы не владеете (и без использования каких-либо ловушек), вы можете использовать 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. Любой другой размер окна приведет к тому, что ограничение вернет окно к ограниченным размерам рабочего стола, поскольку сообщение будет отправлено, а размер окна будет применен.
Изменение размера окна (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, такие как 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 Form рабочего стола.
Другие фреймворки
Другие фреймворки, такие как GTK и Qt, могут или не могут применять поведение и ограничения размера, и могут иметь различные обходные пути для преодоления этих ограничений. Любая данная программа может игнорировать, переписывать или обходить оконное сообщение, а инфраструктура может применять его во всем классе приложений, например, в WPF выше.
Подробнее об API SetWindowPos:
Справочный источник для Process_WM_SIZE
метода HwndSource
:
http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Interop/HwndSource.cs,da4aa32ad121c1b9,references
person
Maxx Daymon
schedule
09.11.2011