I'm trying to respond to clicks on a listbox. Here's the setup:
nsDialogs::Create /NOUNLOAD 1018
Pop $ListBoxPage
${NSD_CreateListBox} 0 20 100% 80% "Backup folders"
Pop $ListBox
Call PopulateListBox
${NSD_OnNotify} $ListBox ListClicked
nsDialogs::Show
The list box is getting populated, but ListClicked is never getting called.
What am I missing?
having trouble with NSD_OnNotify with ListBox
5 posts
Not every notification works for every control. OnNotify hooks WM_NOTIFY and a listbox does not use that message IIRC
Thanks, Anders, for your reply.
Yes, indeed, listboxes neither generate nor receive WM_NOTIFY messages for selection changes. I had been encouraged by another thread (http://forums.winamp.com/showthread....ght=lbs_notify) mentioning LBS_NOTIFY, but that poster was looking for OnChange notifications.
The MSDN dox say that the list box's *parent* ($ListBoxPage in my example) receives selection change notifications and I've verified with Spy++ that, in fact, this notification is in the form of a WM_COMMAND message with a wNotifyCode (HIWORD of wParam) of LBN_SELCHANGE.
So it looks like I need to subclass $ListBoxPage. I've found WndSubclass - http://nsis.sourceforge.net/WndSubclass_plug-in (yours, Anders?), which looks like it might do the trick. If so, I'll post the results. If not, I'll probably ask for more help...
Yes, indeed, listboxes neither generate nor receive WM_NOTIFY messages for selection changes. I had been encouraged by another thread (http://forums.winamp.com/showthread....ght=lbs_notify) mentioning LBS_NOTIFY, but that poster was looking for OnChange notifications.
The MSDN dox say that the list box's *parent* ($ListBoxPage in my example) receives selection change notifications and I've verified with Spy++ that, in fact, this notification is in the form of a WM_COMMAND message with a wNotifyCode (HIWORD of wParam) of LBN_SELCHANGE.
So it looks like I need to subclass $ListBoxPage. I've found WndSubclass - http://nsis.sourceforge.net/WndSubclass_plug-in (yours, Anders?), which looks like it might do the trick. If so, I'll post the results. If not, I'll probably ask for more help...
Thanks to WndSubclass, here's a working example :
Page custom ListBoxDialogPage
OutFile ListBoxTest.exe
Section "Empty section"
SectionEnd
!include LogicLib.nsh
!include NsDialogs.nsh
!include WinMessages.nsh
!include WndSubclass.nsh
var ListBox
var ListBoxPage
!define __NSD_ListBoxMulti_CLASS LISTBOX
!define __NSD_ListBoxMulti_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${WS_VSCROLL}|${LBS_EXTENDEDSEL}|${LBS_HASSTRINGS}|${LBS_NOTIFY}
!define __NSD_ListBoxMulti_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
!insertmacro __NSD_DefineControl ListBoxMulti
Function PopulateListBox
SendMessage $ListBox ${LB_ADDSTRING} 0 "STR:Abel"
SendMessage $ListBox ${LB_ADDSTRING} 0 "STR:Baker"
SendMessage $ListBox ${LB_ADDSTRING} 0 "STR:Charlie"
FunctionEnd
Function ListClicked
SendMessage $ListBox ${LB_GETCURSEL} 0 0 $0
MessageBox MB_OK "Cursel: $0"
FunctionEnd
Var CommandCaptureVar
!define LBN_SELCHANGE 1
Function CommandCapture
${If} $2 = ${WM_COMMAND}
Var /Global HiWord
IntOp $HiWord $3 >> 16
IntOp $HiWord $HiWord & 0xff
${If} $HiWord = ${LBN_SELCHANGE}
Call ListClicked
${EndIf}
${EndIf}
FunctionEnd
Function ListBoxDialogPage
nsDialogs::Create /NOUNLOAD 1018
Pop $ListBoxPage
${NSD_CreateListBoxMulti} 0 20 100% 80% ""
Pop $ListBox
Call PopulateListBox
${WndSubclass_Subclass} $ListBoxPage CommandCapture $CommandCaptureVar $CommandCaptureVar
nsDialogs::Show
FunctionEnd
Old Thread, but much useful
I have done a lot of research in the forums, and got portions of code at this thread that may help to solve a lot of problem with those using listbox control and wanting real time notifications.
The DrBonzo´s solution works, but rely´s on the handle of listbox on called on function ''ListClicked'' because it is abstracted that will exist only one listbox on the dialog, so, I understand that this solution only works with a single listbox.
My purpose is to get the handle of active listbox and get current selection of that listbox.
This is the approach, works fine, here's the code for that, adapted from code from DrBonzo.
Note that WndSubclass receive the $Listbox handle instead of dialog's handle, and this handle is passed to a function by WndSubclass at $1.
I have done a lot of research in the forums, and got portions of code at this thread that may help to solve a lot of problem with those using listbox control and wanting real time notifications.
The DrBonzo´s solution works, but rely´s on the handle of listbox on called on function ''ListClicked'' because it is abstracted that will exist only one listbox on the dialog, so, I understand that this solution only works with a single listbox.
My purpose is to get the handle of active listbox and get current selection of that listbox.
This is the approach, works fine, here's the code for that, adapted from code from DrBonzo.
Note that WndSubclass receive the $Listbox handle instead of dialog's handle, and this handle is passed to a function by WndSubclass at $1.
Page custom ListBoxDialogPage
OutFile ListBoxTest.exe
Section "Empty section"
SectionEnd
!include LogicLib.nsh
!include NsDialogs.nsh
!include WinMessages.nsh
!include WndSubclass.nsh
var ListBoxPage
Var hCtl_JANELA_ListBox1
Var hCtl_JANELA_ListBox2
!define __NSD_ListBoxMulti_CLASS LISTBOX
!define __NSD_ListBoxMulti_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${WS_VSCROLL}|${LBS_EXTENDEDSEL}|${LBS_HASSTRINGS}|${LBS_NOTIFY}
!define __NSD_ListBoxMulti_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
!insertmacro __NSD_DefineControl ListBoxMulti
Function PopulateListBox
SendMessage $hCtl_JANELA_ListBox2 ${LB_ADDSTRING} 0 "STR:Abel"
SendMessage $hCtl_JANELA_ListBox2 ${LB_ADDSTRING} 0 "STR:Baker"
SendMessage $hCtl_JANELA_ListBox2 ${LB_ADDSTRING} 0 "STR:Charlie"
SendMessage $hCtl_JANELA_ListBox1 ${LB_ADDSTRING} 0 "STR:Abel"
SendMessage $hCtl_JANELA_ListBox1 ${LB_ADDSTRING} 0 "STR:Baker"
SendMessage $hCtl_JANELA_ListBox1 ${LB_ADDSTRING} 0 "STR:Charlie"
FunctionEnd
Function ListClicked
SendMessage $1 ${LB_GETCURSEL} 0 0 $0
MessageBox MB_OK "Cursel: $0"
FunctionEnd
Var CommandCaptureVar
Function CommandCapture
${If} $2 = ${WM_LBUTTONUP}
Call ListClicked
${EndIf}
FunctionEnd
Function ListBoxDialogPage
nsDialogs::Create /NOUNLOAD 1018
Pop $ListBoxPage
; === ListBox1 (type: ListBox) ===
${NSD_CreateListBox} 32u 32u 79u 53u ""
Pop $hCtl_JANELA_ListBox1
; === ListBox2 (type: ListBox) ===
${NSD_CreateListBox} 152u 32u 79u 53u ""
Pop $hCtl_JANELA_ListBox2
Call PopulateListBox
${WndSubclass_Subclass} $hCtl_JANELA_ListBox1 CommandCapture $CommandCaptureVar $CommandCaptureVar
${WndSubclass_Subclass} $hCtl_JANELA_ListBox2 CommandCapture $CommandCaptureVar $CommandCaptureVar
nsDialogs::Show
FunctionEnd Hope This Helps anyone.