WPF: Rendez la fenêtre inutilisable, mais conservez le cadre?

J’ai une fenêtre qui n’a pas de barre de titre ( WindowStyle == WindowStyle.None ). La fenêtre entière utilise l’effet de verre Aero. Lorsque je rends la fenêtre inutilisable ( ResizeMode == ResizeMode.NoResize ), l’effet de vitre disparaît et mes contrôles sont suspendus. (Essentiellement, la fenêtre elle-même disparaît mais laisse son contenu.)

Y a-t-il un moyen de rendre la fenêtre inutilisable sans se débarrasser du cadre de la fenêtre?


J’ai lu la question Enable Vista glass effect sur une fenêtre WPF sans bordure , mais ce n’est pas tout à fait ce que je veux – je voudrais conserver la bordure de la fenêtre. Pour un exemple de ce que j’aimerais que ma fenêtre ressemble, appuyez sur Alt + Tab avec Aero activé.


Pour clarifier, je ne veux pas que les curseurs de redimensionnement apparaissent lorsque vous survolez la bordure de la fenêtre. C’est essentiellement ce que je veux que ma fenêtre ressemble à:

Projecteur http://img.zgserver.com/c%23/2mg4jty.png

La solution ne doit pas nécessairement être ssortingctement WPF. Je peux me contenter de pirater l’API Win32 pour y parvenir.

Vous pouvez connecter le wndproc et intercepter le message WM_WINDOWPOSCHANGING . Pas ssortingctement WPF, mais probablement votre meilleur pari.

Si vous voulez masquer les curseurs de redimensionnement, votre meilleur pari est d’intercepter WM_NCHITTEST . Appelez le DefWindowProc (pour obtenir le comportement par défaut) et testez la valeur de retour. s’il s’agit de HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTTOP, HTTOPLEFT ou HTTOPRIGHT, définissez la valeur de retour sur HTBORDER.

Basé sur la réponse d’Erics.

Exemple d'image

 public partial class MainWindow : Window { [DllImport("DwmApi.dll")] public static extern int DwmExtendFrameIntoClientArea( IntPtr hwnd, ref MARGINS pMarInset); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr DefWindowProc( IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); private const int WM_NCHITTEST = 0x0084; private const int HTBORDER = 18; private const int HTBOTTOM = 15; private const int HTBOTTOMLEFT = 16; private const int HTBOTTOMRIGHT = 17; private const int HTLEFT = 10; private const int HTRIGHT = 11; private const int HTTOP = 12; private const int HTTOPLEFT = 13; private const int HTTOPRIGHT = 14; public MainWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); } void MainWindow_Loaded(object sender, RoutedEventArgs e) { try { // Obtain the window handle for WPF application IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle; HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr); mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0); mainWindowSrc.AddHook(WndProc); // Set Margins MARGINS margins = new MARGINS(); margins.cxLeftWidth = 10; margins.cxRightWidth = 10; margins.cyBottomHeight = 10; margins.cyTopHeight = 10; int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins); // if (hr < 0) { //DwmExtendFrameIntoClientArea Failed } } // If not Vista, paint background white. catch (DllNotFoundException) { Application.Current.MainWindow.Background = Brushes.White; } } private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // Override the window hit test // and if the cursor is over a resize border, // return a standard border result instead. if (msg == WM_NCHITTEST) { handled = true; var htLocation = DefWindowProc(hwnd, msg, wParam, lParam).ToInt32(); switch (htLocation) { case HTBOTTOM: case HTBOTTOMLEFT: case HTBOTTOMRIGHT: case HTLEFT: case HTRIGHT: case HTTOP: case HTTOPLEFT: case HTTOPRIGHT: htLocation = HTBORDER; break; } return new IntPtr(htLocation); } return IntPtr.Zero; } private void Button_Click(object sender, RoutedEventArgs e) { this.Close(); } } [StructLayout(LayoutKind.Sequential)] public struct MARGINS { public int cxLeftWidth; // width of left border that retains its size public int cxRightWidth; // width of right border that retains its size public int cyTopHeight; // height of top border that retains its size public int cyBottomHeight; // height of bottom border that retains its size };      

Une façon pernicieuse de le faire serait de définir les propriétés MinWidth / MaxWidth et MinHeight / MaxHeight pour qu’elles ne soient plus exploitables. Bien sûr, le problème réside dans le fait que les curseurs de redimensionnement restnt sur les bordures.

Pourquoi ne créez-vous pas simplement cette bordure de fenêtre pour la fenêtre? Il utilise un décalage pour définir les couleurs de la fenêtre. Ainsi, un moyen simple consiste simplement à enrouler une bordure entière autour de votre fenêtre et en plus de cela, vous obtenez vos propres couleurs!