Archive: MUI_PAGE_DIRECTORY Read Only


MUI_PAGE_DIRECTORY Read Only
Hi all,

i am trying to get the MUI_PAGE_DIRECTORY Page to display the path "greyed out/read only" when it finds the Path Variable for that setup already set in the Registry.

I am using !define MUI_PAGE_CUSTOMFUNCTION_PRE "PRE_PAGE_DIRECTORY" to determine the path and according to what it finds out would like to make the directory page read only.

Any ideas how i could do that?

Thanks
xBarns


From the MUI2 readme:

In the show function, the window handles of all controls on the page can be retrieved from a Modern UI variable. A list of the variables names is not yet available. For now, refer to the source files of the Modern UI 2.0. The variable declarations can be found in the first lines of the header file for a certain page.
Find the HWND variable from the MUI2 DIRECTORY page header (NSIS\Contrib\Modern UI 2\Pages\Directory.nsh), then in the page's show function use enablewindow to disable the path control and browse button.

http://nsis.sourceforge.net/Docs/Chapter4.html#4.9.14.4

I did actually read that but did not recognize it to be the solution to my problem.

For those interested here is how it works.


!define MUI_PAGE_CUSTOMFUNCTION_PRE "PRE_PAGE_DIRECTORY"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW "SHOW_PAGE_DIRECTORY"
!insertmacro MUI_PAGE_DIRECTORY

Function PRE_PAGE_DIRECTORY
Var /GLOBAL DISABLEDIRECTOY
ReadRegStr $0 HKLM "${REGKEY}" Path
${IF} $0 != ''
StrCpy $DISABLEDIRECTOY 1
${ANDIF} $0 != $INSTDIR
StrCpy $INSTDIR $0
${ENDIF}
FunctionEnd

Function SHOW_PAGE_DIRECTORY
${IF} $DISABLEDIRECTOY == 1
EnableWindow $mui.DirectoryPage.Directory 0
EnableWindow $mui.DirectoryPage.BrowseButton 0
${ENDIF}
FunctionEnd

I'm trying to do the same thing and have to say your timing was perfect. Thanks for the code. But, when I implemented it, the path was not grayed out.

What I did was create a .nsh file called DetectDir.nsh containing the code you provided (with appropriate tweaks) and replaced my .nsi's !insertmacro MUI_PAGE_DIRECTORY statement with !insert DetectDir.nsh

The code executes as I would expect - to prove it, I put a MessageBox under the line
${IF} $DISABLEDIRECTORY == 1
so the EnableWindow statements are executed. Yet the directory field is still active. What am I missing?


uh,

i have no idea if

What I did was create a .nsh file called DetectDir.nsh containing the code you provided (with appropriate tweaks) and replaced my .nsi's !insertmacro MUI_PAGE_DIRECTORY statement with !insert DetectDir.nsh
is the right way to do such a thing, what prevents you from doing it the way i did it?

I'm not sure what you're asking. The only thing I did was create a .nsh file containing your code with one line modified:

ReadRegStr $0 HKLM "SOFTWARE\myCompany\myProduct" "aKeyWithPathInfo"

I made this a .nsh file for now because my .nsi file is fairly large and this helped me isolate your code so I could study it more easily in action.

Running this I learned that $0 got loaded with the value of Path. All the logic works. It's just that the directory entry isn't disabled by the EnableWindow statements.


I think you have to keep

!insertmacro MUI_PAGE_DIRECTORY

because if not the page will never be shown, or do you have the "!insertmacro MUI_PAGE_DIRECTORY" in your .nsh file?

You can "export" the code to an .nsh file (the 2 functions) but you need to keep this:

!define MUI_PAGE_CUSTOMFUNCTION_PRE "PRE_PAGE_DIRECTORY"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW "SHOW_PAGE_DIRECTORY"
!insertmacro MUI_PAGE_DIRECTORY


Or am i not getting something here?


I hope this isn't a double post. My browser keeps messing up my text. Anyway, thanks for taking the time to help me with this.

MyFile.nsh file contains this:

!define MUI_PAGE_CUSTOMFUNCTION_PRE "PRE_PAGE_DIRECTORY"
!define MUI_PAGE_CUSTOMFUNCTION_SHOW "SHOW_PAGE_DIRECTORY"
!insertmacro MUI_PAGE_DIRECTORY

Function PRE_PAGE_DIRECTORY
Var /GLOBAL DISABLEDIRECTORY
ReadRegStr $0 HKLM "SOFTWARE\myCompany\myProduct" "PathToExe"
${IF} $0 != ''
StrCpy $DISABLEDIRECTORY 1
${ANDIF} $0 != $INSTDIR
StrCpy $INSTDIR $0
${ENDIF}

FunctionEnd

Function SHOW_PAGE_DIRECTORY
${IF} $DISABLEDIRECTORY == 1
EnableWindow $mui.DirectoryPage.Directory 0
EnableWindow $mui.DirectoryPage.BrowseButton 0
${ENDIF}
FunctionEnd

I commented out !insertmacro MUI_PAGE_DIRECTORY in the .nsi file and added !include myFile.nsh.

When I run the code even without calling the two above functions from a section they still get invoked, due to the PRE prefix I figure. In any event, the directory page shows up with the path still editable.


Here's some relevant info. Looking at the log generated from the above code, I see this:

Function: "SHOW_PAGE_DIRECTORY"
!insertmacro: _If
!insertmacro: end of _If

warning: unknown variable/constant "mui.DirectoryPage.Directory" detected, ignoring (MyFile.nsh:23)
EnableWindow: handle=$mui.DirectoryPage.Directory enable=0

warning: unknown variable/constant "mui.DirectoryPage.BrowseButton" detected, ignoring (MyFile.nsh:24)
EnableWindow: handle=$mui.DirectoryPage.BrowseButton enable=0

!insertmacro: _EndIf
!insertmacro: end of _EndIf
FunctionEnd

For some reason the compiler doesn't see the Directory or BrowseButton.

Directory.nsh has this:

!macro MUI_FUNCTION_DIRECTORYPAGE PRE SHOW LEAVE
--snip--
Function "${SHOW}"
;Get control handles
FindWindow $mui.DirectoryPage "#32770" "" $HWNDPARENT
GetDlgItem $mui.DirectoryPage.Text $mui.DirectoryPage 1006
GetDlgItem $mui.DirectoryPage.DirectoryBox $mui.DirectoryPage 1020
GetDlgItem $mui.DirectoryPage.Directory $mui.DirectoryPage 1019
GetDlgItem $mui.DirectoryPage.BrowseButton $mui.DirectoryPage 1001

--snip--
!insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
FunctionEnd
--snip--
!macroend


You should not remove the page defines from your .nsi file. Remove them from the nsh and put them back in your real script, together with the other page commands/defines.


Why would that make a difference? Aren't .nsh files simply in-lined? Anyway, I went ahead and copied all of the .nsh code into the .nsi. I get the same result. The telling symptom is the complier warnings:

unknown variable/constant "mui.DirectoryPage.Directory" detected, ignoring (myFile.nsi:162)
unknown variable/constant "mui.DirectoryPage.BrowseButton" detected, ignoring (myFile.nsi:163)

Any idea why they are undefined?


Originally posted by abcdgoldfish
[B]Why would that make a difference? Aren't .nsh files simply in-lined?
They are, but on this end there's no way to know whether or not you include the nsh at the proper place. And since the order of page defines also determines the order of pages...

Anyway, are you sure you're including mui2.nsh, and not mui.nsh?

Here is a snippet of my code:

!include MUI2.nsh
!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\main_left.bmp"
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\myIcon.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\myUninstall.ico"
!define MUI_WELCOMEPAGE_TITLE_3LINES
!insertmacro MUI_PAGE_WELCOME
!define MUI_LICENSEPAGE_CHECKBOX
!insertmacro MUI_PAGE_LICENSE "my_eula.rtf"

; This is the macro I replace with the above code either directly or with the !include myFile.nsh.
;!insertmacro MUI_PAGE_DIRECTORY

In one experiment, I tried including MUI.nsh In another I included neither MUI.nsh nor MUI2.nsh. In all three cases I got the same result, which is very surprising.


Okay, I found it. I had a myCode.nsi fiel and a myCode.nsh file. My build script was using the wrong file which indeed was calling !include MUI.nsh, not MUI2.nsh. When I call the right script it works as desired.

Thanks for your help and patience.