I found a nice example of changing the panels to use a white background. I had to tweak it a little because it was setup to use MUI.nsh instead of MUI2.nsh. I am still running into a bit of a text overlay issue on the refresh. The old text seems to accumulate rather than get blanked out and new text added. Here are the code segments I used:
!include MUI2.nsh
!include WinMessages.nsh
; Local bitmap path.
!define BITMAP_FILE white.bmp
; --------------------------------------------------------------------------------------------------
; Definitions
; --------------------------------------------------------------------------------------------------
; The following commented out definitions are due to duplicates already defined in the MUI2.nsh header
; The variable MUI_HWND has to be added because it is missing from MUI2.nsh, but present in MUI.nsh.
;!define LR_LOADFROMFILE 0x0010
;!define LR_CREATEDIBSECTION 0x2000
;!define IMAGE_BITMAP 0
;!define SS_BITMAP 0x0000000E
;!define WS_CHILD 0x40000000
;!define WS_VISIBLE 0x10000000
!define HWND_TOP 0
!define SWP_NOSIZE 0x0001
!define SWP_NOMOVE 0x0002
!define IDC_BITMAP 1500
; typedef struct _RECT {
; LONG left;
; LONG top;
; LONG right;
; LONG bottom;
; } RECT, *PRECT;
!define stRECT "(i, i, i, i) i"
Var hBitmap
Var MUI_HWND
; --------------------------------------------------------------------------------------------------
; Macros
; --------------------------------------------------------------------------------------------------
; Destroy a window.
!macro DestroyWindow HWND IDC
GetDlgItem $R0 ${HWND} ${IDC}
System::Call `user32:😁estroyWindow(i R0)`
!macroend
; Give window transparent background.
!macro SetTransparent HWND IDC
GetDlgItem $R0 ${HWND} ${IDC}
SetCtlColors $R0 0x000000 transparent
!macroend
; Refresh window.
!macro RefreshWindow HWND IDC
GetDlgItem $R0 ${HWND} ${IDC}
ShowWindow $R0 ${SW_HIDE}
ShowWindow $R0 ${SW_SHOW}
!macroend
; --------------------------------------------------------------------------------------------------
; Functions
; --------------------------------------------------------------------------------------------------
Function MyGUIInit
; Extract bitmap image.
InitPluginsDir
ReserveFile `${BITMAP_FILE}`
File `/ONAME=$PLUGINSDIR\bg.bmp` `${BITMAP_FILE}`
; Get the size of the window.
System::Call `*${stRECT} .R0`
System::Call `user32::GetClientRect(i $HWNDPARENT, i R0)`
System::Call `*$R0${stRECT} (, , .R1, .R2)`
System::Free $R0
; Create bitmap control.
System::Call `kernel32::GetModuleHandle(i 0) i.R3`
System::Call `user32::CreateWindowEx(i 0, t "STATIC", t "", i ${SS_BITMAP}|${WS_CHILD}|${WS_VISIBLE}, i 0, i 0, i R1, i R2, i $HWNDPARENT, i ${IDC_BITMAP}, i R3, i 0) i.R1`
System::Call `user32::SetWindowPos(i R1, i ${HWND_TOP}, i 0, i 0, i 0, i 0, i ${SWP_NOSIZE}|${SWP_NOMOVE})`
; Set the bitmap.
System::Call `user32::LoadImage(i 0, t "$PLUGINSDIR\bg.bmp", i ${IMAGE_BITMAP}, i 0, i 0, i ${LR_CREATEDIBSECTION}|${LR_LOADFROMFILE}) i.s`
Pop $hBitmap
SendMessage $R1 ${STM_SETIMAGE} ${IMAGE_BITMAP} $hBitmap
; Set transparent backgrounds.
!insertmacro SetTransparent $HWNDPARENT 3
!insertmacro SetTransparent $HWNDPARENT 1
!insertmacro SetTransparent $HWNDPARENT 2
!insertmacro SetTransparent $HWNDPARENT 1034
!insertmacro SetTransparent $HWNDPARENT 1037
!insertmacro SetTransparent $HWNDPARENT 1038
; Remove unwanted controls.
!insertmacro DestroyWindow $HWNDPARENT 1256
!insertmacro DestroyWindow $HWNDPARENT 1028
!insertmacro DestroyWindow $HWNDPARENT 1039
FunctionEnd
; Refresh parent window controls.
; Has to be done for some controls if they have a
; transparent background.
Function RefreshParentControls
!insertmacro RefreshWindow $HWNDPARENT 1037
!insertmacro RefreshWindow $HWNDPARENT 1038
FunctionEnd
; For directory page.
Function DirectoryPageShow
; Set transparent backgrounds.
FindWindow $MUI_HWND "#32770" "" $HWNDPARENT
SetCtlColors $MUI_HWND 0x000000 transparent
!insertmacro SetTransparent $MUI_HWND 1019
!insertmacro SetTransparent $MUI_HWND 1001
!insertmacro SetTransparent $MUI_HWND 1024
!insertmacro SetTransparent $MUI_HWND 1008
!insertmacro SetTransparent $MUI_HWND 1023
!insertmacro SetTransparent $MUI_HWND 1006
!insertmacro SetTransparent $MUI_HWND 1020
; Remove group box text. $R0 still contains HWND of 1020 🙂
SendMessage $R0 ${WM_SETTEXT} 0 STR:
; Refresh controls.
Call RefreshParentControls
FunctionEnd
; For components page.
Function ComponentsPageShow
; Set transparent backgrounds.
FindWindow $MUI_HWND "#32770" "" $HWNDPARENT
SetCtlColors $MUI_HWND 0x000000 transparent
!insertmacro SetTransparent $MUI_HWND 1017
!insertmacro SetTransparent $MUI_HWND 1022
!insertmacro SetTransparent $MUI_HWND 1021
!insertmacro SetTransparent $MUI_HWND 1023
!insertmacro SetTransparent $MUI_HWND 1006
!insertmacro SetTransparent $MUI_HWND 1032
!insertmacro SetTransparent $MUI_HWND 1043
; Refresh controls.
Call RefreshParentControls
FunctionEnd
; For instfiles page.
Function InstFilesPageShow
; Set transparent backgrounds.
FindWindow $MUI_HWND "#32770" "" $HWNDPARENT
SetCtlColors $MUI_HWND 0x000000 transparent
!insertmacro SetTransparent $MUI_HWND 1027
!insertmacro SetTransparent $MUI_HWND 1004
!insertmacro SetTransparent $MUI_HWND 1006
!insertmacro SetTransparent $MUI_HWND 1016
; Refresh controls.
Call RefreshParentControls
FunctionEnd
; For finish page.
Function FinishPageShow
; Set transparent backgrounds.
SetCtlColors $MUI_HWND 0x000000 transparent
!insertmacro SetTransparent $MUI_HWND 1200
!insertmacro SetTransparent $MUI_HWND 1201
!insertmacro SetTransparent $MUI_HWND 1202
!insertmacro SetTransparent $MUI_HWND 1203
!insertmacro SetTransparent $MUI_HWND 1204
!insertmacro SetTransparent $MUI_HWND 1205
!insertmacro SetTransparent $MUI_HWND 1206
FunctionEnd
; Free loaded resources.
Function .onGUIEnd
; Destroy the bitmap.
System::Call `gdi32:😁eleteObject(i s)` $hBitmap
FunctionEnd
Changing to use white background refresh tweak needed
6 posts
What if you move SetCtlColors $MUI_HWND 0x000000 transparent after the other calls?
Anyway, we don't have a complete code sample here so it is hard to test.
Anyway, we don't have a complete code sample here so it is hard to test.
On the components page, I think my issue is that nothing has been added to Function .onSelChange yet which is changing the component description based on where the mouse is on the panel. It looks like something also needs to be done to some manual changes I did on the install progress panel as well. What I basically need to do is white out the previous black text before I write out the new black text so it doesn't just keep accumulating.
I resolved the text overlay issues by taking away transparency from those components that have changing text. The original background color comes back in the description box, but that is better than overlaying text. Also had to do that for components on the install progress panel as well. As far as Anders comment about complete code, all you have to do is drop in the script above as any header you like (wbg.nsh) and include it in any install sample code you like. You do have to add the MUI references to the show components you want but that's about it.
I was able to come up with a workaround for the component description:
!define BITMAP_FILE "c:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Samples\VC#\Windows CE\RomanLegion\Images\WCEBackground.bmp" ; A big bitmap
...
OutFile "$%temp%\Test.exe"
RequestExecutionLevel user
Section "Foo" S1
SectionEnd
Section "Bar" S2
SectionEnd
!define MUI_CUSTOMFUNCTION_ONMOUSEOVERSECTION MyMouseOverSection
!define MUI_CUSTOMFUNCTION_GUIINIT MyGUIInit
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComponentsPageShow
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_SHOW DirectoryPageShow
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_SHOW InstFilesPageShow
!insertmacro MUI_PAGE_INSTFILES
!define MUI_PAGE_CUSTOMFUNCTION_SHOW FinishPageShow
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${S1} "FOOOOOOOOOOO!_!"
!insertmacro MUI_DESCRIPTION_TEXT ${S2} "bar bar bar"
!insertmacro MUI_FUNCTION_DESCRIPTION_END
!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 MyMouseOverSection
; Force a bitmap repaint of the rectangle under $mui.ComponentsPage.DescriptionText (Redrawing everything causes a lot of flickering)
System::Call '*(i,i,i,i)i.r2'
System::Call 'USER32::GetWindowRect(i$mui.ComponentsPage.DescriptionText,ir2)'
System::Call 'USER32::MapWindowPoints(i0,i$HWNDPARENT,ir2,i2)'
System::Call "user32::RedrawWindow(i,i,i,i)($HWNDPARENT, r2, 0, ${RDW_INVALIDATE}|${RDW_INTERNALPAINT})"
System::Free $2
FunctionEnd Thanks for the work around Anders. This will certainly be of value to someone needing to use an image background with transparent components. I am getting away with using opaque because the image and the opaque background are both white.