Archive: NSD_SetText Crash in Win2k


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


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?


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 " ")

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.


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?


... 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"

actually, the edit box on XP and later has built-in support for showing those "help texts"


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.

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


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"

and it will ALWAYS be alpha, I'm google--


*bows to Anders*

Anyway.. uhh.. Spilly - I hope one of these resolves your problem :)


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