В таких приложениях, как Проводник Windows и Internet Explorer, можно захватить расширенные области фреймов под заголовком и перетаскивать окна вокруг.
Для приложений WinForms формы и элементы управления так же близки к собственным API-интерфейсам Win32, которые они могут получить; можно просто переопределить обработчик WndProc() в своей форме, обработать окно WM_NCHITTEST и обмануть систему, подумав о щелчке по рамка была действительно нажатием на строку заголовка, возвращая HTCAPTION. Я сделал это в своих приложениях WinForms для восхитительного эффекта.
В WPF я также могу реализовать аналогичный метод WndProc() и привязать его к моему дескриптору окна WPF, расширяя рамку окна в клиентской области, например:
// In MainWindow
// For use with window frame extensions
private IntPtr hwnd;
private HwndSource hsource;
private void Window_SourceInitialized(object sender, EventArgs e)
{
try
{
if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
{
throw new InvalidOperationException("Could not get window handle for the main window.");
}
hsource = HwndSource.FromHwnd(hwnd);
hsource.AddHook(WndProc);
AdjustWindowFrame();
}
catch (InvalidOperationException)
{
FallbackPaint();
}
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case DwmApiInterop.WM_NCHITTEST:
handled = true;
return new IntPtr(DwmApiInterop.HTCAPTION);
default:
return IntPtr.Zero;
}
}
Проблема заключается в том, что, поскольку я слепо устанавливаю handled = true и возвращаю HTCAPTION, щелчок в любом месте, кроме значка окна или кнопок управления, вызывает перетаскивание окна. То есть все, выделенное красным цветом, вызывает перетаскивание. Это даже включает в себя ручки изменения размера по бокам окна (неклиентская область). Мои элементы управления WPF, а именно текстовые поля и элемент управления вкладкой, также прекращают получать клики в результате:

Я хочу только
- строка заголовка и
- области клиентской области...
- ... которые не заняты моими элементами управления
можно перетаскивать. То есть, я хочу, чтобы эти красные области были перетаскиваемыми (клиентская область + строка заголовка):

Как мне изменить мой метод WndProc() и остальную часть моего окна XAML/code-behind, чтобы определить, какие области должны возвращать HTCAPTION, а какие нет? Я думаю что-то вроде использования Point для проверки местоположения клика относительно местоположений моих элементов управления, но я не уверен, как это сделать на WPF-земле.
РЕДАКТИРОВАТЬ [4/24]: один простой способ: иметь невидимый элемент управления или даже само окно, ответить на MouseLeftButtonDown, вызвав DragMove() в окне (см. Ответ Росса). Проблема в том, что по какой-то причине DragMove() не работает, если окно максимизировано, поэтому оно не играет хорошо с Windows 7 Aero Snap. Поскольку я собираюсь для интеграции с Windows 7, это не приемлемое решение в моем случае.