2009-08-24 3 views
3

J'ai écrit une propriété attachée que je peux définir sur une fenêtre pour étendre le cadre de verre dans la zone client (en utilisant l'API DwmExtendFrameIntoClientArea). Cela fonctionne bien dans la plupart des cas. Maintenant, je veux que ma fenêtre soit sans marge, donc je définir les attributs suivants sur ma fenêtre:Activer l'effet de verre Vista sur une fenêtre WPF sans bordure

WindowStyle="None" 
    ResizeMode="NoResize" 
    Background="Transparent" 
    u:WinUtil.EnableGlass="True" 
    ShowInTaskbar="False" 

Mais avec ces attributs, le verre ne montre pas du tout: ma fenêtre a juste un fond transparent. Si je règle ResizeMode à CanResize, le verre est montré, mais je ne veux pas que la fenêtre soit redimensionnable. Je suppose que c'est dû au fait que l'effet de verre est obtenu en étendant la trame non-client dans la zone client: avec WindowStyle = None et ResizeMode = NoResize, il n'y a pas de trame non-client, donc il n'y a rien à étendre. Lorsque j'active le redimensionnement, il crée un cadre autour de la fenêtre afin que le cadre puisse être étendu.

je suppose qu'il devrait être possible de créer une fenêtre qui a une bordure mince, pas de barre de titre, et ne peut être redimensionnée, en réglant le WS_ approprié * bits, mais je ne sais pas quels sont ceux exactement

Mes questions sont les suivantes:

  1. Quels sont les bits de style doit être activé ou désactivé pour avoir l'apparence souhaitée et le comportement?
  2. Comment puis-je initialiser les bits de style de la fenêtre? La classe Window ne semble pas avoir quelque chose comme la propriété Windows Forms CreateParams ... Est-il correct de définir ces bits après que le handle a été créé?
  3. J'ai trouvé la classe HwndSource qui pourrait être une réponse à la question 2, mais il semble un peu complexe à utiliser si vous n'êtes pas un expert Win32 ... Serait-ce une solution raisonnable à mon problème?

Tout conseil est le bienvenu

Répondre

5

Avez-vous essayé d'utiliser DwmEnableBlurBehindWindow? Cela vous permet de rendre transparente une partie spécifique de la zone cliente d'une fenêtre.

+0

Cela semble prometteur, merci. Maintenant, je dois comprendre comment l'utiliser, mais il ne semble pas trop mal;) –

+0

Pas de chance jusqu'à présent, ma fenêtre reste désespérément noir ... –

+3

OK, je l'ai eu ... Je devais définir le 'CompositionTarget .BackgroundColor' à 'Transparent', et' AllowsTransparency' à true. Merci ! –

4

J'ai eu une fenêtre que je voulais donner juste une vitrine (sans barre de titre et non redimensionnable) et a rencontré le même problème que vous. Vous ne pouvez pas accomplir cela en définissant le style de Windows. Ma solution consistait à définir ResizeMode = "CanResize" et WindowStyle = "None" puis à gérer l'événement WM_NCHITTEST pour convertir les hits de la taille redimensionnable en hits non-redimensionnables. Il était également nécessaire de modifier le style de la fenêtre pour désactiver maximiser et minimiser (à l'aide des raccourcis Windows) et le menu du système:

private void Window_SourceInitialized(object sender, EventArgs e) 
{ 
    System.Windows.Interop.HwndSource source = (System.Windows.Interop.HwndSource)PresentationSource.FromVisual(this); 
    source.AddHook(new System.Windows.Interop.HwndSourceHook(HwndSourceHook)); 

    IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(this).Handle; 
    IntPtr flags = GetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/); 
    SetWindowLongPtr(hWnd, -16 /*GWL_STYLE*/, new IntPtr(flags.ToInt64() & ~(0x00010000L /*WS_MAXIMIZEBOX*/ | 0x00020000L /*WS_MINIMIZEBOX*/ | 0x00080000L /*WS_SYSMENU*/))); 
} 

private static IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
{ 
    switch (msg) 
    { 
     case 0x0084 /*WM_NCHITTEST*/: 
      IntPtr result = DefWindowProc(hwnd, msg, wParam, lParam); 
      if (result.ToInt32() >= 10 /*HTLEFT*/ && result.ToInt32() <= 17 /*HTBOTTOMRIGHT*/) 
      { 
       handled = true; 
       return new IntPtr(18 /*HTBORDER*/); 
      } 
      break; 
    } 
    return IntPtr.Zero; 
} 

[System.Runtime.InteropServices.DllImport("user32.dll")] 
private static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); 

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); 
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); 

Cela vous donne une fenêtre dans Windows 7 adapté pour flyouts zone de notification (par exemple, l'horloge ou le volume flyouts). BTW, vous pouvez reproduire l'ombrage au bas du flyout en créant un contrôle de la hauteur 44 et en définissant son arrière-plan:

<Control.Background> 
    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 
     <GradientStop Color="{x:Static SystemColors.GradientActiveCaptionColor}" Offset="0"/> 
     <GradientStop Color="{x:Static SystemColors.InactiveBorderColor}" Offset="0.1"/> 
    </LinearGradientBrush> 
</Control.Background> 
Questions connexes