My application is setting the Requested theme in the App.xaml as we only want to show a light theme regardless of what the user's system theme is.
Problem is, when the user is on a dark theme (which has white icons for signal/battery/time etc) the app switches all style resources to use light theme but does nothing about the header bar. This creates the situation where you have a white page background and white icons on top of it.
Is there a way to change the theme applied to this top bar?
I tried adding a dark colour behind the bar (30px high rectangle with margin -30 on top) but the behaviour happens on light theme too so then if the user is on light theme, the icons are black and too dark to see on the colour background.
It's not obvious in the picture, but on top of that map there is the header bar with icons but the icons are white and the theme says page background is white.
Turns out the correct answer is:
http://msdn.microsoft.com/library/windows/apps/windows.ui.viewmanagement.statusbar(v=win.10).aspx
This class also cannot be used from the XAML so you have to do:
public MainPage()
{
StatusBar statusBar = StatusBar.GetForCurrentView();
statusBar.ForegroundColor = new Windows.UI.Color() { A = 0xFF, R = 0xFF, G = 0x00, B = 0xAA };
this.InitializeComponent();
}
Related
I'm currently creating a Xamarin.Forms app. One of my pages uses SkiaSharp to allow users to highlight parts of an image in a text marker style (i.e. a yellow brush with low opacity).
This is how the related SKPaint object is defined:
var strokePaint = new SKPaint()
{
Color = Color.FromRgba(255, 255, 0, 100).ToSKColor(),
Style = SKPaintStyle.Stroke,
StrokeWidth = StrokeWidth
};
That's working fine so far, but what bothers me is that the opacity "increases" when I have multiple overlapping paths, until at some point the underlying picture isn't visible anymore.
What could I do to avoid this overlapping? I was thinking about merging all paths into one, but that doesn't seem to work because the user is allowed to change StrokeWidth in between strokes and I didn't see any way of drawing paths with varying width.
I hope any of you guys has some help for me. Any idea is appreciated!
I'm not super familiar with Skia, but I took a look at the documentation for SKPaint, and it looks like it has a BlendMode property. Based on how similar things work in other systems, that should control how colors are combined. You might have to try different values to get the effect you are looking for. Dst, or Modulate look like good candidates. – Bradley Uffner
Thanks for your answer Bradley! I went with the Darken blend mode and set opacity to 255, which creates a very nice effect when highlighting text (only the darker color is visible, so dark text on a light background becomes dark text on a background of my marker color).
I am using user input images as the Frame Background in my app and I want to darken the image. Reducing opacity does the opposite and brightens the image as the Window color is white on Desktop and not black and I can't see any function to change the color of window.
Changing TitleBar Color doesn't work.
Changing the RequestedTheme from Light to Dark doesn't change the color.
Processing the image to darken is too slow and can't be used.
Here's the code to change the Frame background where 'image' is my BitmapImage object.
ImageBrush b = new ImageBrush();
b.ImageSource = image;
b.Stretch = Stretch.UniformToFill;
(Window.Current.Content as Frame).Background = b;
I need to use the Background on Frame and not on Page as navigation to other pages needs to be smooth and keep the background in place.
I have a Windows 10 UWP app running on mobile. When I run the app in an emulator, everything works fine. When I run it on a device (Lumia 550), the StatusBar is black with black font and the status indicators are not visible.
Is this some kind of bug?
I know I can force the StatusBar to have white background and black color, but the requirement for the app is to stick with the theme (black StatusBar in dark theme, white in Light theme).
If I create a new empty Windows 10 app and run it on a device, the problem is the same, it is not specific to my app.
Edit
Here's a more proper answer:
In Windows 10 Mobile the statusbar inherits it's background color from the topmost page. The foreground color is inherited from RequestedTheme.
This means that if you set the background color of your page to black and your RequestedTheme to Light (which gives a white foreground color), the text will be black on black.
Original post
Have you read this?: https://stenobot.wordpress.com/2015/07/08/uwp-app-development-styling-the-mobile-status-bar/
It might help you.
I have struggled with this a bit.
A strange thing is that when I start my app, the theme (Application.RequestedTheme) is always Light, ignoring the setting on the phone. Even when I try to set it to Dark in the constructor, it immediately reverts to Light. This could explain the black foreground color.
I also experience the inconsistency between simulator and device. To take care of that, I (as suggested in other answer) set the background color of the page (not the root Grid):
<Page
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
... >
</Page>
With this, the status bar at least appear readable.
If you got the black font on the black background with your Light theme project, simple add this line into OnLaunched method in App.xaml.cs:
rootFrame.Background = new SolidColorBrush(Colors.White);
Just add RequestedTheme="Dark"in App.xaml
In your reference Manager add Windows Mobile extensions for the UWP
Then in App.XAML.cs on
protected override void OnLaunched(LaunchActivatedEventArgs e)
add
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
statusBar.BackgroundColor = Windows.UI.Colors.Green;
statusBar.BackgroundOpacity = 1;
statusBar.ForegroundColor = Colors.White;
}
If you want to change Title bar on PC version of UWP app, then you could use this
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.ApplicationView"))
{
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
if (titleBar != null)
{
titleBar.ButtonBackgroundColor = Colors.DarkBlue;
titleBar.ButtonForegroundColor = Colors.White;
titleBar.BackgroundColor = Colors.Blue;
titleBar.ForegroundColor = Colors.White;
}
}
How do I set the color of my labels in a custom form region I developed for Outlook 2010 to match the user selected theme color? Please see picture below about the demonstration of what I'm trying to do.
I'm trying to match my custom form label forecolor to whatever the selected theme forecolor is of the Outlook instance.
From what I can tell (and I may be wrong) Outlook gets its theme from Windows (unless you are meaning email or stationary theme. I would try that route.
Update: Looking around some more I see if you go into an email and then Office Button -> Editor Options -> Theme you can choose between 3 default themes (blue, black and silver) but the only thing I can see that updates in the registry is the key at:
HKCU\Software\Microsoft\Office\12.0\Common\Theme
I'm using Office 2007. The bad part is that it is just plugging in a hex number that appears to correspond to the theme but I don't see where one can find the mappings for this.
Expanding on Mike's post,
this registry entry
HKCU\Software\Microsoft\Office\12.0\Common\Theme
There are only three options.
Values of 1 and 2 are black with a value of 3 is white for foreground.
Silver theme and Blue theme use black foreground.
Black theme uses white and black theme is a value of 3
I finally solved the problem by implementing the Paint event at the formregion level.
private void FormRegion1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
if (controlX.BackColor.ToArgb() == System.Drawing.Color.FromArgb(255, 0, 0, 0).ToArgb())
{
controlX.ForeColor = System.Drawing.Color.White;
}
else if (controlX.BackColor.ToArgb() == System.Drawing.Color.FromArgb(255, 255, 255, 255).ToArgb())
{
controlX.ForeColor = System.Drawing.Color.DarkGray;
}
}
I beleive if you access the SetForeColor property of your label or what have you, you can do the following:
label1.SetForeColor(SystemColors.Highlight);
http://msdn.microsoft.com/en-us/library/system.drawing.systemcolors.aspx
also see:
SystemColors.ActiveBorder
SystemColors.ActiveCaption
SystemColors.ActiveTextCaption
Using the DwmExtendFrameIntoClientArea API call with Aero Glass enabled works just fine. However, I want it to work when Aero Glass is disabled as well, like how it works in the Windows control panel:
Notice how the frame has extended into the client area, even though Aero Glass is disabled? When I make the DwmExtendFrameIntoClientArea API call in my application, the returned HRESULT is definitely not success, and my application ends up looking like this:
http://img197.imageshack.us/img197/9629/clientapplication.png
Normally, with Aero Glass enabled, the border stretches down to underneath the navigation buttons, like in the control panel. How do I do this? DwmExtendFrameIntoClientArea clearly isn't working.
By the way, if it is relevant, my application is a WPF application.
Nir's answer is correct; when composition is disabled you have to draw that area yourself.
i can show you the code i have in the paint handler of the panel at the top of my form - the panel normally responsible for drawing the 0x00000000 transparent black to make the glass appear:
Psuedo-code:
procedure DrawGlassHeaderArea(g: Graphics; r: Rectangle; IsFormFocused: Boolean);
const
clFakeGlassColor = $00EAD1B9; //(185, 209, 234) This is the fake foreground glass color (for use when composition is disabled)
clFakeGlassColorUnfocused = $00F2E4D7; //(215, 228, 242) This is the fake background glass color (for use when composition is disabled)
begin
if Dwm.IsCompositionEnabled then
begin
g.FillRectangle(r, 0x00000000); //fill rectangle with transparent black
end
else
//Composition disabled; fake it like Microsoft does
//The color to use depends if the form has focused or not
Color glassColor;
if (IsFormFocused) then
c = clFakeGlassColor
else
c = clFakeGlassColorUnfocused;
g.FillRectangle(r, glassColor); //fill rectangle with fake color
//Now we have to draw the two accent lines along the bottom
Color edgeHighlight = ColorBlend(Colors.White, glassColor, 0.33); //mix 33% of glass color to white
Color edgeShadow = ColorBlend(Colors.Black, glassColor, 0.33); //mix 33% of glass color to black
//Draw highlight as 2nd-last row:
g.DrawLine(edgeHighlight, Point(r.Left, r.Bottom-2), Point(r.Right, r.Bottom-2);
//Draw shadow on the very last row:
g.DrawLine(edgeHighlight, Point(r.Left, r.Bottom-1), Point(r.Right, r.Bottom-1);
end;
end;
Sample usage
procedure MyForm.PaintBox1Paint(PaintEventArgs e)
begin
DrawGlassHeaderArea(e.Graphics, PaintBox1.ClientRectangle, this.HasFocus);
end;
Bonus Screenshot
Update 7/9/2014
#JakePetroules was right, and i was wrong. The "blue" used for fake glass is not hard-coded into Windows. And it is accessible using GetThemeColor.
I coded up all the available colors (TMT_COLOR) available for a Window class:
Note: For more information about Classes, Parts, and States, see Aero Style Classes, Parts, and States
When using:
Class: Window
Part: WP_CAPTION
State: n/a (StateID is not used for the Caption part, nor the entire Window class)
and fetch the color code propertyID:
TMT_FILLCOLORHINT: for when the window has focus
TMT_BORDERCOLORHINT: for when the window does not have focus
you get the two important colors:
The pseudo-code i now use to get the fake glass color:
public Color GetFakeClassColor(Boolean isWindowFocused=true)
{
static Color fakeGlass= 0x00B8D0E9; //the correct answer anyway
if ((GetThemeAppProperties() && STAP_ALLOW_CONTROLS) == 0)
return fakeGlass;
hTheme = OpenThemeData(GetDesktopWindow(), "Window");
if (hTheme = 0)
return fakeGlass;
Int32 propID;
if (isWindowFocused)
propID= TMT_FILLCOLORHINT; //The color used as a fill color hint for custom controls.
else
propID= TMT_BORDERCOLORHINT; //The color used as a border color hint for custom controls.
DWORD rgb;
if (Failed(GetThemeColor(hTheme, WP_CAPTION, 0, propID, ref rgb))
return fakeGlass;
Result = new Color(rgb);
}
In reality, since i use Delphi, my actual code is:
function GetFakeGlassColor(IsWindowFocused: Boolean=True): TColor;
var
ted: TThemedElement;
hTheme: THandle;
propID: Integer;
rgb: DWORD;
begin
Result := $00B8D0E9; //the correct answer anyway
//We can't use the ThemeServcies.ThemesEnabled, as that mistakenly checks for version 6 of the common controls library
//Themes can be enabled without using ComCtl V6, or common controls at all
if not ThemeServices.ThemesAvailable then
Exit;
if (GetThemeAppProperties and STAP_ALLOW_CONTROLS) = 0 then
Exit;
htheme := ThemeServices.Theme[teWindow];
if hTheme = 0 then
Exit;
if IsWindowFocused then
propID := TMT_FILLCOLORHINT //The color used as a fill color hint for custom controls.
else
propID := TMT_BORDERCOLORHINT; //The color used as a border color hint for custom controls.
if Failed(GetThemeColor(hTheme, WP_CAPTION, 0, propID, {var}rgb)) then
Exit;
Result := rgb;
end;
You have to paint it to be frame-like yourself.
You have to use DwmIsCompositionEnabled to check if the DWM is enabled and handle WM_DWMCOMPOSITIONCHANGED to detect DWM state changed.
Then you have to have to separate way of drawing the window, if DWM is enabled you use DwmExtendFrameIntoClientArea, if it's disabled you draw the "frame" yourself.
I have no idea how to duplicate the Aero frame in WPF (in my app I have my own color scheme and I'm not using the Auro frame).
This is annoying but when the DWM is disabled the system falls back to XP-style drawing and none of the DWM's services work - even those that aren't related to the glass effect.
You need to paint the window background yourself. You should not actually hard-code the colors as previous posts have suggested, but use the theme functions to retrieve them, like so (semi-pseudocode):
DWORD rgb;
HANDLE hTheme = OpenThemeData(GetDesktopWindow(), L"WINDOW");
GetThemeColor(hTheme, WP_CAPTION, CS_ACTIVE,
<is active window> ? TMT_FILLCOLORHINT : TMT_BORDERCOLORHINT, &rgb);
// Can use these functions to retrieve the individual RGB values
BYTE r = GetRValue(rgb);
BYTE g = GetGValue(rgb);
BYTE b = GetBValue(rgb);
These colors will remain correct even if the user changes title bar colors in the control panel (unlike using COLOR_ACTIVECAPTION / COLOR_GRADIENTACTIVECAPTION). You should also check that themes are active using IsThemeActive() before attempting to get theme colors.
The values of the constants for quick reference:
WP_CAPTION: 1
CS_ACTIVE: 1
TMT_FILLCOLORHINT: 3821
TMT_BORDERCOLORHINT: 3822