How to Prevent Flicker (Double-buffering not helping)

C

Charles Law

This is actually a follow on from yesterday's post about masking mouse
clicks in a user control.

The solution I have implemented - from Herfried - places a transparent
window over the entire user control, which then uses the various mouse
events to allow the user to drag the control without any clicks going
through to the buttons and dropdowns on the control below. All well and
good.

However, I am getting an unsightly flicker when I enable and disable the
feature.

I change the drag enable feature simply by making the transparent window
either visible or not visible. In either case, when the visible state is
changed, I get a flicker of the controls underneath that I cannot get rid
of. I have tried enabling double-buffering for the form and the user control
but it makes no difference. Oddly, the problem is very bad for the TrackBar
control, but imperceptible for other controls.

Can anyone suggest any other techniques for making my form and control
flicker free?

TIA

Charles
 
H

Herfried K. Wagner [MVP]

Charles,

* "Charles Law said:
The solution I have implemented - from Herfried - places a transparent
window over the entire user control, which then uses the various mouse
events to allow the user to drag the control without any clicks going
through to the buttons and dropdowns on the control below. All well and
good.

However, I am getting an unsightly flicker when I enable and disable the
feature.

I change the drag enable feature simply by making the transparent window
either visible or not visible. In either case, when the visible state is
changed, I get a flicker of the controls underneath that I cannot get rid
of. I have tried enabling double-buffering for the form and the user control
but it makes no difference. Oddly, the problem is very bad for the TrackBar
control, but imperceptible for other controls.

I would not actually hide the control that is placed over the other
controls. Instead, I would handle the 'MouseUp' and 'MouseDown' events
and move the controls behind the transparent control accordingly.
 
M

Mick Doherty

I just tried this out and it seems to work OK.
It's probably a different drag method to yours but it was quick and simple.

I use a MenuItem (EditMenu) to switch between Design and Run Mode.
I added the Transparent Control from the other thread which I named
TransControl.
Add this code to your form:

\\\
Const WM_NCLBUTTONDOWN As Integer = &HA1
Const HT_CAPTION As Integer = &H2

Private Sub TransControl_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles TransControl.MouseDown

If Me.Controls.GetChildIndex(TransControl) <> 0 Then Return

Dim Child As Control

For Each c As Control In Me.Controls
If c.Bounds.Contains(e.X, e.Y) Then
If Not c Is Me AndAlso Not c Is TransControl Then
Child = c
End If
End If
Next

If Child Is Nothing Then Return

TransControl.Capture = False
WndProc(Message.Create(Child.Handle,WM_NCLBUTTONDOWN, _
IntPtr.op_Explicit(HT_CAPTION), IntPtr.Zero))
TransControl.BringToFront()

End Sub

Private Sub EditMenu_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles EditMenu.Click

If Me.Controls.GetChildIndex(TransControl) = 0 Then
TransControl.SendToBack()
Else
TransControl.BringToFront()
End If

End Sub
///
 
C

Charles Law

I also tried changing the z-order, but this did not improve things for me.
In addition, the bits of the transparent window that are not covered by
controls allows the user control to be dragged even in run mode.

What may make it worse for me is that I have an MDI app with a child window.
This child window contains my user control which is itself made up of user
controls. The base class is the one that implements the transparent window,
and also includes the track bar control. When I switch between design and
run mode it is only the track bar control that disappears and is then
redrawn. It is very noticeable. It is as if there is something specific with
the track bar control.

Charles


"Mick Doherty"
 
C

Charles Law

I would not actually hide the control that is placed over the other
controls. Instead, I would handle the 'MouseUp' and 'MouseDown' events
and move the controls behind the transparent control accordingly.

I'm not sure I quite follow you. Are you saying that you would have the
controls behind the transparent control always? If that is the case, how
would you pass the mouse events to the controls behind when the control is
not draggable, i.e not in design mode?

Charles
 
H

Herfried K. Wagner [MVP]

* "Charles Law said:
I'm not sure I quite follow you. Are you saying that you would have the
controls behind the transparent control always? If that is the case, how
would you pass the mouse events to the controls behind when the control is
not draggable, i.e not in design mode?

You would have to implement the dragging yourself and check what control
is under the mouse pointer based on position and Z-order. Sure, that's
very complicated and I assume that there are easier solutions...
 
C

Charles Law

Hmm. The easier solution I had in mind was making the transparent control
invisible when not in design mode. Then, it's just one line.

Assuming, for the moment, that I don't go down the route of writing all this
extra code, can you think why only the track bar control should disappear,
whilst checkboxes, labels and a progress bar are rock steady?

Charles
 
H

Herfried K. Wagner [MVP]

* "Charles Law said:
Hmm. The easier solution I had in mind was making the transparent control
invisible when not in design mode. Then, it's just one line.

Mhm... But then, the controls can receive focus, which is not the case
for VS.NET's Windows Forms designer.
Assuming, for the moment, that I don't go down the route of writing all this
extra code, can you think why only the track bar control should disappear,
whilst checkboxes, labels and a progress bar are rock steady?

Sorry, I don't understand this sentence... My English is too bad.
 
C

Charles Law

Mhm... But then, the controls can receive focus, which is not the case
for VS.NET's Windows Forms designer.

Ah, yes, but that is what I want to happen. When in 'design mode' the user
can drag one of my user controls around the form and position it at will.
When they come out of design mode, the user control should behave just like
a regular control, with buttons pressing and performing actions and
dropdowns dropping down for selection.

I was just asking why the track bar might behave differently. It is the only
control that I use that has this flicker problem. Actually, it is more than
just a flicker, because the control is erased and then redrawn.

Charles
 
J

Jay B. Harlow [MVP - Outlook]

Charles,
In your many posts on your project, did anyone ever refer you to this
article on creating a Windows Forms Designer?

I'm just wondering if the article (or sample code) has any insights that may
help you in your endeavors...

http://www.windowsforms.net/default.aspx?tabindex=6&tabid=47&ItemID=13&mid=142

Along the same lines I wonder if the Sharp Develop source would give you any
ideas.

http://www.icsharpcode.net/OpenSource/SD/

As it sounds like you are creating a Designer of sorts...

Hope this helps
Jay
 
M

Mick Doherty

I'm confused!
In addition, the bits of the transparent window that are not covered by
controls allows the user control to be dragged even in run mode.
Surely your controls can only be dragged by an event raised by the
transparent window, thus, if the transparent window is not on top of the
control then the control cannot be dragged.

I do see minor flicker of the Trackbar control, but I'm not sure you are
going to get rid of this.
I do not think it unreasonable to see a minor flicker when switching between
modes.
 
C

Charles Law

Hi Jay

I am creating a designer, in fact, although that should have been the easy
part ;-)

They are actually two separate projects: one is primarily a designer; an
html forms designer. The other is a control application, where the user
needs to arrange the components they wish to control (over a serial/usb
port) on a series of windows, before they start clicking buttons to drive
the external devices.

Anyway, I will certainly look at the link. I have looked at the SharpDevelop
stuff, but there is just so much of it that tracking down the interesting
bit is a full-time job in itself.

Cheers

Charles
 
C

Charles Law

Hi Mick

Send to back does not send the transparent control/window behind the user
control; just behind the controls _on_ the user control. Therefore, wherever
there is a gap between controls, the transparent control can still be
clicked, and hence dragged.

I have just knocked up a test app to simplify the task, and I agree that
there is only slight flicker of the track bar. But, for some reason, when I
run my main app with all its windows and other controls, the effect is ten
times worse.

If it were all controls then I would agree that it might just be something I
had to live with. But when it is only one control my suspicions are raised.

Charles


"Mick Doherty"
 
J

Jay B. Harlow [MVP - Outlook]

Charles,
Anyway, I will certainly look at the link. I have looked at the SharpDevelop
stuff, but there is just so much of it that tracking down the interesting
bit is a full-time job in itself.
However their code may have the "right answer" were as we can only offer
"best guest".

I would probably do both scrutinize their code and ask here.

Just a thought
Jay
 
M

Mick Doherty

Are you dragging the transparent window or the usercontrol?
I know that you are doing this in a usercontrol instead of a form, but the
principal is the same.

I assumed you were dragging controls, as my example does. The Transparent
control is Docked to fill and the dragging of controls is activated in the
mousedown event of the transparent control. If the Transparent control is
not at zOrder 0 (i.e. OnTop of all other controls) then the Drag method is
not Initialised.
Is this not what you are doing?
 
C

Charles Law

I am certainly dragging the transparent window. As you suggest, I am using
the mouse events of the transparent control to trigger this.

When my base class loads, I create the transparent window object, which is
declared WithEvents so that I can process the appropriate mouse events
easily.

I dock it, add it to the Controls collection, and then bring it to the front
of the z-order. Thereafter, to disable dragging I make the transparent
window invisible, thus allowing the user control below to behave like an
active control.

Up to this point, I am happy with the way it performs. It does exactly what
I want it to do. The issue I have is with the disappearing track bar. I have
tried sending the transparent window to the back and front, and every time
the track bar disappears and is redrawn. Therefore, I conclude that it is
not the hiding of the transparent window that is the problem, but something
else, intrinsic to the track bar.

Charles


"Mick Doherty"
 
C

Charles Law

Yes I did. It doesn't go very far though, and a lot of the things it leaves
out are the tricky bits. Anyway, this project is actually complete now, and
I am at the stage of adding new features.

The live project, as it were, is the control application. That other link
you gave points to a very good article and code in both C# and VB.NET. It
shows how to do just about everything I need, and in surprising little code
as well. It doesn't specifically address the disappearing track bar problem
though.

Charles
 
C

Charles Law

Using Enabled instead of Visible works every bit as well, without the
disappearing track bar.

Charles
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top