J'essaie le contrôle Ribbon
en combinaison avec RibbonWindow
, mais ils échouent même dans des expériences triviales.
System.Windows.Controls.Ribbon
et suppression du préfixe ribbon:
(pourquoi les exemples sont-ils obsolètes?).Je peux déjà voir de nombreux problèmes:
Déplaçons la barre d'outils vers le bas. Maintenant nous voyons ceci:
Les boutons sont en dehors de la barre d'outils.
Et enfin, maximisons la fenêtre:
La moitié de l'en-tête a disparu en dehors de l'écran (techniquement, la fenêtre correspond à en dehors de l'écran de 8 pixels de chaque côté, mais les autres applications ne sont pas gênées par cela).
J'utilise Windows 7, Aero, un seul moniteur, rien de spécial. J'ai peur de tester l'application sur Windows 8 ...
Une chance de résoudre ce problème?
Sous le capot, la classe WindowChrome
lie sa ResizeBorderThickness
à SystemParameters.WindowResizeBorderThickness
qui utilise à son tour l'API Win32 GetSystemMetrics
pour déterminer la taille de la bordure système.
Toutefois, le comportement de cette méthode change en fonction de la version du sous-système définie dans l'en-tête PE exécutable. Si elle est compilée uniquement pour Windows Vista et versions ultérieures (version> = 6.0), les bordures seront plus fines que si elles étaient compilées pour des systèmes d'exploitation plus anciens. Plus d'informations à ce sujet dans cette SO réponse.
Lors de la compilation avec .NET 4.5, le compilateur C # définit cette version sur 6.0 car .NET 4.5 ne peut pas être utilisé sous XP. Toutefois, la classe WindowChrome
semble s'appuyer sur le comportement hérité et ne parvient donc pas à calculer correctement la taille du verre sous Windows Vista et 7.
Vous pouvez compiler avec .NET 4 pour forcer le compilateur à utiliser 4.0 comme valeur de version de sous-système. Le ruban est disponible pour WPF 4 en tant que téléchargement séparé _. Notez que même avec cette solution, vous devez décocher "Activer le processus d'hébergement Visual Studio" dans les propriétés du projet à des fins de débogage. Sinon, le processus vshost.exe sera utilisé, ce qui est signalé par une version de sous-système de 6.0.
Edit: Olly a fourni un moyen de le faire dans les commentaires:
Ajoutez une propriété dans le fichier de projet
<subsystemversion>5.01</subsystemversion>
qui indique faussement que Le code peut être exécuté sur Windows XP.
Vous pouvez modifier la propriété attachée WindowChrome.WindowChrome
dans votre fenêtre et utiliser les valeurs souhaitées, ignorant ainsi complètement les valeurs système. Vous ne devriez jamais faire cela, mais vous le pouvez.
Il y a un bogue existant sur Connect concernant le changement de comportement de GetSystemMetrics
, mais tout se résume à la version du sous-système, il s'agit donc plutôt d'une fonctionnalité du point de vue de Microsoft. Cependant, la classe WindowChrome
devrait vraiment être corrigée pour fonctionner correctement sous Vista/7, d’autant plus qu’elle est maintenant intégrée à .NET 4.5.
Voici un autre moyen de contourner le problème, très simple et très simple. Ajoutez simplement une marge négative dans la barre d’outils. Vous devez conserver la classe de fenêtre d'origine et non la fenêtre Ribbon!
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
Title="Application Name" Height="350" Width="525" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
Ajoutez simplement cette marge au titre du ruban
<Ribbon Title="" Foreground="#333333" Margin="0,-22,0,0">
Maintenant, lorsque vous maximisez la fenêtre, tout reste bien
Pour quiconque lit cette question, je réponds moi-même. Oubliez l'horrible contrôle de ruban empaqueté et utilisez autre chose. Recherchez quelques-unes des alternatives ici: Quelle est la meilleure suite de contrôles de ruban WPF? (comme toutes les bonnes questions, il est fermé cependant).
Jusqu'à présent, Fluent Ribbon Control Suite me semble être la meilleure option gratuite. Les fonctionnalités de base fonctionnent simplement (pas de problèmes de bordures et de maximisation, redimensionnement de la fenêtre n’est pas si lent, etc.) Il possède des styles Office et les préserve si Glass est désactivé (cela signifie que vous ne verrez pas la fenêtre Windows9x-ish dans Metro). Son interface (backstage, QAT) ressemble plus à Office 2010.
Peut-être que dans un futur lointain, Microsoft va réparer son ruban, mais pour le moment, cherche des alternatives.
J'ai eu le même problème avec le titre dans la RibbonWindow. Je l'ai résolu en définissant le style global du TextBlock dans RibbonTitlePanel.
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type primitives:RibbonTitlePanel}},Path=Visibility}" Value="Visible"></Condition>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type RibbonWindow}},Path=WindowState}" Value="Maximized"></Condition>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
Ce n'est pas une solution, peut-être même pas une solution de contournement, mais plutôt un bidouillage que j'espère ne pas utiliser que pendant une courte période, le temps que le problème soit résolu dans le cadre.
Le code est principalement copier-coller de cette question https://stackoverflow.com/a/8082816/44726
J'ai changé la position autorisée de l'écran, ce qui semble résoudre le problème, pas le résoudre.
Call est comme ça dans le code derrière
InitializeComponent();
RibbonWindowService.FixMaximizedWindowTitle(this);
public static class RibbonWindowService
{
public static void FixMaximizedWindowTitle(Window window)
{
window.SourceInitialized += WinSourceInitialized;
}
[DllImport("user32")]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport("User32")]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x0024:
WmGetMinMaxInfo(hwnd, lParam);
handled = true;
break;
}
return (IntPtr)0;
}
private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
{
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
// Adjust the maximized size and position to fit the work area of the correct monitor
int MONITOR_DEFAULTTONEAREST = 0x00000002;
IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor != IntPtr.Zero)
{
MONITORINFO monitorInfo = new MONITORINFO();
GetMonitorInfo(monitor, monitorInfo);
RECT rcWorkArea = monitorInfo.rcWork;
RECT rcMonitorArea = monitorInfo.rcMonitor;
// Offset top and left 1 pixel improves the situation
rcMonitorArea.top += 1;
rcMonitorArea.left += 1;
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);
}
private static void WinSourceInitialized(object sender, EventArgs e)
{
IntPtr handle = (new WinInterop.WindowInteropHelper((Window)sender)).Handle;
WinInterop.HwndSource.FromHwnd(handle).AddHook(WindowProc);
}
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
};
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
/// <summary>
/// x coordinate of point.
/// </summary>
public int x;
/// <summary>
/// y coordinate of point.
/// </summary>
public int y;
/// <summary>
/// Construct a point of coordinates (x,y).
/// </summary>
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct RECT
{
/// <summary> Win32 </summary>
public int left;
/// <summary> Win32 </summary>
public int top;
/// <summary> Win32 </summary>
public int right;
/// <summary> Win32 </summary>
public int bottom;
/// <summary> Win32 </summary>
public static readonly RECT Empty = new RECT();
/// <summary> Win32 </summary>
public int Width
{
get { return Math.Abs(right - left); } // Abs needed for BIDI OS
}
/// <summary> Win32 </summary>
public int Height
{
get { return bottom - top; }
}
/// <summary> Win32 </summary>
public RECT(int left, int top, int right, int bottom)
{
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
/// <summary> Win32 </summary>
public RECT(RECT rcSrc)
{
left = rcSrc.left;
top = rcSrc.top;
right = rcSrc.right;
bottom = rcSrc.bottom;
}
/// <summary> Win32 </summary>
public bool IsEmpty
{
get
{
// BUGBUG : On Bidi OS (hebrew arabic) left > right
return left >= right || top >= bottom;
}
}
/// <summary> Return a user friendly representation of this struct </summary>
public override string ToString()
{
if (this == Empty)
{
return "RECT {Empty}";
}
return "RECT { left : " + left + " / top : " + top + " / right : " + right + " / bottom : " + bottom + " }";
}
/// <summary> Determine if 2 RECT are equal (deep compare) </summary>
public override bool Equals(object obj)
{
if (!(obj is Rect))
{
return false;
}
return (this == (RECT)obj);
}
/// <summary>Return the HashCode for this struct (not garanteed to be unique)</summary>
public override int GetHashCode()
{
return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode();
}
/// <summary> Determine if 2 RECT are equal (deep compare)</summary>
public static bool operator ==(RECT rect1, RECT rect2)
{
return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom);
}
/// <summary> Determine if 2 RECT are different(deep compare)</summary>
public static bool operator !=(RECT rect1, RECT rect2)
{
return !(rect1 == rect2);
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MONITORINFO
{
/// <summary>
/// </summary>
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
/// <summary>
/// </summary>
public RECT rcMonitor = new RECT();
/// <summary>
/// </summary>
public RECT rcWork = new RECT();
/// <summary>
/// </summary>
public int dwFlags = 0;
}
}