I went on hacking up a small patch to implement WS_EX_TRANSPARENT in
the X11 backend. What should happen when this style/flag is set is
that transparency for the control is simulated. When the transparent
control is going to receive WM_PAINT, first its container and other
controls will be send a WM_PAINT before the transparent control get
its. This behaviour is in Windows itself, so it works with the Win32
xplatui backend and is not Control.cs specific.
The issue with the patch is that even though the order of repaints is
changed I still get black rectangle where the control should be. May
be you can help me out on this one?
I have attached a test-case to CWL wm_paint order for you and the patch.
P.S: One thing I've notices is that zorder when adding initially
controls in x11 is reversed opposed to win32. A bug? (you will have to
swap the below and above controls for proper result wth the testcase
on win32)
P.S2: The patch can be optimized, etc etc.
--
Ivan N. Zlatev
Web: http://www.i-nZ.net
"It's all some kind of whacked out conspiracy."
Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/Hwnd.cs
===================================================================
--- mcs/class/Managed.Windows.Forms/System.Windows.Forms/Hwnd.cs (revision 74173)
+++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/Hwnd.cs (working copy)
@@ -560,6 +560,13 @@
}
}
+ public bool Transparent {
+ get {
+ return ((initial_ex_style & WindowExStyles.WS_EX_TRANSPARENT)
+ == WindowExStyles.WS_EX_TRANSPARENT);
+ }
+ }
+
public int X {
get {
return x;
Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
===================================================================
--- mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs (revision 74173)
+++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs (working copy)
@@ -3611,7 +3611,7 @@
if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
goto ProcessNextMessage;
}
- msg.message=Msg.WM_MOUSE_LEAVE;
+ msg.message=Msg.WM_MOUSELEAVE;
HoverState.Timer.Enabled = false;
HoverState.Window = IntPtr.Zero;
break;
@@ -3819,6 +3819,11 @@
ShowCaret();
Caret.Paused = false;
}
+
+ if (hwnd.Transparent) {
+ SimulateTransparency (hwnd);
+ }
+
msg.message = Msg.WM_PAINT;
break;
}
@@ -5272,10 +5277,33 @@
return;
}
+ if (hwnd.Transparent) {
+ SimulateTransparency (hwnd);
+ }
+
SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
hwnd.Queue.Paint.Remove(hwnd);
}
+ private void SimulateTransparency (Hwnd hwnd)
+ {
+ if (hwnd.Transparent) {
+ Control parent = Control.FromHandle (GetParent (hwnd.Handle));
+ // Repaint all controls before the transparent one.
+ if (parent != null) {
+ int index = parent.Controls.IndexOf (Control.FromHandle (hwnd.Handle));
+ hwnd.expose_pending = true;
+ UpdateWindow (parent.Handle);
+ for (int i = 0; i < parent.Controls.Count; i++) {
+ if (i != index) {
+ UpdateWindow (parent.Controls[i].Handle);
+ }
+ }
+ hwnd.expose_pending = false;
+ }
+ }
+ }
+
internal override void CreateOffscreenDrawable (IntPtr handle,
int width, int height,
out object offscreen_drawable)
using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
namespace mwfbugs
{
public class TransparentControlTest
{
public static void Main (string[] args)
{
Form f = new Form ();
LogPanel p = new LogPanel ("ContainerPanel");
p.BackColor = Color.Blue;
LogControl above = new LogControl ("AboveControl");
above.BackColor = Color.Red;
above.Width = 20;
above.Height = 20;
TransparentControl t = new TransparentControl ("TransparentControl");
t.Width = 200;
t.Height = 200;
LogControl below = new LogControl ("BelowControl");
below.BackColor = Color.Green;
below.Width = 50;
below.Height = 50;
p.Controls.Add (below);
p.Controls.Add (t);
p.Controls.Add (above);
f.Controls.Add (p);
f.ShowDialog ();
}
}
public class TransparentControl : LogControl
{
public TransparentControl (string name) : base (name)
{
// this.SetStyle (ControlStyles.SupportsTransparentBackColor, true);
//this.BackColor = Color.Transparent;
}
protected override void OnPaintBackground (PaintEventArgs pevent)
{
//pevent.Graphics.FillRectangle (new SolidBrush (Color.Transparent), new Rectangle (0, 0, this.Width, this.Height));
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnClick (EventArgs e)
{
this.Parent.Refresh ();
base.OnClick (e);
}
protected override void OnPaint (PaintEventArgs e)
{
base.OnPaint (e);
e.Graphics.DrawLine (new Pen (Color.Orange), new Point (0, 0), new Point (200, 200));
}
}
public class LogPanel : Panel
{
private string _name;
public LogPanel (string name)
{
_name = name;
}
public string Name {
get { return _name; }
}
public override string Text {
get { return _name; }
set { base.Text = value;}
}
protected override void OnPaint (PaintEventArgs e)
{
Console.WriteLine (this.Name + ": " + "OnPaint");
base.OnPaint (e);
}
protected override void WndProc (ref Message m)
{
if (m.Msg == 15) {
Console.WriteLine (this.Name + ": " + "WM_PAINT");
}
base.WndProc (ref m);
}
}
public class LogControl : UserControl
{
private string _name;
public LogControl (string name)
{
_name = name;
}
public string Name {
get { return _name; }
}
public override string Text {
get { return _name; }
set { base.Text = value;}
}
protected override void OnPaint (PaintEventArgs e)
{
Console.WriteLine (this.Name + ": " + "OnPaint");
base.OnPaint (e);
}
protected override void WndProc (ref Message m)
{
if (m.Msg == 15) {
Console.WriteLine (this.Name + ": " + "WM_PAINT");
}
base.WndProc (ref m);
}
}
}
_______________________________________________
Mono-winforms-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list