Aero drop - shadow on a borderless form? - winforms

I tried the following code to override the CreateParams.
protected: virtual property System::Windows::Forms::CreateParams^ CreateParams
{
System::Windows::Forms::CreateParams^ get() override
{
System::Windows::Forms::CreateParams^ cp = Form::CreateParams;
cp->ClassStyle::set(CS_DROPSHADOW);
return cp;
}
}
It works fine. But it does not give the desired result.
This is the type of shadow I wanted...
And this is what I got from the code...
I was thinking if there is any way to get that aero style of Drop-Shadows ?

Related

Custom drawing background in Canvas

I want to create Program for drawing shapes.
Something like this (http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part-1).
To do this I consider use WPF and MVVM(PRISM).
My requirement is custom background drawing.
During implementation I met with some obstacles:)
View Code
public class DrawingAreaCanvas : Canvas, IDrawingAreaCanvas
{
.......
private IDrawingAreaModelView _modelView;
[Dependency]
public IDrawingAreaModelView ModelView
{
get { return _modelView; }
set
{
_modelView = value;
DataContext = _modelView;
}
}
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
base.OnRender(dc);
_modelView.OnRender(dc); // Pass drawing to modelview
}
}
Is this approach correct ?
Regards,
Leszek

override the super class methods in wpf Window

I wanna make a customized window base. So I made a custom window which inherits from Window.
For example:
public class MyWindowBase : Window
{
...
...
}
I wanna override the different Brushes of the super class Window for my own purpose.
In my previous experience, to override methods/properties with no abstract or virtual in the super class need the key word "new".
For example:
public new void DoSomething() { ........ base.DoSomething() ....... }
public new string SomeText { get { ... } set {......} }
It works in my previous work.
However, in this time of dealing with WPF Window, it doesn't work.
I tried to override the different Brushes of the super class Window as follows:
public new Brush BorderBrush
{
get { ... }
set { myBorderBrush = value; base.BorderBrush = null }
}
public new Brush Background
{
get { ... }
set { myBackground = value; base.Backgound = null; }
}
.....
.....
.....
I tried the change the value of the above Brushes in MyWindowBase, it just change the value of the super class Window, it doesn't change the value of myBorderBrush and myBackground.
So, how could I override the methods and properties of the super class Window?
Actually, I want to override the base background so that it will be null or transparent forever, but the changed value will be applied on my own custom Background.
Thank you very much!
If you only want to set the value, then you can set it using
this.BorderBrush = Brushes.Blue;
this.Background = Brushes.Red;
If you wish to overwrite the Property Metadata (for things like default value, property changed logic, or validation), you can use OverrideMetadata
Window.BackgroundProperty.OverrideMetadata(
typeof(MyWindowBase), myPropertyMetadata);
If you simply want to add some logic on Changed, you can use a DependencyPropertyDescriptor
var dpd = DependencyPropertyDescriptor.FromProperty(
Window.BackgroundProperty, typeof(Window));
dpd.AddValueChanged(this.Value, new EventHandler(BackgroundChanged));
private void BackgroundChanged(object sender, EventArgs e)
{
//do the code here
}
And if you're looking to override a Method, and not a Property, then you can use the override keyword
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
}

Render WPF control on top of WindowsFormsHost

I know that default WPF behavior is to render WPF controls and then on top render WinForms, but are there any way to render WPF on top of WindowsFormsHost?
Edit: I have found a temp hack as well. When wpf control overlaps WindowsFormsHost, I change the size of the WindowsFormsHost (This only works when you have rectangular object which overlaps, doesn't work for other shapes.)
Late to the party, I know, but I recently came across this issue using a WebBrowser control.
The final fix was to create a screenshot of the web browser whenever I hosted a modal dialog over the top. Since this was a little fiddly, I turned it into a Github project, hopefully this helps a little -
https://github.com/chris84948/AirspaceFixer
(It's on Nuget too, under AirspaceFixer)
Once you have the project all you need to do is this
xmlns:asf="clr-namespace:AirspaceFixer;assembly=AirspaceFixer"
<asf:AirspacePanel FixAirspace="{Binding FixAirspace}">
<WebBrowser x:Name="Browser" />
</asf:AirspacePanel>
Where FixAirspace is the dependency property that switches from the "real" view of the content, to the screenshot or "fake" view.
This "airspace" issue is suppose to be fixed in WPF vNext. There are a couple solutions out there, such as here, here, and here.
One way to do this is to host the WPF content in a transparent Popup or Window, which overlays the Interop content.
Try this on for size:
<hacks:AirspaceOverlay>
<hacks:AirspaceOverlay.OverlayChild>
<Canvas ToolTip = "A tooltip over a DirectX surface" Background="#01000000" Name="Overlay" />
</hacks:AirspaceOverlay.OverlayChild>
<controls:OpenGLControlWrappingWindowsFormsHost />
</hacks:AirspaceOverlay>
// Adapted from http://blogs.msdn.com/b/pantal/archive/2007/07/31/managed-directx-interop-with-wpf-part-2.aspx & http://www.4mghc.com/topics/69774/1/in-wpf-how-can-you-draw-a-line-over-a-windowsformshost
public class AirspaceOverlay : Decorator
{
private readonly Window _transparentInputWindow;
private Window _parentWindow;
public AirspaceOverlay()
{
_transparentInputWindow = CreateTransparentWindow();
_transparentInputWindow.PreviewMouseDown += TransparentInputWindow_PreviewMouseDown;
}
public object OverlayChild
{
get { return _transparentInputWindow.Content; }
set { _transparentInputWindow.Content = value; }
}
private static Window CreateTransparentWindow()
{
var transparentInputWindow = new Window();
//Make the window itself transparent, with no style.
transparentInputWindow.Background = Brushes.Transparent;
transparentInputWindow.AllowsTransparency = true;
transparentInputWindow.WindowStyle = WindowStyle.None;
//Hide from taskbar until it becomes a child
transparentInputWindow.ShowInTaskbar = false;
//HACK: This window and it's child controls should never have focus, as window styling of an invisible window
//will confuse user.
transparentInputWindow.Focusable = false;
return transparentInputWindow;
}
void TransparentInputWindow_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
_parentWindow.Focus();
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
UpdateOverlaySize();
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
if (_transparentInputWindow.Visibility != Visibility.Visible)
{
UpdateOverlaySize();
_transparentInputWindow.Show();
_parentWindow = GetParentWindow(this);
_transparentInputWindow.Owner = _parentWindow;
_parentWindow.LocationChanged += ParentWindow_LocationChanged;
_parentWindow.SizeChanged += ParentWindow_SizeChanged;
}
}
private static Window GetParentWindow(DependencyObject o)
{
var parent = VisualTreeHelper.GetParent(o);
if (parent != null)
return GetParentWindow(parent);
var fe = o as FrameworkElement;
if (fe is Window)
return fe as Window;
if (fe != null && fe.Parent != null)
return GetParentWindow(fe.Parent);
throw new ApplicationException("A window parent could not be found for " + o);
}
private void ParentWindow_LocationChanged(object sender, EventArgs e)
{
UpdateOverlaySize();
}
private void ParentWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateOverlaySize();
}
private void UpdateOverlaySize()
{
var hostTopLeft = PointToScreen(new Point(0, 0));
_transparentInputWindow.Left = hostTopLeft.X;
_transparentInputWindow.Top = hostTopLeft.Y;
_transparentInputWindow.Width = ActualWidth;
_transparentInputWindow.Height = ActualHeight;
}
}
Here's a link to the best answer I've seen on this subject so far:
Can I overlay a WPF window on top of another?
If anyone finds themselves unsatisfied with the hacks, setting the Visibility of the WindowsFormsHost to Collapsed or Hidden is always an option.
I came across this issue while trying to create a MDI style interface hosting WinForms controls while porting a win forms app to WPF.
I managed to solve it by doing something like this:
WindowsFormsHost -> ElementHost -> WindowsFormsHost -> my win forms controls.
Its super ugly, but it creates windows layers for the WPF content to be under the WinForms content.

Custom Winforms Controls (a button specifically)

I'm trying to create a custom button where the foreColor is always crimson and the backColor is always cyan. Ugly color scheme, but I'm just trying to get it so I can create large amounts of controls with a consistent color scheme without setting each control individually. Here's how I coded the button:
public partial class CustomButton : Button
{
private static Color _defaultForeColor = Color.Crimson;
private static Color _defaultBackColor = Color.Cyan;
public CustomButton()
{
InitializeComponent();
base.ForeColor = _defaultForeColor;
base.BackColor = _defaultBackColor;
}
public AutoScaleMode AutoScaleMode { get; set; }
[DefaultValue(typeof(Color), "Crimson")]
override public Color ForeColor
{
get { return base.ForeColor; }
set
{
base.ForeColor = _defaultForeColor;
}
}
[DefaultValue(typeof(Color), "Cyan")]
public override Color BackColor
{
get { return base.BackColor; }
set
{
base.BackColor = _defaultBackColor;
}
}
}
When I drop the custom button onto my form, the background is the regular button color and the text is crimson. If I run the app it's the same also. Now if I try to modify the forecolor or backcolor in the properties window they go right back to their defaults that I set (crimson, cyan) and then they also show up that way when I run my app. How do I get the controls to show up correctly in the designer and at run time?
The problem exists because UseVisualStyleBackColor is automatically set to true and you can't override it. If you change it to false, you'll notice that your button will work correctly.
One option is to override OnControlAdded of the button like this:
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
UseVisualStyleBackColor = false;
}
First time in the designer, the color won't show, but when you run the application it will work correctly.
I suggest you bind fore and back colors to, for example, application settings (Or settings class specific to your controls). Standard button and bind in designer, or use your own descendant and bind in code. In this case you will have consistent color scheme, and, more important, you can change it without recompilation.
public class CustomButton : Button
{
public CustomButton
{
InitializeComponent();
if (!DesignMode)
{
DataBindings.Add(new Binding("ForeColor", Settings.Default, "ButtonForeColor", true, DataSourceUpdateMode.Never));
DataBindings.Add(new Binding("BackColor", Settings.Default, "ButtonBackColor", true, DataSourceUpdateMode.Never));
}
}
// ...

How to make an ownerdraw Trackbar in WinForms

I'm trying to make a trackbar with a custom graphic for the slider thumb. I have started out with the following code:
namespace testapp
{
partial class MyTrackBar : System.Windows.Forms.TrackBar
{
public MyTrackBar()
{
InitializeComponent();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// base.OnPaint(e);
e.Graphics.FillRectangle(System.Drawing.Brushes.DarkSalmon, ClientRectangle);
}
}
}
But it never calls OnPaint. Anyone else come across this? I have used this technique before to create an ownerdraw button but for some reason it doesn't work with TrackBar.
PS. Yes, I have seen question #625728 but the solution there was to completely re-implement the control from scratch. I just want to modify the existing control a little.
If you want to paint over the top of the trackbar you can capture the WM_PAINT message manually, this means you dont have to re-write all the painting code yourself and can simply paint it, like this:
using System.Drawing;
using System.Windows.Forms;
namespace TrackBarTest
{
public class CustomPaintTrackBar : TrackBar
{
public event PaintEventHandler PaintOver;
public CustomPaintTrackBar()
: base()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// WM_PAINT
if (m.Msg == 0x0F)
{
using(Graphics lgGraphics = Graphics.FromHwndInternal(m.HWnd))
OnPaintOver(new PaintEventArgs(lgGraphics, this.ClientRectangle));
}
}
protected virtual void OnPaintOver(PaintEventArgs e)
{
if (PaintOver != null)
PaintOver(this, e);
// Paint over code here
}
}
}
I've solved it by setting the UserPaint style in the constructor like so:
public MyTrackBar()
{
InitializeComponent();
SetStyle(ControlStyles.UserPaint, true);
}
OnPaint now gets called.
In this answer PaintOver is never called, because it is never assigned, its value is null.

Resources