This is an odd one and a work around to problems on a customer system. It also happens to be something I'd like to do as my app doesn't function well across monitos.
Using an app written in WPF/C#, a customer tries to maximize the window. His machine is running win 8.1, 640bit with three monitors. On maximizing the window it expand to cover all three windows, and then terminates with a "invalid DPI error", which I believe is coming from the display driver. This is easy enough to fix by hooking the main windows wndproc and limiting its max size to be only as large as the monitor it is on.
Now the app uses XamDockManager, and consists of several tabs that the user can 'pop out' to be their own window. They end up being PaneToolWindows, I've tried to find the HWND so I can hook into the wndproc of the window that manages this window so when the users presses maximize on the tool bar window it maximize to the monitor it is located on. Unfortunately I haven't been successful.
I am sure I am missing something that will allow me to limit the size of the tool window (hopefully dynamically so it can be limited to the monitor it on.)
What can you recommend I try?
On the main window this is what I do:
Hooking the WNDPROC in the loaded event:
// Attach our WndProc handler to this WindowHwndSource source = HwndSource.FromHwnd(Handle);
Debug.Assert(source != null, "source != null");// ReSharper disable once ConditionIsAlwaysTrueOrFalseif (source != null) source.AddHook(WndProc);
The Wnd Proc
// ReSharper disable PossibleNullReferenceExceptionprivate IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){// Check if a System Command has been executedswitch (msg){case NativeMethods.WM_GETMINMAXINFO:{MonitorInfo.WmGetMinMaxInfo(hwnd, lParam);handled = true;}break;
break;
}
return IntPtr.Zero;}
Routine to set the MIn/max Info stucture based on windows monitor:
public static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam){var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
// Adjust the maximized size and position to fit the work area of the correct monitorIntPtr monitor = MonitorFromWindow(hwnd, (int)MonitorFromWindowFlags.MONITOR_DEFAULTTONEAREST);
if (monitor != IntPtr.Zero){var monitorInfo = new MONITORINFO();GetMonitorInfo(monitor, monitorInfo);RECT rcWorkArea = monitorInfo.rcWork;RECT rcMonitorArea = monitorInfo.rcMonitor;mmi.ptMaxPosition.X = Math.Abs(rcWorkArea.Left - rcMonitorArea.Left);mmi.ptMaxPosition.Y = Math.Abs(rcWorkArea.Top - rcMonitorArea.Top);mmi.ptMaxSize.X = Math.Abs(rcWorkArea.Right - rcWorkArea.Left);mmi.ptMaxSize.Y = Math.Abs(rcWorkArea.Bottom - rcWorkArea.Top);}
Marshal.StructureToPtr(mmi, lParam, true);}
I'm looking for a way to accomplish the same thing on a tool window.
I've try hooking in the toolwindow loaded event, but with out success:
//ToolWindow toolWindow = VisualTreeHelperExtended.GetAncestor(e.Window, typeof (ToolWindow)) as ToolWindow;//if (toolWindow != null)//{// DependencyObject toolWindowPresenter = VisualTreeHelper.GetParent(toolWindow as DependencyObject);
// if (toolWindowPresenter != null)// {// DependencyObject toolWindowHost = VisualTreeHelper.GetParent(toolWindowPresenter);
// if (toolWindowHost != null)// {// Window twh = toolWindowHost as Window;
// if (twh != null)// {// IntPtr handle = new WindowInteropHelper(twh).EnsureHandle();
// HwndSource source = (HwndSource) HwndSource.FromHwnd(handle);
// Debug.Assert(source != null, "source != null");
// // ReSharper disable once ConditionIsAlwaysTrueOrFalse// if (source != null)// source.AddHook(ToolWindowWndProc);// }// }// }//}
I know it a weird one, but anything you can do to help is appreciated.
Hi dcg1212,
Let me know if you have any further questions on this matter.
Well one option might be to just set the MaxWidth and MaxHeight of the PaneToolWindow in the ToolWindowLoaded event (via the Window property of the event args).
If that isn't sufficient then you might try getting the HwndSource using the PresentationSource.FromVisual method in the ToolWindowLoaded; you'll need to check the return type and upcast from PresenationSource to HwndSource. I'm not sure if it will be available at that point but even if it is then you probably want to add a handler into the PresentationSource.AddSourceChangedHandler method in the ToolWindowLoaded so you can respond (unhook from the old and hook into the new assuming its non-null) when/if the HwndSource changes. You should also hook into the ToolWindowUnloaded and make sure you remove that handler (using PresentationSource.RemoveSourceChangedHandler).