usar - wpf c# ejemplos
Obtén el color activo del tema de color automático de Windows 8 (2)
Esto se puede hacer en .NET 4.5 y versiones posteriores sin P / Invokes. La clase SystemParameters ahora tiene WindowGlassBrush estáticas WindowGlassBrush y WindowGlassColor junto con un evento StaticPropertyChanged .
Desde XAML, puede enlazar a la propiedad WindowGlassBrush como:
<Grid Background="{x:Static SystemParameters.WindowGlassBrush}">
Sin embargo, con esta asignación, el color de fondo no se actualizará automáticamente cuando Windows cambie sus colores. Desafortunadamente, SystemParameters no proporciona las propiedades WindowGlassBrushKey o WindowGlassColorKey para usarlas como ResourceKeys con DynamicResource, por lo que obtener notificaciones de cambios requiere un código para manejar el evento StaticPropertyChanged.
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
SystemParameters.StaticPropertyChanged += this.SystemParameters_StaticPropertyChanged;
// Call this if you haven''t set Background in XAML.
this.SetBackgroundColor();
}
protected override void OnClosed(EventArgs e)
{
SystemParameters.StaticPropertyChanged -= this.SystemParameters_StaticPropertyChanged;
base.OnClosed(e);
}
private void SetBackgroundColor()
{
this.Background = SystemParameters.WindowGlassBrush;
}
private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "WindowGlassBrush")
{
this.SetBackgroundColor();
}
}
}
En Windows 8, he establecido el esquema de color en automático y configuré mi fondo de pantalla para que cambie después de x minutos. El esquema de color cambia según el fondo de pantalla activo.
Estoy desarrollando una aplicación WPF y me gustaría que mis gradientes cambien cuando Windows cambie la combinación de colores para que coincida con el fondo de pantalla actual.
¿Hay alguna manera de obtener el esquema de color actual / real y ser notificado del cambio en C #?
Si es posible. Sin embargo, tenga cuidado: esto abarca un poco de interoperabilidad de Win32 (esto significa P / Invokes en archivos DLL nativos desde código administrado), y solo es factible con ciertas API no documentadas . Aunque, las únicas características no documentadas involucradas son para obtener el esquema de color de la ventana (o como lo llama DWM, el color de la colorización de la ventana), que se trata en esta otra pregunta:
Vista / 7: ¿Cómo conseguir el color del vidrio?
En mi propio proyecto, hago uso de una llamada a DwmGetColorizationParameters()
:
internal static class NativeMethods
{
[DllImport("dwmapi.dll", EntryPoint="#127")]
internal static extern void DwmGetColorizationParameters(ref DWMCOLORIZATIONPARAMS params);
}
public struct DWMCOLORIZATIONPARAMS
{
public uint ColorizationColor,
ColorizationAfterglow,
ColorizationColorBalance,
ColorizationAfterglowBalance,
ColorizationBlurBalance,
ColorizationGlassReflectionIntensity,
ColorizationOpaqueBlend;
}
Lo he probado y funciona bien con Windows 8 y su función de colorización automática de ventanas. Como se sugirió en el enlace anterior, puede buscar en el registro los valores de color como una alternativa a un P / Invoke, pero no he probado ese método y, como he dicho, estos no están documentados y no se garantiza que sean estables.
Una vez que obtenga el color para dibujar sus pinceles de degradado, los pinceles no se actualizarán cuando cambie la combinación de colores de la ventana, ya sea manual o automáticamente por Windows. Afortunadamente, Windows transmite el mensaje de la ventana WM_DWMCOLORIZATIONCOLORCHANGED
cuando esto sucede, por lo que simplemente necesita escuchar ese mensaje y actualizar sus colores cada vez que se envía. Para ello, enganche en el procedimiento de la ventana ( WndProc()
).
El valor de WM_DWMCOLORIZATIONCOLORCHANGED
es 0x320
; querrás definir eso como una constante en algún lugar para que puedas usarlo en código.
Además, a diferencia de WinForms, las ventanas WPF no tienen un método WndProc()
virtual para anular, por lo que tiene que crear y enlazar una como delegado a sus identificadores de ventana asociados (HWND).
Tomando un ejemplo de código de estas respuestas mías:
- ¿Cómo puedo hacer que una ventana WPF se mueva arrastrando el marco de la ventana extendida?
- Detectar el cambio de tema del sistema en WPF
Tenemos:
const int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320;
private IntPtr hwnd;
private HwndSource hsource;
private void Window_SourceInitialized(object sender, EventArgs e)
{
if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
{
throw new InvalidOperationException("Could not get window handle.");
}
hsource = HwndSource.FromHwnd(hwnd);
hsource.AddHook(WndProc);
}
private static Color GetWindowColorizationColor(bool opaque)
{
var params = NativeMethods.DwmGetColorizationParameters();
return Color.FromArgb(
(byte)(opaque ? 255 : params.ColorizationColor >> 24),
(byte)(params.ColorizationColor >> 16),
(byte)(params.ColorizationColor >> 8),
(byte) params.ColorizationColor
);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_DWMCOLORIZATIONCOLORCHANGED:
/*
* Update gradient brushes with new color information from
* NativeMethods.DwmGetColorizationParams() or the registry.
*/
return IntPtr.Zero;
default:
return IntPtr.Zero;
}
}
Cuando Windows realiza la transición del cambio de color, WM_DWMCOLORIZATIONCOLORCHANGED
se distribuye en cada fotograma clave de la transición, por lo que recibirá numerosos mensajes en una breve ráfaga durante el cambio de color. Esto es normal; simplemente actualice sus pinceles de degradado como de costumbre y notará que cuando Windows haga la transición al esquema de color de la ventana, sus degradados se realizarán sin problemas junto con el resto de los marcos de las ventanas.
Recuerde que es posible que deba tener en cuenta las situaciones en las que el DWM no está disponible, como cuando se ejecuta en Windows XP, o cuando se ejecuta en Windows Vista o posterior con la composición del escritorio deshabilitada. También querrá asegurarse de no usar excesivamente esto, o puede incurrir en un impacto significativo en el rendimiento y ralentizar su aplicación.