- NSIS Discussion
- NSD_SetText Crash in Win2k
Archive: NSD_SetText Crash in Win2k
Spilly
9th April 2009 19:12 UTC
NSD_SetText Crash in Win2k
The following code has no issues in xp or vista, but crashes in 2k when NSD_SetText is called.
${NSD_CreateText} $(NSD_X) $(NSD_Y) $(NSD_WIDTH) $(NSD_HEIGHT) "$(NSD_TEXT)"
Pop $0
${NSD_OnChange} $0 clearTextBoxWhenClicked
...
Function clearTextBoxWhenClicked
Exch $0
${NSD_SetText} $0 ""
Pop $0
FunctionEnd
demiller9
9th April 2009 19:35 UTC
The EXCH $0 in clearTextBoxWhenClicked is going to pop a value from the stack, but your code snippet doesn't show that anything is on the stack. Is that why it crashes?
Animaether
9th April 2009 19:39 UTC
What happens when you manually use...
SendMessage $0 ${WM_SETTEXT} 0 `STR:`
What happens if you use a non-empty string? (i.e. instead of "" use " ")
Spilly
10th April 2009 01:05 UTC
demiller9, NSD_OnChange puts the control's HWND on the stack when the callback is called.
Animaether, I tried both suggestions and each crashed the 2k machine. If I comment out the NSD_SetText call, there's no crash at all.
Anders
10th April 2009 03:32 UTC
I'm sorry but, how is this not a loop that will never end?
Are you trying to create one of those "Search..." things that go away when you click the edit box?
Animaether
10th April 2009 04:41 UTC
... NSD_SetText triggers the OnChange function? brr. Well that might indeed explain it (although not explain why he'd only see it on 2K).
I suppose the solution is to only change the text when it needs changing;
!addplugindir "."
!addincludedir "."
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
!include "MUI2.nsh"
OutFile "test.exe"
Var dialog
Var hwnd
Var null
Page Custom CustomPage
Function CustomPage
nsDialogs::Create 1018
Pop $dialog
${NSD_CreateText} 0 0 100% 8% "Hello world"
Pop $hwnd
${NSD_OnChange} $hwnd TextChanged
${NSD_OnClick} $hwnd TextClicked
nsDialogs::Show
FunctionEnd
Function TextChanged
Pop $hwnd
MessageBox MB_OK "Text Changed"
${NSD_GetText} $hwnd $0
${Unless} $0 == "Foo"
${NSD_SetText} $hwnd "Foo"
${EndUnless}
FunctionEnd
Section
SectionEnd
!insertmacro MUI_LANGUAGE "English"
If you are indeed trying to create what Anders mentioned, you might have to track focus (as there's no OnFocus type callback yet);
!addplugindir "."
!addincludedir "."
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
!include "MUI2.nsh"
OutFile "test.exe"
Var dialog
Var hwnd
Var null
var NSD_TextField
var NSD_Focus_hwnd
Page Custom CustomPage
Function CustomPage
nsDialogs::Create 1018
Pop $dialog
${NSD_CreateText} 0 0 100% 8% "Password"
Pop $NSD_TextField
SetCtlColors $NSD_TextField 0x888888 0xffffff
${NSD_OnChange} $NSD_TextField TextChanged
${NSD_CreateTimer} FocusTimer 100
nsDialogs::Show
FunctionEnd
Function TextChanged
Pop $hwnd
; text change code here
FunctionEnd
Function FocusTimer
System::Call "user32::GetFocus(v) i.r0" ; get element with current focus in $0
${If} $0 != $NSD_Focus_hwnd
StrCpy $NSD_Focus_hwnd $0
${If} $NSD_Focus_hwnd == $NSD_TextField
${NSD_KillTimer} FocusTimer
${NSD_GetText} $NSD_TextField $0
${If} $0 == "Password"
${NSD_SetText} $NSD_TextField ""
SetCtlColors $NSD_TextField 0x000000 0xffffff
${EndIf}
${EndIf}
${EndIf}
FunctionEnd
Section
SectionEnd
!insertmacro MUI_LANGUAGE "English"
Anders
10th April 2009 06:03 UTC
actually, the edit box on XP and later has built-in support for showing those "help texts"
Animaether
10th April 2009 06:58 UTC
Originally posted by Anders
actually, the edit box on XP and later has built-in support for showing those "help texts"
Unfortunately it seems he requires 2K support.
But if you could give an example of EM_SETCUEBANNER working with the NSD_CreateText (I'm failing at it), I'd be happy to add it to the nsDialogs snippets.
( not sure if NSIS ends up using common controls v6, already used the System plugin to explicitly specify a unicode string)
Though browsing around, I see that..
- it won't work on multi-line controls
- it won't work on any XP install that has asian language support installed
The above solution - though not pretty due to the use of a timer - should work regardless and give you more control.
Anders
10th April 2009 07:44 UTC
NSD should not have a timer in the first place IMHO, it does not belong there at all, all you can do with it are hacks. There is a subclass plugin, its not pretty, but its the right tool for this job
Animaether
10th April 2009 08:20 UTC
Given three options:
- you can't do this
- you can do this, good luck figuring it out*
- use hacks
Many people would use hacks if the appropriate means are too cumbersome. If you're stuck on a roof mounting a satellite dish with a wrench and you happen to note a roof tile nail is loose, but your hammer is 2 flights down, you betcha you'll just tap that nail back in with the wrench.. no matter how inappropriate a wrench is for serious hammering purposes.
Granted, I don't use the timer very often, but even just as a post-show function (i.e. the nsDialogs::show command has been run, all code after that halts.. which means you're stuck if you want to update something on that dialog without further user interaction) it does the job just fine as a 'hack'.
*That said... the 'not pretty' plugin...
http://nsis.sourceforge.net/WndSubclass_plug-in
...does the job just fine; although I might not be using it correctly as its current state appears to be alpha (from another thread).
!addplugindir "."
!addincludedir "."
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
!include "MUI2.nsh"
!include "WndSubclass.nsh"
OutFile "test.exe"
var dialog
var hwnd
var null
Page Custom CustomPage
var NSD_TextField
var NSD_Label
var TextFieldSubProc
Function CustomPage
nsDialogs::Create 1018
Pop $dialog
${NSD_CreateText} 0 0 100% 8% "Password"
Pop $NSD_TextField
SetCtlColors $NSD_TextField 0x888888 0xffffff
${WndSubclass_Subclass} $NSD_TextField TextFieldSubProc $TextFieldSubProc $TextFieldSubProc
${NSD_CreateLabel} 0 10% 100% 8% ""
Pop $NSD_Label
nsDialogs::Show
FunctionEnd
Function TextFieldSubProc
${If} $2 = ${WM_SETFOCUS}
${NSD_GetText} $NSD_TextField $R0
${If} $R0 == "Password"
${NSD_SetText} $NSD_TextField ""
SetCtlColors $NSD_TextField 0x000000 0xffffff
${EndIf}
${ElseIf} $2 = ${WM_KILLFOCUS}
${NSD_GetText} $NSD_TextField $R0
${If} $R0 == ""
${NSD_SetText} $NSD_TextField "Password"
SetCtlColors $NSD_TextField 0x888888 0xffffff
${EndIf}
${EndIf}
FunctionEnd
Function TextChanged
Pop $hwnd
; text change code here
FunctionEnd
Section
SectionEnd
!insertmacro MUI_LANGUAGE "English"
Anders
10th April 2009 08:46 UTC
and it will ALWAYS be alpha, I'm google--
Animaether
10th April 2009 08:49 UTC
*bows to Anders*
Anyway.. uhh.. Spilly - I hope one of these resolves your problem :)
Spilly
16th April 2009 18:18 UTC
Wow, thanks for the help guys. It seemed a little too much code to add simply for win2k support, so I was going to remove this feature and add the text above the text box instead, but I found a much more simple solution.
Here it is:
Var SetTextOnce
${NSD_CreateText} $(NSD_X) $(NSD_Y) $(NSD_WIDTH) $(NSD_HEIGHT) "$(NSD_TEXT)"
Pop $0
StrCpy $SetTextOnce 0
${NSD_OnChange} $0 clearTextBoxWhenClicked
...
Function clearTextBoxWhenClicked
Exch $0
StrCmp $SetTextOnce 0 0 +3
${NSD_SetText} $0 ""
StrCpy $SetTextOnce 1
Pop $0
FunctionEnd