When dragging a window around if it went to a specific area via DragMove i wanted to show a semi-transparent window overlay in that region.
Showing the window worked fine, but it would always come up on top of the window i was dragging.
I tried various things such as .focus/.activate after i show the overlay, but they didn't work.
Each window had WindowStyle="None" Topmost="True" ShowInTaskbar="False" and the overlay window even had IsHitTestVisible="False" Focusable="False". Though, the overlay would still get focus when it's visibility was toggled on.
The only thing i found to work was to hide my main window and then show it again. Though, i didn't want it to flicker, so i disabled the dispatcher while i was doing it. This ended up working beautifully. I couldn't find any similar issues online so i figured i'd post this to help the next person.
private void showOverlay()
{
//show the docking window
_overlayWindow.Visibility = Visibility.Visible;
//problem here will be that the overlay window will be on top of main
//this.focus this.activate +other efforts did not work to bring main back on top
//only thing i could find that would bring the main win on top is to hide/show it again.
//i wrap this hide/show in a disabled dispatcher block so that the window never really gets hidden on screen
using (var d = Dispatcher.DisableProcessing())
{
this.Visibility = Visibility.Hidden;
this.Visibility = Visibility.Visible;
}
}
Related
I have a panel and on that I've a picturebox. There are around 20 labels that I've to show in the panel. I want the background of Label to be transparent ie the image in picturebox is shown and the label displays only the text.
Now since labels do not exhibit true transparency I made the labels child of picturebox
this.lbl1.Parent = pictureBox1;
This has solved my immediate problem but now when the form loads, all the labels take a while to become visible and do so one at a time. I'd appreciate if you guys can give some solution for this.
Thanks in advance
The standard cure for flicker is double-buffering. But that cannot solve this kind of flicker. It is a different kind, caused by having multiple windows overlapping each other. Each label is its own window. When the form needs to paint itself, it draws its background leaving holes for the child windows. Each child window then takes a turn drawing itself. And their child windows draw themselves next. Etcetera.
This becomes noticeable when one control takes a while to draw, no doubt your picture box. Especially when it displays a large image that needs to be resized. The holes for the child windows stay unpainted while the picture box draws. They have a white background, black when you use the form's TransparencyKey or Opacity property. This can contrast badly with the image in your picture box, that effect is perceived by the user as flicker.
One immediate cure is to not use controls so you don't pay for their window. A Label is very convenient but it is a massive waste of system resources to burn up a window just to display a string. You can simply implement the picture box' Paint event and draw the strings with TextRenderer.DrawText(). PictureBox has double-buffering turned on by default so the image as well as the text is drawn completely smoothly, no more flicker. The obvious disadvantage is that you lose the convenience of point-and-click, you have to write code.
There are other fixes possible. One of them is to prevent the picture box from leaving holes for the child windows. It will draw the entire image, the labels pop on top of them. That's still flicker but not nearly as noticeable. Add a new class to your project and paste this code:
using System;
using System.Windows.Forms;
internal class MyPictureBox : PictureBox {
protected override CreateParams CreateParams {
get {
var parms = base.CreateParams;
parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN
return parms;
}
}
}
Compile and drop the new picture box control from the top of the toolbox onto your form.
Yet another possible workaround is to make the form and all of its children double-buffered. This doesn't speed up the painting at all but all of the windows get rendered into a memory buffer, the result is blitted to the screen. You'll notice a delay but the window suddenly pops on the screen. This is called compositing. Winforms doesn't support this directly since it can have side-effects but it is easy to enable. Paste this code into your form class:
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
Supported by XP and later. Watch out for painting artifacts.
or you can ditch the labels and draw the text yourself:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
TextRenderer.DrawText(e.Graphics, "Label1", SystemFonts.DefaultFont,
new Point(10, 10), Color.Black, Color.Empty);
}
The label does not support transparency, you must create your own unique custom control, you can see these code examples.
http://www.codeproject.com/KB/dotnet/transparent_controls_net.aspx http://www.codeproject.com/KB/vb/uLabelX.aspx
Bye
I have a minimized WPF window. I click the item in the taskbar to maximize. It makes a little audio ding, then I try again, and again. Usually about the third try it will maximize. What could cause it to refuse my initial maximize attempt?
One possibility is that you have some code that's changing the value of the ResizeMode property to NoResize.
See this page for more: http://msdn.microsoft.com/en-us/library/ms748948.aspx
Second, you might be overriding OnStateChanged and not calling base.OnStateChanged() consistently.
Third, you may have something hogging the UI's thread during your first attempts. Once that task--whatever it is--stops blocking then WPF can repaint the window in restored/maximized state.
I had a similar problem when trying to manually maximize a custom window.
The solution was to put the next code in my maximize button...
this.SizeToContent = System.Windows.SizeToContent.Manual;
this.MaxWidth = double.PositiveInfinity;
this.MaxHeight = double.PositiveInfinity;
this.Width = double.NaN;
this.Height = double.NaN;
this.WindowState = WindowState.Maximized;
Where 'this' referes to the Window.
I have a ChildWindow which contains a ExpressionMediaPlayer inside it. When I click on the ChildWindow Media Player Full screen button it swiches the whole application to FullScreen Mode.
Is there a way to avoid it. I am not quite sure if this scenario is going to fall under SL security restrictions.
When I drag the ChildWindow(the position of ChildWindow changes) and click on the fullscreen
now the ChildWindow also changes it's position.
For example if I have dragged the ChildWindow 50px from Top and pressed the Full Screen button of of mediaPlayer (it contains) the Child Window also appears 50 pixels below the Screen Top.
But I want My ChildWindow to be FullScreen without having any Gap from LEFT,TOP,RIGHT or below.
Any help will be greatly appreciated.
Thanks,
Subhen
Silverlight only uses one of its two windows. The first is the normal window embedded in the Host application such as IE (or in windowless mode it co-operates with the host to draw directly on one of the host's windows in a give rectangle). The other window is a Fullscreen one.
When in full screen mode it moves all its rendering of its stack of content to the full screen window. You can't get Silverlight to render only some controls on the Fullscreen window, its an all or nothing proposition.
Creating a "fullscreenable" ChildWindow would be an interesting exercise. Probably a new templated control based on Childwindow with a new "Fullscreen" visual state (in a new state group) that hides the chrome and causes the content grid to stretch with Auto Width and Height.
I want to achieve the same effect as Windows Media Player or Browser based Flash players which take up the ENTIRE (not even the taskbar is visible) real estate when maximized.
This works fine if the WindowState is set to Maximized and the WindowStyle is set to None in XAML so the app is started in that state. Problem is I want to start the app in a bordered window and when the user chooses, maximize as specified above. In the StateChanged handler I check for Maximized state and if this is the case I set the WindowStyle to None. This has the effect of maximizing the window but NOT covering the taskbar. The following code will make this work as I want but its a hack and I'd like to clean it up:
if (WindowState == WindowState.Maximized)
{
m_videoWindow.Maximize();
WindowStyle = WindowStyle.None;
//the following makes this work but I would like to clean it up
Hide();
Show();
}
EDIT This (from 2006 when still in CTP) mentions the problem and someone from MS states they hope to improve full screen support in the next version, have these improvements been made?
This article explains it all: Maximizing window (with WindowStyle=None) considering Taskbar.
Also worth checking out: Custom Window Chrome in WPF.
Edit: Now new, is the WPF Shell Integration Library that allows complete restyle of the window chrome without the headaches of reimplementing move, resizing, etc.
Edit 2015: Shell Integration Library is now integrated in WPF and MS retired the code
I found I could maximize to full screen (covering the taskbar) by setting the properties when creating the window (in xaml), but was not able to switch back and forth after creation. After some experimenting, I found the order the properties are set seems to matter:
public bool IsFullscreen
{
get
{
return WindowState == System.Windows.WindowState.Maximized
&& ResizeMode == System.Windows.ResizeMode.NoResize
&& WindowStyle== System.Windows.WindowStyle.None;
}
set
{
if ( value )
{
ResizeMode = System.Windows.ResizeMode.NoResize;
WindowStyle = System.Windows.WindowStyle.None;
WindowState = System.Windows.WindowState.Maximized;
}
else
{
ResizeMode = System.Windows.ResizeMode.CanResize;
WindowStyle = System.Windows.WindowStyle.SingleBorderWindow;
WindowState = System.Windows.WindowState.Normal;
}
}
}
Note that WindowState comes last in the setter.
To get this to properly work in my WPF/.NET 4.0 application I am calling this function whenever I enter or exit full screen mode:
private static void RefreshWindowVisibility(Window window)
{
if (window.OriginalWindowState == WindowState.Maximized)
{
window.Hide();
window.Show();
window.BringIntoView();
}
}
There is a flicker associated with this method, but it seems the same flicker exists when going to full screen mode on Chrome. Internet Explorer seems to take a different approach.
I don't know if this is ok for you, but you can resize the window to have the same size than the working area (that is, in most cases, all the screen except the taskbar) and locate it at 0,0 (top-left corner):
Width = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
Left = 0;
Top = 0;
The exact definition for the WorkingArea property (from MSDN) is:
Gets the working area of the display. The working area is the desktop area of the display, excluding taskbars, docked windows, and docked tool bars.
Hope it helps
I need a listbox with IPhone-like functionality for Silverlight. That is, animated scrolling, and click and drag to scroll. Scrolling will continue a bit after the mouse up event based on the "speed" of the dragging. I've search and found no control vendors providing this. So question is how should I build it? I need some hints to get started.
There's two parts to this question:
Part 1, How to get the animated scrolling of the listbox.
Part 2, How to build a "draggable" scrolling, I guess I should put a canvas on top and track the mouseevent, and simulate some physics. Some hints here would have been great.
Thanks Larsi.
A while ago I made a control that did something like this. All I did was put a stackpanel inside a canvas. Just adjust the canvas.top of the entire stackpanel on a mousemove (while mouse is pressed). To animate the scrolling after a mouseup, you really just need to track the amount moved and apply an animation to the canvas.top property.
Here's a really nice complete sample for WPF that does both drag scrolling and automatic flick/inertia scrolling. I'm not sure what if anything would need to be changed to make it work in Silverlight.
http://sachabarbs.wordpress.com/2009/12/24/friction-scrolling-now-an-wpf-attached-behaviour-too/
Just a note that as-is you can't click and drag the view if you click on a child (e.g. buttons) that capture the mouse input. I actually ended up modifying this sample so you could still drag scroll when you click on children, while still allowing children to accept mouse input when not drag scrolling.
This will be easier in Silverlight 3 than Silverlight 2, but not impossible in 2.
This video from MIX 09, Building Microsoft Silverlight Controls, should help you.
Another post from Sacha Barber's website:
http://sachabarber.net/?p=481
Jeremiah Morrill shares code that implements animated scrolling with inertia in a custom ContentControl (templated with an included ScrollViewer)
<ScrollViewer x:Name="sv1" Width="500" Height="285">
<StackPanel x:Name="sp1" Width="450" Height="285">
</StackPanel>
</ScrollViewer>
By setting pos. and neg. margins to the stackpanel inside the scrollviewer
you can create a scroll effect.
onScroll_Up()
{
//Change this based on your scrollviewer dimension
if (this.sv1.ScrollableHeight < 300)
{
Thickness thickness = this.sp1.Margin;
thickness.Top += 50;
this.sv1.SetValue(StackPanel.MarginProperty, thickness);
}
}
onScroll_Down()
{
if (this.sv1.ScrollableHeight > 1)
{
Thickness thickness = this.sp1.Margin;
thickness.Top += -50;
this.sv1.SetValue(StackPanel.MarginProperty, thickness);
}
}