Making the panel transparent? [duplicate] - winforms

This question already has answers here:
Translucent circular Control with text
(1 answer)
How to make two transparent layer with c#?
(1 answer)
Closed 23 days ago.
I'm creating a simple form with WinForms with dotNET7 using VS2022:
The gray rectangle is a Panel, which I need to make transparent. You can see a label underneath the panel, and I wish it to be visible, while the panel itself is brought to front.
With dotNET framework, it was so easy:
public class TransparentPanel : Panel
{
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//base.OnPaintBackground(e);
}
}
However, with dotNET7 and VS2022 (don't really know which one causes the limitation), when I change the Panel to "TransparentPanel", designer simply gets rid of it:
With original panel, these are my components:
After changing panel1 from System.Windows.Forms.Panel to TransparentPanel:
I tried changing panel's background to transparent, but it's not the giving me my required results:
this.panel1.BackColor = System.Drawing.Color.Transparent;
Also tried to apply color with alpha:
this.panel1.BackColor = Color.FromArgb(100, Color.Red);
So how can I achieve this very simple thing with dotNET7?

Related

windows forms application - how to make the tabs in a tab control get full width?

So i'am working with tabControl in windows forms application and i want to make the tabs get full width regardless whether the application window is maximized or not.
When the window isn't maximized everything appears great:
But when the window gets maximized the tabs doesn't get the full width:
Is there any known way to fix this problem?
Thanks in advance
You can achieve this in some way by modifying the ItemSize property as described bellow, else you'd have to draw the tab page selectors yourself.
public Form1()
{
InitializeComponent();
tabControl1.SizeMode = TabSizeMode.Fixed;
tabControl1.ItemSize = new Size((tabControl1.Width / tabControl1.TabPages.Count) - 1, tabControl1.ItemSize.Height);
}
//Hook to form or parent container Resize event, either Resize or ResizeEnd.
private void Form1_ResizeEnd(object sender, EventArgs e)
{
tabControl1.ItemSize = new Size((tabControl1.Width / tabControl1.TabPages.Count) - 1, tabControl1.ItemSize.Height);
}

Button hover effect and touch (WPF)

I have WPF desktop application with a Button. When I run it on normal PC and go with mouse cursor over the button, it becomes blue (default Windows theme). When I move cursor out, button is gray again. Pretty normal behavior.
But when I run it on Windows 8 tablet, following is happening: I touch the Button, it becomes blue. Then I move up my finger, but button stays blue. There is no MouseLeave event. I see blue button until I click somewhere else on the screen.
Is there any workaround how to prevent this? I know I can remove the whole hover effect, but I don't want to do that unless there is another way.
check whether following (http://blakenui.codeplex.com/) will help you to handle the issue
WPF: Is there a possibility to "route" ordinary mouse events to touch events in Windows 7
I was able to fix that by using following behavior which uses visual states:
public class TouchDeviceMouseOverUIElementFixBehavior : Behavior<UIElement>
{
protected override void OnAttached()
{
AssociatedObject.StylusUp += AssociatedObject_StylusUp;
}
protected override void OnDetaching()
{
AssociatedObject.StylusUp -= AssociatedObject_StylusUp;
}
private void AssociatedObject_StylusUp(object sender, StylusEventArgs e)
{
var control = sender as FrameworkElement;
if (control != null)
{
if (!VisualStateManager.GoToElementState(control, "Normal", true))
{
VisualStateManager.GoToState(control, "Normal", true);
}
}
}
}
You can do this by removing default mouse hover option in WPF. It worked perfectly fine for me.
Here is the source i found the answer

How to prevent a ScrollViewer from handling MouseMove event of a descendant? (Silverlight for Windows Phone)

Consider this:
<ScrollViewer>
<!-- Several Controls /-->
<MyControl MouseMove="myMouseMoveHandler" />
<!-- Several Controls /-->
</ScrollViewer>
MyControl is a HSV color selection control with the color spectrum on a circle which can rotate, and the nuances of the selected hue on a triangle. It looks awesome, but sadly I cannot post a picture yet (rep). It really needs to be able to handle mouse movement in all directions on its surface.
Now when I move the mouse on MyControl (and it correctly handles the movement), the ScrollViewer still scrolls!
This happens even when it is the only control in the ScrollViewer, the movement starts and ends inside my control, and/or I set e.Handled = true in both the MouseLeftButtonDown / -Up events. Using CaptureMouse() in ..Down and ReleaseMouseCapture() in ..Up doesn't help either.
You will agree that I cannot change the ScrollViewer implementation (or can I?), and I cannot guarantee that my control is never hosted inside a ScrollViewer (eg. because I want to publish it).
It must be possible to prevent the ScrollViewer from getting the MouseMove. Proof: simply replace MyControl with a ListBox containing more items than fit into its Height, and you can swipe through the ListBox items without the ScrollViewer reacting.
But how? Is it also a ScrollViewer inside the ListBox and that's why it works there, or can it be done for my control too?
Alright, I found a solution that works nicely.
My thoughts were so fixed to e.Handled (unavailable in MouseMove), IsHitTestVisible (hides all children from touch events as well) and sorts of stuff, I didn't see the obvious.
Here is the code in case somebody has the same question:
struct ScrollVisibilities
{
public ScrollBarVisibility Horizontal;
public ScrollBarVisibility Vertical;
}
Dictionary<ScrollViewer, ScrollVisibilities> scrollersStates = new Dictionary<ScrollViewer, ScrollVisibilities>();
bool scrollersDisabled;
void disableScrollViewers(bool disable)
{
if (scrollersDisabled == disable) // can't disable if disabled or enable if enabled
return;
scrollersDisabled = disable;
if (disable)
{
DependencyObject dpo = Parent;
while (dpo is FrameworkElement)
{
if (dpo is ScrollViewer)
{
ScrollViewer s = dpo as ScrollViewer;
ScrollVisibilities v = new ScrollVisibilities()
{
Horizontal = s.HorizontalScrollBarVisibility,
Vertical = s.VerticalScrollBarVisibility
};
scrollersStates.Add(s, v);
s.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
s.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
}
dpo = ((FrameworkElement)dpo).Parent;
}
}
else // restore
{
foreach (ScrollViewer s in scrollersStates.Keys)
{
s.HorizontalScrollBarVisibility = scrollersStates[s].Horizontal;
s.VerticalScrollBarVisibility = scrollersStates[s].Vertical;
}
scrollersStates.Clear();
}
}
In MouseLeftButtonDown, I disableScrollViewers(true), and hook into Touch.FrameReported.
In Touch_FrameReported, I disableScrollViewers(false) when all touch points have Action == Up. That way, I get the Up event even when it happens outsided MyControl.
There are limitations to this approach, as disabling the ScrollViewers will cause them to jump to their (and their childrens) unscrolled state. So I put MyControl on the top and set all the alignments accordingly.

Wpf Adorner not responding to interactions

I'm trying to create an overlay in wpf (with darkening background), similar to the ones you can find on the web to popup images.
I would like it to be reusable in more than 1 part of the application, with diffent types of content.
this is the temporary code of the constructor of the adorner class (just to try)
private readonly Grid _grid = new Grid();
public DarkOverlayAdorner(UIElement adornedElement, Object content) :
base(adornedElement)
{
_grid.Background = new SolidColorBrush(Color.FromArgb(99, 0, 0, 0));
IsHitTestVisible = true;
var visual = content as UIElement;
if (visual != null)
_grid.Children.Add(visual);
}
In addition in the class (of course), I have the ovverrides of MeasureOverride and ArrangeOverride to give the adorner the correct size of the adorned element, GetVisualChild, and VisualChildCount...
The problem here is that the adorner is correctly shown, but no events or behaviour are applied on the adorned element. For example:
AdornerLayer layer = AdornerLayer.GetAdornerLayer(textBoxProva);
layer.Add(new DarkOverlayAdorner(textBoxProva, new Button{Content = "prova"}));
The button here is shown, but I can-t click the button and no effects on button mouseover are applied.
I still can't figure out the problem.
Ok, I've lost a lot of time trying to figure out what was the problem.
In the end I found the solution:
If you want the element added to react to events, I think that the element must be bound to the visual tree of the adorner.
The way to do it is to use a VisualCollection, intitialized to the adorner itself:
VisualCollection visualChildren;
FrameworkElement #object;
public DarkOverlayAdorner(UIElement adornedElement) :
base(adornedElement)
{
visualChildren = new VisualCollection(this);
#object = new Button {Content = "prova"};
visualChildren.Add(#object);
}
protected override Visual GetVisualChild(int index)
{
return visualChildren[index];
}
This way the events are correctly routed.
You might want to take a look at the ChildWindow control in the Extended WPF Toolkit. It is a control that pops up a Window with a modal background effect, and you can specify the content to put inside the Window.

Black background before loading a wpf controll when using ElementHost

I'm using WPF in WinForms with ElementHost. When the form loads, there is a flash of black background where the ElementHost is about to load. This looks kind of bad. Any suggestions on how to get rid of this?
Hide the element (Visibility = Hidden) until the WinForms control is fully loaded...
I know this has already been answered and the question is old but none of the presented answers worked for myself and after a long time of troubleshooting the issue. I finally found an easier answer.
If you build a class extending from Element Host and in the initial constructor. You can set a Load Event for the Host Container. The Host Container is the panel that the Element Hosts Child is being displayed on top of. From there, just set the Host Containers background color to being of the Element Hosts Parents background color.
Like this
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
public class MyElementHost : ElementHost
{
public MyElementHost()
{
this.HostContainer.Loaded += new RoutedEventHandler(HostPanelLoad);
}
public void HostPanelLoad(object sender, RoutedEventArgs e)
{
System.Drawing.Color parentColor = this.Parent.BackColor;
this.HostContainer.Background = new SolidColorBrush(Color.FromArgb(parentColor.A, parentColor.R, parentColor.G, parentColor.B));
}
}
you need first show control with empty bounds first time to avoid black flickering
if (!_control.Created && _control.BackColor != Color.Transparent)
{
_control.Bounds = Rectangle.Empty;
_control.Show();
}
// set control bounds and show it
Rectangle bounds = GetBounds(context, rect);
if (_control.Bounds != bounds)
_control.Bounds = bounds;
if (!_control.Visible)
_control.Show();

Resources