Correct way to redraw a label?
Alright, back to that old topic...
There's the camp of ShowWindow hide/show (flicker), so a more correct way would be invalidaterect or redrawwindow.
I've been using invalidaterect in a ${RedrawControl} macro with apparent success for some time now, but now I ran into a problem with it.
Basically I've got a GroupBox on which I place a Label. Why do I do that? Because I can't change the color of the text in a GroupBox - it's always happily blue.
Of course that does bring other issues with it - such as Windows' UI drawing being.. suboptimal. Suffice to say that there's several situation in which you might end up having the groupbox's label (a long string of spaces so as not to cut through the label control) being on top of the label control.
Despite the fact that the groupbox should have a transparent background, that now-underlying label control does not show through.
So, I have to redraw that label control either periodically, or based on some event, or whatever.
Now to the meat of this post.. I can't seem to redraw that label control properly with InvalidateRect or RedrawWindow. As soon as I redraw the control, it essentially paints on top of itself. That sounds like it's not so bad, until you're using font Smoothing or ClearType; the smoothing effect composites on top of itself, making the text look increasingly bold.. and increasingly jaggy.
So below is a test script to play with...
!addplugindir "."
!addincludedir "."
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
!include "MUI2.nsh"
OutFile "test.exe"
var dialog
var hwnd
var null
var text
var button.showhide
var button.invalidaterect
var button.redrawwindow
Page custom test
Function test
nsDialogs::Create 1018
Pop $dialog
/*
${NSD_CreateGroupBox} 0 0 100% 12% "This is a test"
Pop $hwnd
SetCtlColors $hwnd 0xFF0000 transparent ; This doesn't work.
*/
${NSD_CreateLabel} 0 0 100% 6% "This is a test"
Pop $text
${NSD_CreateButton} 0 15% 30% 10% "&Show/Hide"
Pop $button.showhide
${NSD_OnClick} $button.showhide button.showhide.onclick
${NSD_CreateButton} 0 30% 30% 10% "&InvalidateRect"
Pop $button.invalidaterect
${NSD_OnClick} $button.invalidaterect button.invalidaterect.onclick
${NSD_CreateButton} 0 45% 30% 10% "&RedrawWindow"
Pop $button.redrawwindow
${NSD_OnClick} $button.redrawwindow button.redrawwindow.onclick
nsDialogs::Show
FunctionEnd
Function button.showhide.onclick
Pop $hwnd
ShowWindow $text ${SW_HIDE}
SetCtlColors $text 0x008000 transparent
ShowWindow $text ${SW_SHOW}
FunctionEnd
Function button.invalidaterect.onclick
Pop $hwnd
SetCtlColors $text 0x800000 transparent
System::Call "user32::InvalidateRect(i,i,i)i ($text, 0, 1)"
FunctionEnd
!ifndef RDW_INVALIDATE
!define RDW_INVALIDATE 0x0001
!define RDW_INTERNALPAINT 0x0002
!define RDW_ERASE 0x0004
!define RDW_VALIDATE 0x0008
!define RDW_NOINTERNALPAINT 0x0010
!define RDW_NOERASE 0x0020
!define RDW_NOCHILDREN 0x0040
!define RDW_ALLCHILDREN 0x0080
!define RDW_UPDATENOW 0x0100
!define RDW_ERASENOW 0x0200
!define RDW_FRAME 0x0400
!define RDW_NOFRAME 0x0800
!endif
Function button.redrawwindow.onclick
Pop $hwnd
SetCtlColors $text 0x000080 transparent
System::Call "user32::RedrawWindow(i,i,i,i)i ($text, 0, 0, ${RDW_INVALIDATE}|${RDW_ERASE}|${RDW_UPDATENOW})"
FunctionEnd
Section
SectionEnd
!insertmacro MUI_LANGUAGE "English"
I've hotkeyed the buttons, so just press e.g. Alt+S to use the show/hide method (flickers), and Alt+I for InvalidateRect (font smoothing issue), Alt+R for RedrawWindow (font smoothing issue).
I'm probably going to have to just drop the groupboxes (faking them about with bitmaps isn't exactly appealing either, as you might imagine) which would circumvent the problem in the first place.
But I'm still curious as to what the correct way to redraw a label should be. I've always had problems like SetCtlColors not working immediately, not even after an InvalidateRect (I guess because the next paint message gets 'halted' until the script finishes sometimes), but also always have been able to work around it.. but this one's got me baffled.
If this is just a bug in Windows and the only -real- way to redraw a control effectively is the ShowWindow method, then is there some way to prevent the flicker from it?