Opened 5 years ago

Closed 4 years ago

Last modified 4 years ago

#12087 closed defect (fixed)

wxOwnerDrawnComboBox animated drop-down doesn't draw correctly

Reported by: mcben Owned by:
Priority: normal Milestone: 2.9.2
Component: GUI-generic Version: stable-latest
Keywords: wxOwnerDrawnComboBox wxVListBoxComboPopup Cc:
Blocked By: Blocking:
Patch: no

Description

in a VS2010/win7 build: wxEnumPropertys (like "BoolProperty" or "ColourProperty" from the sample)
doesn't draw correctly.
Hard to describe so I added a screenshot.

Attachments (2)

Zwischenablage02.jpg download (55.9 KB) - added by mcben 5 years ago.
screenshot of propgrid sample
Zwischenablage01.png download (910 bytes) - added by mcben 5 years ago.
ownerdrawncombobox of widgets-sample (empty list)

Download all attachments as: .zip

Change History (20)

Changed 5 years ago by mcben

screenshot of propgrid sample

comment:1 Changed 5 years ago by jmsalli

  • Status changed from new to infoneeded_new

Sorry, I can't reproduce this on Windows 7 with VS2008. Could you provide more information about your system?

Changed 5 years ago by mcben

ownerdrawncombobox of widgets-sample (empty list)

comment:2 Changed 5 years ago by mcben

  • Component changed from wxPropertyGrid to GUI-generic
  • Keywords wxOwnerDrawnComboBox wxVListBoxComboPopup added
  • Status changed from infoneeded_new to new
  • Summary changed from wxEnumProperty animated drop-down doesn't draw correctly to wxOwnerDrawnComboBox animated drop-down doesn't draw correctly

Win7 Home/32bit (German); VS2010 (includes .Net-Framework 4)
..same executable works fine on another WinXP machine..


a better description how it looks like:
when the drop-down list slides-in artifacts of the last animation frame is drawn on top of the new one.
For example: an empty list will draw a rectangle filled with horz.line artifacts. May be from lower border? see "Zwischenablage01.png"

When the animation is finished you can select an item to trigger a correct redraw of it.


After further investigation I figured out this is a general problem with OwnerDrawn-Comboboxes.
Same happens in the widgets-sample (Generic->OwnerDrawnCombobox).

On a quick try I completely removed/outcommented "wxVListBox::OnPaint" but that doesn't help. It's still draws lines in the empty box.

comment:3 Changed 5 years ago by jmsalli

Could you test if this occurs also on wxWidgets 2.8?

Also, to work around this by disabling the animation, wxComboCtrl::EnablePopupAnimation(false) would need to be called.

comment:4 Changed 4 years ago by mcben

same problem with 2.8.2 & 2.8.11
I tried to reproduce it on a VirtualMachine with no luck (same binary works fine there).
Disabling wxUSE_UXTHEME -a shot in the dark- didn't helped.
I compared the used DLL's from VM and from my system but both are completely the same.

With wxComboCtrl::EnablePopupAnimation(false) it works .. without animation of course.
But there is another problem with it (same on VM):
-> the drop-down close immediately after mouse button release.
-> So: large lists with scrollbars won't work.
maybe a topic for another ticket ;)

On the otherhand it wouldn't solve the issue in propgrid anyway.

comment:5 Changed 4 years ago by JMS

(In [64419]) In wxComboPopupExtraEventHandler::OnMouseEvent(): Also include wxEVT_LEFT_UP among the mouse events to be blocked when the cursor is outside the popup area. This fixes wxMSW bug where the popup disappears immediately after mouse button is released (see #12087).

comment:6 Changed 4 years ago by jmsalli

Ok, that issue where the popup closed immediately was a serious one since it occurred on every system which had 'Slide open combo boxes' visual option disabled. Luckily it didn't seem to be issue on wx2.8. Thanks for spotting it!

Anyways, the corrupted popup animation is probably not a theme issue as such. The animation code resides in src/msw/combo.cpp, wxComboCtrl::AnimateShow() and wxComboCtrl::DoTimerEvent(). It is done by manually resizing the window in a timer event. A better way to do it may be to use wxWindow::ShowWithEffect(), which calls actual Win32 API function AnimateWindow. However, in my brief tests this did not work properly with wxVListBox as a popup control (which is the case with wxOwnerDrawnComboBox) - the popup refuses to respond to refresh/paint until the animation has finished and remains gray. Since ShowWithEffect() seems to work when a wxTreeCtrl is a popup, all may not be lost and there probably is a way around. Still, I'd rather not spend much more time to find out what it is exactly, and unless someone has a better suggestion I will probably just disable the popup animations in both branches. After all, how big a deal can it be when application like a Firefox does not implement it ;)

Oh, and just out of curiosity, what graphics hardware do you have, mcben? Maybe something else about your system that might make it a special case? After all, the animation code has been in wxComboCtrl for years and has probably been used in numerous systems without a problem. While I haven't tested with VS2010, I doubt a compiler version is issue here (or even Windows SDK version...).

Thanks!

comment:7 Changed 4 years ago by jmsalli

FWIW, I built wx2.9 SVN trunk and the combo sample with VS2010, and still was not able to reproduce this bug.

comment:8 Changed 4 years ago by mcben

Here's workaround I will use for now:
in void wxComboCtrl::DoTimerEvent() (src/msw/combo.cpp)

Index: combo.cpp
===================================================================
--- combo.cpp	(revision 64459)
+++ combo.cpp	(working copy)
@@ -759,8 +759,8 @@
             }
             else
             {
+                win->SetSize( rect.x, rect.y, rect.width, h );
                 popup->Move( 0, -y );
-                win->SetSize( rect.x, rect.y, rect.width, h );
             }
         }
         else
@@ -774,6 +774,7 @@
         popup->Move( 0, 0 );
         m_animTimer.Stop();
         DoShowPopup( m_animRect, m_animFlags );
+        GetPopupWindow()->Refresh();
     }
 }
 #endif

Tests revealed that switching the order of "Move" and "SetSize" reduces (not eliminates!) the artifacts.
(the sample combobox with 3 item will sometimes(!) show garbage in the first ~5 lines )
Another solution is to completely remove the "Move" so artifacts can't happen..but then animation looks stupid.

The additional "Refresh" at the end ensures the final box looks correct.
So even when animation went wrong: who cares :)


As said: I tried to reproduce it on other systems too - using the same binary - without luck.

I don't have any idea what can be special on my system:

System:
OS  Microsoft Windows 7 Home Premium	
Version	6.1.7600 Build 7600	
Processor	Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz, 2400 MHz
Manufacture HP-Pavilion	/ GZ706AA-ABD m9075.de	
Locales     German
HAL	Version = "6.1.7600.16385"	
Phys. Memory (RAM)	3,00 GB (0,98 free)	
Virt. Memory        8,08 GB (5,98 free)


Graphics:
Name	NVIDIA GeForce 8600 GT	
Adapter-RAM	512,00 MB (536.870.912 Bytes)	
Driver	nvd3dum.dll,nvwgf2um.dll,nvwgf2um.dll	
Driver	c:\windows\system32\drivers\nvlddmkm.sys (8.15.11.8627, 9,32 MB (9.777.376 Bytes), 26.06.2009 22:01)	
Driver-version	8.15.11.8627	
Resolution 1280 x 1024 x 85 Hz	/ 32 Bit

if I've some time to spend I'll check some software combinations on my VM.

comment:9 Changed 4 years ago by jmsalli

  • Milestone set to 2.9.2

Many thanks for putting so much effort into this  mcben! Additional question though: in the combo sample, is it only wxOwnerDrawnComboBox which shows garbage, or also the wxComboCtrl with wxTreeCtrl popup?

Anyway, I think disabling the animation is probably the only fool proof method of eliminating garbage, aside from using ShowWithEffect(), if it can be made to work with wxVListBox. Still, even if I disable the animation, I will put example in combo sample that uses ShowWithEffect().

Need to look at this soon.

comment:10 Changed 4 years ago by jmsalli

  • Status changed from new to infoneeded_new

Ok, I think it would be best to use your patch for now, and disable animation later if someone else complains about it. Please let me know under which name would you like to be credited in docs/changes.txt, I had to use just "mcben" for now.

comment:11 Changed 4 years ago by mcben

  • Status changed from infoneeded_new to new

Sorry, I don't know which sample you meant (wxComboCtrl with wxTreeCtrl).

oh, and "mcben" is fine..in fact I don't care.
The time I put into this is just my way to say thank you to the whole wxWidget-Crew :)

comment:12 Changed 4 years ago by mcben

After thinking twice about my workaround:
The "DoShowPopup" includes a "SetSize" call. So the final animation step also includes a "Move" before "SetSize". Thats why there are artifacts left on my system (without the final "Refresh").

The addition "Refresh" can be replaced by putting the "popup->Move( 0, 0 );"
after "DoShowPopup( m_animRect, m_animFlags );"
Maybe this can save one OnPaint call.

comment:13 Changed 4 years ago by jmsalli

  • Status changed from new to infoneeded_new

Replying to mcben:

Sorry, I don't know which sample you meant (wxComboCtrl with wxTreeCtrl).

Combo sample, third row, second column, labeled "Tree Ctrl wxComboCtrl".

The "DoShowPopup" includes a "SetSize" call. So the final animation step also includes a "Move" before "SetSize". Thats why there are artifacts left on my system (without the final "Refresh"). The addition "Refresh" can be replaced by putting the "popup->Move( 0, 0 );" after "DoShowPopup( m_animRect, m_animFlags );"

Sorry, do you propose some improvements that actually futher reduce the garbage (compared to your previous patch), or is this only about eliminating the Refresh()?

Maybe this can save one OnPaint call.

It does not really matter, and besides AFAIK redundant Refresh() calls should not cause extra paint events.

comment:14 Changed 4 years ago by mcben

  • Status changed from infoneeded_new to new

hihi...by unknown reason the project wasn't in my VS-solution file .. maybe I removed it by accident :/
Checked wxTreeCtrl and works fine.

What I meant in my last post:
the real cause of the artifacts is the order: "Move" before "SetSize".
The final refresh isn't needed if made sure "Move" is called after "SetSize".
(which requires to move the "popup->Move( 0, 0 );" after "DoShowPopup( m_animRect, m_animFlags );")

I didn't investigate it deeper but it look like atleast one of these does a immediately repaint.
And this might be the reason of the/my problem.

comment:15 Changed 4 years ago by JMS

  • Resolution set to fixed
  • Status changed from new to closed

(In [64476]) Greatly reduce rare animation garbage in wxOwnerDrawnComboBox drop-down animation (fixes #12087)

comment:16 Changed 4 years ago by JMS

(In [64477]) Backported from wx2.9: Greatly reduce rare animation garbage in wxOwnerDrawnComboBox drop-down animation (see #12087)

comment:17 Changed 4 years ago by jmsalli

Can you confirm that the committed fix works?

comment:18 Changed 4 years ago by mcben

yes..looks good

(OffTopic:)
but svn-rev:64475 makes trouble on windows 'cause "near" is defined in "windef.h"
so "bool near;" won't work

Note: See TracTickets for help on using tickets.