The custom control I have created uses WM_NCCALCSIZE to define a custom
border area and modify the client size acordingly. This works perfect if the
border doesn't require a repaint and no invalidate of non-client area is
needed. However on capture focus event I want to give a glow effect to the
control so a nonclient area repaint is needed. To repaint I have found that
I can use this method to invalidate the non-client area:
/// <summary>
/// Invalidates non-client area
/// </summary>
private void InvalidateNC()
{
//try to fix flickering problems
User32.SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0,
User32.SWP.SWP_NOMOVE |
User32.SWP.SWP_NOSIZE |
User32.SWP.SWP_NOZORDER |
User32.SWP.SWP_NOACTIVATE |
User32.SWP.SWP_DRAWFRAME
);
}
where:
User32 contains this:
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy, uint uFlags);
public struct SWP {
public const int SWP_NOSIZE = 0x0001;
public const int SWP_NOMOVE = 0x0002;
public const int SWP_NOZORDER = 0x0004;
public const int SWP_NOREDRAW = 0x0008;
public const int SWP_NOACTIVATE = 0x0010;
public const int SWP_FRAMECHANGED = 0x0020; // The frame changed: send
WM_NCCALCSIZE
public const int SWP_DRAWFRAME = SWP_FRAMECHANGED;
public const int SWP_SHOWWINDOW = 0x0040;
public const int SWP_HIDEWINDOW = 0x0080;
public const int SWP_NOCOPYBITS = 0x0100;
public const int SWP_NOOWNERZORDER = 0x0200; // Don't do owner Z ordering
public const int SWP_NOREPOSITION = SWP_NOOWNERZORDER;
public const int SWP_NOSENDCHANGING = 0x0400; // Don't send
WM_WINDOWPOSCHANGING
}
So in the code i override OnEnter and OnLeave and call InvalidateNc at the
end.
Everything works fine, only that on every Invalidate huge flickering
appears. Debuging the problem I have found that after the NC_CALCSIZE
message with WParam = true the control dissapears completely and will be
redrawn. It shouldn't redraw since I return m.Result = IntPtr.Zero and
WParam doesn't change. I have debuged the message from start to end and the
only thing that my "WndProc message override" does is recompute the client
area. At the start of the message LParam looks like this:
----
lpPos //doesn't matter it doesnt' get changed
rectBeforeMove = {162,26,162,41}
rectClientBeforeMove = {168,32,150,29}
rectProposed = {162,25,162,41}
--
after the override the only thing changed is rectProposed recomputing the
client according to the border:
----
lpPos //doesn't matter it doesnt' get changed
rectBeforeMove = {162,26,162,41}
rectClientBeforeMove = {168,32,150,29}
rectProposed = {168,32,150,29}
--
where the structure is defined like this:
[StructLayout(LayoutKind.Sequential)]
public struct NCCALCSIZE_PARAMS
{
/// <summary>
/// Contains the new coordinates of a window that has been moved or resized,
that is, it is the proposed new window coordinates.
/// </summary>
public RECT rectProposed;
/// <summary>
/// Contains the coordinates of the window before it was moved or resized.
/// </summary>
public RECT rectBeforeMove;
/// <summary>
/// Contains the coordinates of the window's client area before the window
was moved or resized.
/// </summary>
public RECT rectClientBeforeMove;
/// <summary>
/// Pointer to a WINDOWPOS structure that contains the size and position
values specified in the operation that moved or resized the window.
/// </summary>
public WINDOWPOS lpPos;
}
Liviu Balan,
System Engineering
I think it's better to have a sample to research on this issue. If
possible, could you please send me a sample project that could just
reproduce the problem?
To get my actual email address, remove 'online' from my displayed email
address.
Thank your for your cooperation!
Sincerely,
Linda Liu
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
I just sent an e-mail with the flickering problem.
Thank you for trying to help,
Liviu Balan
Systems Engineering
"Linda Liu [MSFT]" <v-l...@online.microsoft.com> wrote in message
news:DzRohzxg...@TK2MSFTNGHUB02.phx.gbl...
I'm working in VB.Net (in WindowsXP) and have a lot of code for the base
Controls, but have extracted and converted the relevant parts to C#.
Hopefully, I've included all the necessary code.
I'm fairly happy with the results, but there may be some improvements that
can be made.
If you're Control derives from ScrollableControl, then things start to get
much more complicated as you need to modify the hRegion passed to m.wParam
so that it contains the Window Rectangle (in Parent relative coordinates)
minus the ClientRectangle and ScrollBarRectangles, but it should include the
GrowBox rectangle if both scrollbars are visible.
The class below shows a basic Control based class. For simplicity, I have
only included the WM_NCCALCSIZE and WM_NCPAINT methods, and an
InvokeNCPaint() method which I use to force a NonClient paint as necessary,
but obviously theres a bit more to it than that.
I believe the control will work OK in Vista, but I can't verify that.
\\\
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Dotnetrix.Samples.CSharp
{
class NCControlBase : Control
{
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case NativeMethods.WM_NCCALCSIZE:
{
if (m.WParam.Equals(IntPtr.Zero))
{
NativeMethods.RECT rc = (NativeMethods.RECT)m.GetLParam(
typeof(NativeMethods.RECT));
rc.Inflate(-4, -4);
Marshal.StructureToPtr(rc, m.LParam, true);
m.Result = IntPtr.Zero;
}
else
{
NativeMethods.NCCALCSIZE_PARAMS csp =
(NativeMethods.NCCALCSIZE_PARAMS)
m.GetLParam(typeof
(NativeMethods.NCCALCSIZE_PARAMS));
csp.rgrc0.Inflate(-4, -4);
Marshal.StructureToPtr(csp, m.LParam, true);
m.Result = (IntPtr)(NativeMethods.WVR_VALIDRECTS |
NativeMethods.WVR_REDRAW);
}
break;
}
case NativeMethods.WM_NCPAINT:
{
NCPaint();
base.DefWndProc(ref m);
NativeMethods.DeleteObject(m.WParam);
m.Result = IntPtr.Zero;
break;
}
}
base.WndProc(ref m);
}
private void NCPaint()
{
if (this.Parent == null)
return;
if (this.Width <= 0 || this.Height <= 0)
return;
IntPtr windowDC = NativeMethods.GetDCEx(this.Handle, IntPtr.Zero,
NativeMethods.DCX_CACHE | NativeMethods.DCX_WINDOW |
NativeMethods.DCX_CLIPSIBLINGS |
NativeMethods.DCX_PARENTCLIP |
NativeMethods.DCX_LOCKWINDOWUPDATE);
if (windowDC.Equals(IntPtr.Zero))
return;
Bitmap bm = new Bitmap(this.Width, this.Height,
PixelFormat.Format32bppPArgb);
Graphics g = Graphics.FromImage(bm);
//Define a Clip Region to exclude the Client Area.
Rectangle winBounds= new Rectangle(0, 0, this.Width, this.Height);
Region Rgn = new Region(winBounds);
Rectangle r = new Rectangle();
r.X = 4;
r.Y = 4;
r.Width = this.ClientSize.Width;
r.Height = this.ClientSize.Height;
Rgn.Exclude(r);
//Apply the Clip Region to the WindowDC
IntPtr hRgn = Rgn.GetHrgn(g);
if (!hRgn.Equals(IntPtr.Zero))
NativeMethods.SelectClipRgn(windowDC, hRgn);
g.FillRectangle(Brushes.Aqua, winBounds);
IntPtr bmDC = g.GetHdc();
IntPtr hBmp = bm.GetHbitmap();
IntPtr oldDC = NativeMethods.SelectObject(bmDC, hBmp);
NativeMethods.BitBlt(windowDC, 0, 0, bm.Width, bm.Height, bmDC, 0, 0,
NativeMethods.SRCCOPY);
//Clean Up
NativeMethods.SelectClipRgn(windowDC, IntPtr.Zero);
NativeMethods.DeleteObject(hRgn);
Rgn.Dispose();
g.ReleaseHdc(bmDC);
g.Dispose();
NativeMethods.SelectObject(oldDC, hBmp);
NativeMethods.DeleteObject(hBmp);
bm.Dispose();
NativeMethods.ReleaseDC(this.Handle, windowDC);
}
protected void InvokeNCPaint()
{
NativeMethods.SetWindowPos(this.Handle,
(IntPtr)NativeMethods.HWND_NOTOPMOST,
0, 0, 0, 0, NativeMethods.SWP_NOSIZE |
NativeMethods.SWP_NOMOVE |
NativeMethods.SWP_NOZORDER |
NativeMethods.SWP_FRAMECHANGED |
NativeMethods.SWP_NOCOPYBITS);
}
}
internal class NativeMethods
{
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll")]
public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip,
int flags);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd,
IntPtr hWndInsertAfter,
int X, int Y, int cx, int cy,
int uFlags);
[DllImport("gdi32.dll")]
public static extern int SelectClipRgn(IntPtr hdc, IntPtr hrgn);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest,
int nWidth, int nHeight, IntPtr hdcSrc,
int nXSrc, int nYSrc, int dwRop);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left, Top, Right, Bottom;
public RECT(Rectangle bounds)
{
this.Left = bounds.Left;
this.Top = bounds.Top;
this.Right = bounds.Right;
this.Bottom = bounds.Bottom;
}
public void Inflate(int x, int y)
{
this.Left -= x;
this.Top -= y;
this.Right += x;
this.Bottom += y;
}
public Rectangle ToRectangle()
{
return Rectangle.FromLTRB(Left, Top, Right, Bottom);
}
public int Height
{
get{ return this.Bottom - this.Top; }
}
public int Width
{
get{ return this.Right - this.Left; }
}
}
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
public IntPtr hWnd, hWndInsertAfter;
public int x ,y ,cx ,cy,flags;
}
[StructLayout(LayoutKind.Sequential)]
public struct NCCALCSIZE_PARAMS
{
public RECT rgrc0, rgrc1, rgrc2;
public WINDOWPOS lppos;
}
public const int WM_NCCALCSIZE = 0x83;
public const int WM_NCPAINT = 0x85;
public const int WVR_HREDRAW = 0x100;
public const int WVR_VREDRAW = 0x200;
public const int WVR_REDRAW = (WVR_HREDRAW | WVR_VREDRAW);
public const int WVR_VALIDRECTS = 0x400;
public const int SRCCOPY = 0xCC0020;
public const int DCX_WINDOW = 0x1;
public const int DCX_CACHE = 0x2;
public const int DCX_CLIPCHILDREN = 0x8;
public const int DCX_CLIPSIBLINGS = 0x10;
public const int DCX_PARENTCLIP = 0x20;
public const int DCX_LOCKWINDOWUPDATE = 0x400;
public const int HWND_NOTOPMOST = -2;
public const int SWP_NOSIZE = 0x1;
public const int SWP_NOMOVE = 0x2;
public const int SWP_NOZORDER = 0x4;
public const int SWP_FRAMECHANGED = 0x20;
public const int SWP_NOCOPYBITS = 0x100;
}
}
///
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
Thank you for your sample project.
I have run the program on my machine and did see the problem. The two
custom TextBoxes are flickering when I press the Tab key to switch to focus
between the two controls on the form.
Firstly, I'd like to say that you needn't use the private field '_hasFocus'
to track whether the custom control gets focused. Control class has
provided a property called 'Focused', which we can use to determine whether
the control gets focused or not.
Secondly, since what you want is to glow the custom TextBox when it gets
focused, I think you could send a WM_NCPAINT message to the control when it
gets focused, so that the non-client part of the control will be repainted.
To cancel the glowing when the control losts focus, you may send a
WM_NCPAINT message to control as well.
The following is the main alteration based on your sample code.
public partial class ZTextBox : System.Windows.Forms.TextBox
{
[DllImport("user32.dll")]
public static extern Int32 SendMessage(IntPtr hWnd, Int32 wMsg,
Int32 wParam, Int32 lParam);
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
SendMessage(this.Handle, 0x0085, 0, 0);
}
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
SendMessage(this.Handle, 0x0085, 0, 0);
}
protected void DrawBorder(Graphics g, Rectangle clientArea,IntPtr
hRgn)
{
....
if (hRgn.ToInt32() == 1)
{
//shadow
Drawing.DrawShadow(tmpMaskDC, borderPath, 3, 3);
//glow
using (GraphicsPath glowPath = new GraphicsPath())
{
glowPath.AddRectangle(outsideGlowRect);
Drawing.DrawGlow(tmpMaskDC, glowPath);
}
//white fill
using (Brush fillBrush = new
SolidBrush(System.Drawing.Color.White))
{
tmpMaskDC.FillPath(fillBrush, borderPath);
}
//border
if(this.Focused == false)
{
using (Pen borderPen = new Pen(new
SolidBrush(Color.FromArgb(150, 150, 150)), 2))
{
tmpMaskDC.DrawRectangle(borderPen, outsideRect);
}
}
else
{
using (Pen borderPen = new Pen(new
SolidBrush(Color.FromArgb(0, 150, 150)), 2))
{
tmpMaskDC.DrawRectangle(borderPen, outsideRect);
}
}
g.DrawImage(tmpBmp, clientArea);
}
private void PaintNonClientArea(IntPtr hWnd, IntPtr hRgn)
{
...........
using (Graphics g = Graphics.FromHdc(hDC))
{
DrawBorder(g, new Rectangle(0, 0, this.Size.Width,
this.Size.Height),hRgn);
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case (int)User32.WindowMessages.WM_NCCALCSIZE:
{
WmNCCalcSize(ref m);
break;
}
case (int)User32.WindowMessages.WM_NCPAINT:
{
// Here should all our painting occur, but...
WmNCPaint(ref m);
break;
}
// comment out the entire case branch below
//case (int)User32.WindowMessages.WM_PAINT:
// {
// Console.WriteLine("WM_PAINT");
// //TODO: This will cause infinite loop flickering
// //if two controls are on top of eachother
// // if design mode don't repaint border
// //if (!this.DesignMode)
// //{
// // InvalidateNC();
// //}
// base.WndProc(ref m);
// break;
// }
default:
{
base.WndProc(ref m);
break;
}
}
}
}
In addition, I comment out the code to call the InvalidateNC method in
OnEnter, OnLeave, OnLostFocus, OnPaintBackground and OnResize methods.
I also send you the modified sample project via email.
If you have any question, please feel free to let me know.
Thank you for fixing that code. I had a lot of problems trying to work
around the flickering problem.
It seems that our company has a strong policy against receiving mail
attachements so I wasn't able to get your modified solution. Do you think is
possible to resend the e-mail to my hotmail account? (lbal...@hotmail.com)
Thank you a lot,
Liviu Balan
Systems Engineer
"Linda Liu [MSFT]" <v-l...@online.microsoft.com> wrote in message
news:NCJ9zIZh...@TK2MSFTNGHUB02.phx.gbl...
Thank you for your prompt response.
I have sent the modified solution to your hotmail account.
Thank you for your work. The direct call for ncpaint message solved a lot of
problems.
However there still seem to be a problem with deleting the WM_PAINT message
override. If we don't invalidate the non client area the border can
disappear in some cases. For example: if we cover the application window
with any other dialog/application and then move it on top of the custom text
box the border will disappear or have strange paint artifacts. However if we
override the WM_PAINT message and invalidate the area some flickering
appears.
Thank you,
Liviu Balan
Systems Engineering
"Linda Liu [MSFT]" <v-l...@online.microsoft.com> wrote in message
news:MHztIohh...@TK2MSFTNGHUB02.phx.gbl...
It's not exactly what you want since you are Inheriting TextBox which
already has a NonClient Area, but it's not far off.
The order which you should be doing things in response to a WM_NCPAINT
message:
1. Call your NonClientPaint() method passing m.wParam by reference since
you'll need to modify the original hRegion if you keep the original
NonClientArea.
2. Call base.DefWndProc()
3. Delete the hRegion passed to m.wParam or you will eventually get a
Generic GDI exception when your leaked GDI objects grow too much.
4. Set m.Result to Zero
5. Call base.Wndproc()
You do not need to intercept the WM_PAINT method. This only invalidates the
Client Area.
Windows will paint the original NonClientArea if you do not modify the
hRegion passed to m.Wparam. I haven't seen your code, but I believe that
this is very likely what is causing your flicker (unless you're also
painting over the Client Area).
I would suggest that you remove the original border (BorderStyle = None) and
repaint it yourself. You could even override the BorderStyle property so
that the base control always has it's BorderStyle set to None no matter what
value the overriden property has. You would then find that the example I
gave works just fine as is.
Hopefully, you are using BitBlt to draw to the Window. If not then try
setting your Forms opacity to anything less than 100% and see how this
affects the right and bottom edge of your NonClient control (assuming you
are actually changing the border size).
SendMessage() does indeed work much better than SetWindowPos(). I can't
remember why I originally used SetWindowPos() but I'm not using it now ;-)
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
"Liviu Balan" <lbal...@community.nospam> wrote in message
news:uvT5dYph...@TK2MSFTNGP04.phx.gbl...
Thank you for your reply. The custom control I build followed exactly your
steps with very promising results. Linda helped me by pointing out the
flickering problems:
- calling InvalidateNC instead of sending an WM_NCPAINT causes flicker
- my paint method was painting without taking into consideration the hRgn
value of the WM_NCPAINT message. Linda introduced a check that will paint
the transparent area of the border only if hRgn.ToInt32() == 1.
About WM_NCCALCSIZE message I'm pretty confident it works right since the
border width and client area are always as expected.
This is what works. But there are some graphical problems: when a region of
the border gets invalidated the control won't repaint it's non-client area
too. Like I have tried to explain in my last post when any window is moved
over the control the non-client area will dissapear and it will take a while
until a new WM_NCPAINT message gets called. And second if I put the control
in a container that uses double buffering sometimes (not always and this is
strange) the border doesn't get painted at all.
If you want to take a look at the small test solution Linda helped me with
please let me know and I'll send the code to your e-mail.
Thank you,
Liviu Balan
Systems Engineering
"Mick Doherty"
<EXCHANGE#WI...@AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com]> wrote in
message news:ONpVNVs...@TK2MSFTNGP06.phx.gbl...
If m.wParam.ToInt32() == 1 then the entire Frame needs painting. If it is
any other value then it represents the handle to a clip region and only part
of the NonClient Area needs repainting, such as when you drag a window over
the top of your window.
> If you want to take a look at the small test solution Linda helped me with
> please let me know and I'll send the code to your e-mail.
If you send me a copy of the source, I'll be happy to a look at it.
I've recieved the source and I am 100% certain that I can improve it.
I won't have time to look over it properly until the weekend, but I am
sending you a slightly modified version of the code I posted in this thread
(Inherits TextBox as well as some other minor adjustments) to show you the
sort of results you should be expecting. It doesn't paint in your style, but
it doesn't flicker or mis-paint. You may be able to adapt my example to your
needs before I get a chance to check your code over.
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
"Mick Doherty"
<EXCHANGE#WI...@AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com]> wrote in
message news:Odqp4Q4h...@TK2MSFTNGP02.phx.gbl...
I performed a test on the sample application and did see that the
non-client part of the custom TextBox doesn't get repainted when a window
covers over it and then is removed.
I have modified the code in the DrawBorder method within the ZTextBox class
as follows:
protected void DrawBorder(Graphics g, Rectangle clientArea,IntPtr hRgn)
{
....
// modify the condition from 'hRgn.ToInt32() == 1' to 'hRgn.ToInt32()
!= 0'
if (hRgn.ToInt32() != 0)
{ .... }
....
}
I also modified the DrawShadow(Graphics g, GraphicsPath path, int
ShadowDownOffset, int ShadowRightOffset) method in the Drawing class as
follows:
public static void DrawShadow(Graphics g, GraphicsPath path, int
ShadowDownOffset, int ShadowRightOffset)
{
...
// add the following code to clear the graphics object
g.Clear(SystemColors.Control);
g.FillPath(brush, ShadowPath);
...
}
Please try my suggestion and let me know the result.
Is Transparency of the Client Area something that you really need? Setting
WS_EX_TRANSPARENT in the CreateParams() method is another thing that is
causing you problems, but AFAIKT is not giving the desired effect.
I think it's easier for me to rewrite your class rather than try to fix it
and so I have made some further modifications to the example class I sent
you and it now draws the Border, Shadow and Glow from your example. I will
attempt to implement Transparency, before sending you the updated class, but
I'm not sure how successful this will be since TextBox seems to behave
differently to other controls in this respect.
I was just doing some testing with different property settings and found
that the control is not always painting scrollbars correctly.
It seems that System.Windows.Forms.TextBox is a bit under the weather.
You can see the same issues in the standard TextBox by setting the following
properties:
Multiline: True
RightToLeft: Yes
ScrollBars: Both
TextAlign: Left
WordWrap: False
Before I spend anymore time on this, should I attempt to correct this in the
class I'm working on, or are you unlikely to need this or any similar
combination of these settings?
... and another issue, set TextAlign to Center or Right (Left if RightToLeft
= True) and you get WordWrap regardless of the setting.
I'm off to check the bug reports!
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
"Mick Doherty"
<EXCHANGE#WI...@AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com]> wrote in
message news:%23HVtbrX...@TK2MSFTNGP05.phx.gbl...
Sorry for the delay in my response. I received your sample solution. I am
trying to figure out now how to make full transparency work since that is a
hard requirement for this controls border. Anyway your e-mail helped me fix
many problems in my code. I am still working on the code and once I have
something acceptable I'll post again and send you the resulting code by
e-mail if you don't mind.
Thank you,
Liviu Balan
Systems Engineer
"Mick Doherty"
<EXCHANGE#WI...@AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com]> wrote in
message news:Odr8q%23ZiHH...@TK2MSFTNGP05.phx.gbl...
Your code changes are welcomed. As Mick observed, there are important leaks
with the GDI so this fixes the problem. I'm trying to refactor the class a
little to make it more efficient with double buffering and proper clip
areas. I'll let you know how this goes.
Thank you again,
Liviu Balan
Systems Engineer
"Linda Liu [MSFT]" <v-l...@online.microsoft.com> wrote in message
news:WX$eWNViH...@TK2MSFTNGHUB02.phx.gbl...
Don't worry about the delay in your response. I program purely as a hobby
and so the weekend is the best time for me, but if it's your job, then you
probably want a rest from it (I know that work is the last thing I want to
think about at the weekend).
Whilst looking into the issues in the standard textbox, I discovered that
the TextBox class has the CS_PARENTDC style set. I haven't figured out how
yet, but according to the documentation, since the class uses the same DC as
it's parent, you should be able to draw the glow directly on to the parents
window and so you wouldn't need transparency in the Non client area.
Another idea might be to create a Glow Layer control. This would basicly be
a control with the WS_EX_TRANSPARENT style set. It would be docked to fill
and put at the top of the zOrder. You could intercept this controls
WM_NCHITTEST method and return HTTRANSPARENT so that any mouse messages are
sent to the control underneath it. This could then extend other controls and
paint a glow around them when they recieve focus.
I haven't really thought these ideas through and they may not be feasible,
but they may be easier than trying to implement true transparency. The
second option would even give the option to paint a glow on top of other
controls which overlap the Glow Area.
Feel free to send me any updates, or to ask any questions which you feel I
might be able to answer.
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
"Liviu Balan" <lbal...@community.nospam> wrote in message
news:OpW$GfziHH...@TK2MSFTNGP02.phx.gbl...
I had some time today to mess up again with this control so I will just post
some more comments.
On the good side the custom control doesn't require a scrollbar so that
simplifies a little bit the code.
On the bad side real transparency is required and some controls might even
overlap. From this point direct painting to the parent window seems to
complicate things. This happens only at a first view.
So I did a lot of tests with the transparency create param flag 0x20. I have
also fixed the GDI leak as per your suggestion, added the client clipping
region and modified the code as Linda suggested. That improved a lot the
control but the overlapping problem is still there. (If two controls
intersect things get out of control. Moving a window over it will make the
border disappear in certain cases.) I have tried to apply the same create
param to your custom class and got same result. It seems that even the
client area gets some painting artifacts at some points and I am starting to
think more and more that the default api transparency has some underlying
problems.
Anyway, after trying to fix this in different ways I am thinking to get back
to your idea of painting on the parent or letting the parent manage the
transparency. Implementing a custom transparency/z-order engine over a
window would involve a lot of coding and I am not sure how fast the result
would be in the end.
Those are just some comments but at this point I won't be surprised to find
out that control, region transparency in win api has huge implementation
issues.
Liviu Balan
Systems Engineer
"Mick Doherty"
<EXCHANGE#WI...@AND.REMOVE.SQUAREBRACKETS.[mdaudi100#ntlworld.com]> wrote in
message news:uSs%237AAjH...@TK2MSFTNGP03.phx.gbl...
Your suggestions made the control act more close to what is expected.
However the problem is still there. I have also solved the GDI leak and
added client clipping as per Mick's suggestion. Overall this made things
much better but as I noted in Mick's response the transparency still causes
the control to hide its border. Even more interesting some painting
artifacts appear in the client area when another window moves over it. T
here might be multiple problems but maybe the nonclient painting is not
called all the time when it should be called and second there might be some
issues with the transparency api.
Liviu Balan
Systems Engineer
"Linda Liu [MSFT]" <v-l...@online.microsoft.com> wrote in message
news:WX$eWNViH...@TK2MSFTNGHUB02.phx.gbl...
I have played around with the WS_EX_TRANSPARENT style in the past, and I
never got any sort of result which I found to be acceptable.
According to the documentation when this style is set, if your control needs
painting, it causes every control underneath your control to paint itself
first, and then it paints itself. It would appear however, that if one of
those controls also has this style set, that it paints itself after your
control has painted, so you end up with what looks like a zOrder problem. On
top of all that, it appears that a window with this style does not support
Double Buffering and so you end up with a lot of flickering.
I played with this for a while and eventually gave it up as a bad idea. I
keep meaning to revisit the issue as I do not like these things to beat me,
but I've had plenty of other problems to keep me occupied and so never have.
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
"Liviu Balan" <lbal...@community.nospam> wrote in message
news:OI5j$4OjHH...@TK2MSFTNGP02.phx.gbl...
If it's just the border that you want true transparency in, then maybe you
should Dock.Fill a textbox to a Transparent control with a modified
DisplayRectangle. You'll still have zOrder issues, but this would solve the
problem of the mispainted Client Area.
--
Mick Doherty
http://dotnetrix.co.uk/nothing.html
"Liviu Balan" <lbal...@community.nospam> wrote in message
news:OI5j$4OjHH...@TK2MSFTNGP02.phx.gbl...
I am glad to hear that the performance of your application is improved a
lot. I'd like to thank Mick for his kind help on this issue : )
> Overall this made things much better but as I noted in Mick's response
the transparency still causes the control to hide its border.
What the 'transparency' do you mean in the above sentence? Could you
explain a little more?
In fact, TextBox doesn't support transparent back color. So TextBox
subclasses don't support transparent back color, either.
You have mentioned that when two derived TextBoxes intersect, things get
out of control; and moving a window over the derived TextBox will make the
border disappear in certain cases. Mick has suggested that you place the
derived TextBox in a Panel, and dock fill the derived TextBox to the Panel.
I have tried this workaround and confirmed it works.
Hope this helps.
How about the problem now?
If you still need our assistance, please feel free to let me know.
Thank you for using our MSDN Managed Newsgroup Support Service!