- NSIS Discussion
- Dynamically changing the text of labels with transparent Bg
Archive: Dynamically changing the text of labels with transparent Bg
aerDNA
27th May 2010 16:26 UTC
Dynamically changing the text of labels with transparent Bg
I need to change some labels on a custom page, based on user input. That normally wouldn't be a problem but I changed the labels' colors, with Bgcolor set to transparent, and so when I change a label, the old text remains and overlaps with the new one. I could use a solid Bgcolor but it looks crappy. I could also recolor the whole dialog and all the controls but I was hoping for a more elegant solution.
My real problem is that SetCtlColors doesn't accept variables. If it did, I could get the dialog Bgcolor at runtime and use that instead of transparent (I already coded that part before I remembered I can't use it).
Any possible workarounds? It's not like it would kill me to use the default font color but I'd like to know. If there's no relatively simple solution, don't bother because it's not worth it.
Afrow UK
27th May 2010 17:53 UTC
This has been discussed before. One possible simple solution is to hide and show the window with ShowWindow but for some reason it does not work in all cases.
Stu
Animaether
27th May 2010 17:58 UTC
Here's the code I use which I haven't seen failing yet.. but it's far from ideal.
!macro RedrawControl control
Push $0
StrCpy $0 ${control}
EnableWindow $0 0
System::Call "user32::InvalidateRect(i,i,i)i (r0, 0, 1)"
EnableWindow $0 1
Pop $0
!macroend
!define RedrawControl `!insertmacro RedrawControl`
There's a use example in this post:
http://forums.winamp.com/showthread.php?p=2499582
Afrow UK
27th May 2010 18:00 UTC
Why is the first EnableWindow before the StrCpy and not after?
Stu
Animaether
27th May 2010 18:40 UTC
because I fail at plucking the code out and pasting it into posts ;)
( to answer the question.. the code I had pasted is not even wrong )
Edit: and to answer a potential follow-up question of 'why are you using EnableWindow in the first place'; can't find the check-in notes after moving from CVS to SVN, but it was probably because of some redraw issue.
aerDNA
27th May 2010 20:28 UTC
Thanks, InvalidateRect does the job. Only it doesn't work when I pass hwnd of a single control, I have to redraw the whole dialog (which is also fine).
aerDNA
28th May 2010 10:46 UTC
I would still appreciate any tips on how to replace SetCtlColors with api calls. If I could use variables, I could finally get around that win theming issue and change the color of chkboxes and other controls that turn black when Bg is set to transparent, black was never transparent enough for my standards.
Afrow UK
28th May 2010 16:03 UTC
Today is your lucky day :)
http://nsis.sourceforge.net/SetCtlColors_with_variables
Stu
aerDNA
28th May 2010 16:57 UTC
Thank you!
:up: :up: :up: :up: :up:
aerDNA
28th May 2010 19:25 UTC
Tested and works like a charm. Thank you so much!
I'd like to contribute my code for retrieving the dialog Bgcolor, for usage with your function:
System::Call "user32::GetSysColor(i 15) i. R0"
IntFmt $R0 "%06X" $R0
StrCpy $1 $R0 2 4
StrCpy $0 $R0 2 2
StrCpy $1 $1$0
StrCpy $0 $R0 2
StrCpy $DlgBgColor "0x$1$0"
...
${SetCtlColors} $HWND_Ctl_x ${FgColor} $DlgBgColor $Memory_Ctl_x
This code will fail aesthetically in case the user decides to change the theme while the page is shown, but the chances of that happening are small enough.
Afrow UK
28th May 2010 19:37 UTC
You don't need to convert the return value from GetSysColor to hexadecimal. The first IntOp in the SetCtlColors function converts it to an integer anyway (before it is converted to BBGGRR). In other words, this function accepts integer or hexadecimal colour values.
Edit: And just to be sure for anyone who uses the code; $Memory_Ctl_x must be freed on installer close:
Function .onGUIEnd
System::Free $Memory_Ctl_x
FunctionEnd
Stu
aerDNA
29th May 2010 00:58 UTC
I realized I still can't recolor checkboxes. Bg doesn't turn black anymore but the text color is always stuck to default (when I first tested, all controls were set to a dark color so I didn't notice the difference). Disabling theming seems to be the only working solution again, but instead of using XPStyle Off, I learned how to disable it for a a specific control (also courtesy of Afrow UK):
System::Call "uxtheme::SetWindowTheme(i$HWND,w' ',w' ')"
And the custom SetCtlColors wasn't coded in vain, it solves the issue for which I started this thread. It beats the InvalidateRect method because the dialog is not redrawn so there's no flickering.
Afrow UK
29th May 2010 09:18 UTC
Good job. Your other option would be to use a static text (label) next to the check box and assign an onclick to it. This way is simpler though (even if the theme is gone). These kind of macros could be included in nsDialogs.nsh, except the annoyance with SetCtColors having to free the allocated memory yourself. Will see what kichik thinks.
Stu