Page 1 of 2

API Question. #CBN_SELCHANGE and #EN_CHANGE handling

Posted: Sun Jan 01, 2006 11:47 am
by Fangbeast
I have a callback working on a ListIconGadget with a hidden combobox and a hidden stringgadget.

The combobox detection and change (The #CBN_SELCHANGE section) works fine as it should. Master srod designed it:):)

I've added the stringgadget and it sort of works. The #EN_CHANGE is being detected and the stringbox activated but it closes immediately after one character.

I suspect this is because I don't understand what (wParam >> 16) & $ffff does and I have the #EN_CHANGE in the wrong place but I frankly (even Georgely!!) don't understand this bit of code so cannot fix it.

Anyone have any ideas please?

Code: Select all

Procedure.l ListIconECallBack(hWnd, uMsg, wParam, lParam)  ; The following callback allows a listicon control to be subclassed.
  Protected Result
  Select uMsg
    Case #WM_COMMAND                ; This is how the CBN_SELCHANGE message is sent.
      Select (wParam >> 16) & $ffff ; This contains the notification code.
        ;-----------------------------------------------------------------
        Case #CBN_SELCHANGE
          MapItem.l = GetGadgetState(#Gadget_exportaddress_mapbox)
          NewText.s = GetGadgetItemText(#Gadget_exportaddress_mapbox, MapItem.l, 0)
          SetGadgetItemText(#Gadget_exportaddress_tables, GetGadgetState(#Gadget_exportaddress_tables), NewText, 1)
          If Newtext.s <> "-Empty-"
            SetGadgetItemText(#Gadget_exportaddress_tables, GetGadgetState(#Gadget_exportaddress_tables), Str(MapItem.l + 1), 2)
          EndIf
          HideGadget(#Gadget_exportaddress_mapbox, 1)
          ;---------------------------------------------------------------
        Case #EN_CHANGE
          NewText.s = GetGadgetText(#Gadget_exportaddress_stringbox)       ; Get the text from the string box
          SetGadgetItemText(#Gadget_exportaddress_tables, GetGadgetState(#Gadget_exportaddress_tables), NewText, 0)
          HideGadget(#Gadget_exportaddress_stringbox, 1)                   ; Hide the gadget again
          ;---------------------------------------------------------------
      EndSelect
  EndSelect
  Result = CallWindowProc_(OldListEProc, hWnd, uMsg, wParam, lParam)
  ProcedureReturn Result
EndProcedure

Posted: Sun Jan 01, 2006 11:28 pm
by srod
I suspect this is because I don't understand what (wParam >> 16) & $ffff does and I have the #EN_CHANGE in the wrong place but I frankly (even Georgely!!) don't understand this bit of code so cannot fix it.
Fangs, the #WM_COMMAND message is sent to the parent window of the relevant control, in this case the parent of the String Gadget which is the ListIcon; so everything looks fine. When the #WM_COMMAND message fires, it places the code for the particular notification in the high order word of the wParam parameter, i.e. in the last 16 bits. To get at this code, we first shift these 16 bits into the low order word (by using wParam >>16) and then to extract these 16 bits, perform a bitwise AND with the binary number %1111111111111111 (or $ffff in hexadecimal). We can then test this code for #CBN_SELCHANGE or #EN_CHANGE etc.

As for your string gadget closing, your code suggests that it is simply being hidden. The #EN_CHANGE message fires whenever the string gadget thinks that the user has changed the contents. This means that whenever a key is pressed, the message fires. Thus, because of the command HideGadget(#Gadget_exportaddress_stringbox, 1), your string gadget is being hidden after every key press!

Hope this helps.

Ouch!

Posted: Sun Jan 01, 2006 11:43 pm
by Fangbeast
"Fangs, the #WM_COMMAND message is sent to the parent window of the relevant control, in this case the parent of the String Gadget which is the ListIcon; so everything looks fine. When the #WM_COMMAND message fires, it places the code for the particular notification in the high order word of the wParam parameter, i.e. in the last 16 bits. To get at this code, we first shift these 16 bits into the low order word (by using wParam >>16) and then to extract these 16 bits, perform a bitwise AND with the binary number %1111111111111111 (or $ffff in hexadecimal). We can then test this code for #CBN_SELCHANGE or #EN_CHANGE etc."

I didn't really understand that but I can work with it:):)

"As for your string gadget closing, your code suggests that it is simply being hidden. The #EN_CHANGE message fires whenever the string gadget thinks that the user has changed the contents. This means that whenever a key is pressed, the message fires. Thus, because of the command HideGadget(#Gadget_exportaddress_stringbox, 1), your string gadget is being hidden after every key press!"

Ouch, that was dumb of me. Hiding the string gadget is taken care of elsewhere and I was hiding it prematurely. Oh well, live and learn.

Do you know what events are fired off by calendargadgets as I want to add them next?

Thanks for all your help, it has been invaluable.

Posted: Mon Jan 02, 2006 12:02 am
by srod
Afraid I've never used a calendar gadget. It doesn't appear to be a native Window's control (I could be wrong there) and so there's not much info around. If it isn't a native Window's control, then you'd need to find which control (if any) it is based upon before you can identify the messages etc. It might simply be painted directly onto a static control, or some other container, or even a subclassed ListViewGadget etc.

Thanks for that.

Posted: Mon Jan 02, 2006 12:13 am
by Fangbeast
srod, is there anything I can do for you to thank you for all your help?

P.s. Latest changes are working great, new release for address book shortly with output mapping now. Damn it, now I have to write a help file:(

Posted: Mon Jan 02, 2006 12:20 am
by srod
If I gave a quid to everyone who's helped me with PB and Win API or whose code I've swiped and studied to death, then I'd owe some horrendous amount. Sparkie would be a rich man, El-choni would probably get my house, ... :lol:

Like everyone on these forums, I'm just glad to help and give something back.

Posted: Mon Jan 02, 2006 12:59 am
by Fangbeast
srod wrote:If I gave a quid to everyone who's helped me with PB and Win API or whose code I've swiped and studied to death, then I'd owe some horrendous amount. Sparkie would be a rich man, El-choni would probably get my house, ... :lol:

Like everyone on these forums, I'm just glad to help and give something back.
At that rate, El would own my first born child, Fred my cats, Frek, Rings and a few others my house and computer etc....The list goes on and on

Posted: Mon Jan 02, 2006 1:41 am
by Xombie
srod wrote:Afraid I've never used a calendar gadget. It doesn't appear to be a native Window's control (I could be wrong there) and so there's not much info around. If it isn't a native Window's control, then you'd need to find which control (if any) it is based upon before you can identify the messages etc. It might simply be painted directly onto a static control, or some other container, or even a subclassed ListViewGadget etc.
There's a month calendar control - "SysMonthCal32" if you're using CreateWindow_() or CreateWindowEx_() to create it from scratch rather than using internal PB stuff.

http://msdn.microsoft.com/library/defau ... eflist.asp

That should get you the list of messages and notifications available for it. To be on the safe side, you may want to run GetClassName_() on the PB calendar gadget just to make sure it's the same one.

Code: Select all

Procedure.b GetGadgetType(Handle.l)
   ; Return the gadget type based on the classname used in CreateWindowEx_()
   HoldString.s
   ; This will store the length of the wide character string, in characters.
   lCount.l
   ; Used to store the number of character copied.
   HoldString = Space(255)
   ; Allocate size for our string.
   GetClassName_(Handle, @HoldString, 255)
   ; Call our function to retrieve the classname.
   ProcedureReturn HoldString
   ;
EndProcedure
Should tell you what it is. I messed with calendar gadgets a little bit and I think it only returned one event. I suspect the PB version might be an edit control with this calendar attached to it. Not sure.

Posted: Mon Jan 02, 2006 2:26 am
by PB
> I've never used a calendar gadget. It doesn't appear to be a native Window's control

The CalendarGadget calls the native Windows control called "SysMonthCal32".

Posted: Tue Jan 03, 2006 3:47 am
by Sparkie
Fangbeast wrote:Do you know what events are fired off by calendargadgets as I want to add them next?
You can use Win API for a couple events...

Code: Select all

#MCN_SELCHANGE = #MCN_FIRST + 1
#MCN_SELECT = #MCN_FIRST + 4

Procedure WinCallback(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_NOTIFY
      *pnmh.NMHDR = lparam
      If *pnmh\hwndFrom = GadgetID(0)
        Select *pnmh\code
          Case #MCN_SELCHANGE
            selDate = GetGadgetState(0)
            selDate$ = FormatDate("%yyyy/%mm/%dd", selDate)
            SetGadgetText(1, "Selected Month has changed to" + #CRLF$ + selDate$)
          Case #MCN_SELECT
            selDate = GetGadgetState(0)
            selDate$ = FormatDate("%yyyy/%mm/%dd", selDate)
            SetGadgetText(1, "Selected Day has changed to" + #CRLF$ + selDate$)
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure
      
If OpenWindow(0, 0, 0, 220, 280, #PB_Window_SystemMenu|#PB_Window_ScreenCentered,"CalendarGadget()")
  If CreateGadgetList(WindowID())
    CalendarGadget(0, 10, 10, 200, 180)
    TextGadget(1, 10, 200, 200, 50, "")
    SetWindowCallback(@WinCallback())
    Repeat
      event = WaitWindowEvent()
    Until event = #PB_Event_CloseWindow
  EndIf
EndIf
@srod: Thanks for the thought of making me a rich man but your quid don't spend too well over here. :mrgreen:

Flamin' heck, some people are just dead set legends!

Posted: Tue Jan 03, 2006 4:48 am
by Fangbeast
Like the subject says. And you aren't even dead yet!!!

/me bows low to the great sparkie of codedom.

That makes three geniuses in the forum (or should that be geniiiiiii??). srod, xombie and you.

I think we should set concrete boxes around all of you so you will all be safe MWUAHAHAHA :lol: :lol: :lol:

/me wanders off to take his weird pills

Now, do you have one for the dategadget? The one I need:):):)

Never mind.I think it's this one #DTN_DATETIMECHANGE

Thanks sparkie (and all others)

Posted: Tue Jan 03, 2006 5:09 am
by Fangbeast
This is the working routine (testbed). Now that I know where to look, I am able to build on it.

Code: Select all


#DTN_DATETIMECHANGE = #DTN_FIRST + 1


Procedure WinCallback(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_NOTIFY
      *pnmh.NMHDR = lparam
      If *pnmh\hwndFrom = GadgetID(0)
        Select *pnmh\code
          Case #DTN_DATETIMECHANGE
            selDate = GetGadgetState(0)
            selDate$ = FormatDate("%dd/%mm/%yyyy", selDate)
            SetGadgetText(1, "Selected Month has changed to" + #CRLF$ + selDate$)
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure
     
If OpenWindow(0, 0, 0, 220, 280, #PB_Window_SystemMenu|#PB_Window_ScreenCentered,"CalendarGadget()")
  If CreateGadgetList(WindowID())
    DateGadget(0, 10, 10, 200, 25)
    TextGadget(1, 10, 200, 200, 50, "")
    SetWindowCallback(@WinCallback())
    Repeat
      event = WaitWindowEvent()
    Until event = #PB_Event_CloseWindow
  EndIf
EndIf 

The rest of the datepicker messages

Posted: Tue Jan 03, 2006 5:25 am
by Fangbeast
In case anyone wants them:

--------------------------------------------------------------------------------

Sent by a date and time picker (DTP) control when the user closes the drop-down month calendar. The month calendar is closed when the user chooses a date from the month calendar or clicks the drop-down arrow while the calendar is open.

DTN_CLOSEUP = DTN_FIRST + 7

Sent by a date and time picker (DTP) control whenever a change occurs. This notification message is sent in the form of a WM_NOTIFY message.

DTN_DATETIMECHANGE = DTN_FIRST + 1

Sent by a date and time picker (DTP) control when the user activates the drop-down month calendar.

DTN_DROPDOWN = DTN_FIRST + 6

Sent by a date and time picker (DTP) control to request text to be displayed in a callback field. This notification message is sent in the form of a WM_NOTIFY message.

DTN_FORMAT
DTN_FORMATA = DTN_FIRST + 4
DTN_FORMATW = DTN_FIRST + 17

Sent by a date and time picker (DTP) control to retrieve the maximum allowable size of the string that will be displayed in a callback field. This notification message is sent in the form of a WM_NOTIFY message.

DTN_FORMATQUERY
DTN_FORMATQUERYA = DTN_FIRST + 5
DTN_FORMATQUERYW = DTN_FIRST + 18

Sent by a date and time picker (DTP) control when a user finishes editing a string in the control. This notification message is only sent by DTP controls that are set to the DTS_APPCANPARSE style. This message is sent in the form of a WM_NOTIFY message.

DTN_USERSTRING
DTN_USERSTRINGA = DTN_FIRST + 2
DTN_USERSTRINGW = DTN_FIRST + 15

Sent by a date and time picker (DTP) control when the user types in a callback field. This message is sent in the form of a WM_NOTIFY message.

DTN_WMKEYDOWN
DTN_WMKEYDOWNA = DTN_FIRST + 3
DTN_WMKEYDOWNW = DTN_FIRST + 16

Notifies a date and time picker control's parent window that the control has lost the input focus. NM_KILLFOCUS (date time) is sent in the form of a WM_NOTIFY message.

NM_KILLFOCUS = NM_FIRST-8

Notifies a date and time picker control's parent window that the control has received the input focus. NM_SETFOCUS (date time) is sent in the form of a WM_NOTIFY message.

NM_SETFOCUS = NM_FIRST-7

--------------------------------------------------------------------------------

MSDN page reference:

http://msdn.microsoft.com/library/defau ... change.asp

Posted: Tue Jan 03, 2006 5:26 am
by Sparkie
Thanks Fangles, but if it's all the same to you, I prefer to remain a living mortal for the time being. ;)

And as for being stuck inside a wall of concrete boxes, well (no offense to srod and Xombie) unless one of them is of the female gender, I'll take a pass on that too. :razz:

I see you beat me to the DateGadget messages. :) This one can also be done without a callback due to the fact that, unlike the CalendarGadget, the DateGadget sends a #PB_EventGadget when a change occurs. Just adjust the mask$ to remove the time if it's not needed. ;)

Code: Select all

If OpenWindow(0, 0, 0, 220, 280, #PB_Window_SystemMenu|#PB_Window_ScreenCentered,"CalendarGadget()")
  If CreateGadgetList(WindowID())
    DateGadget(1, 10, 10, 180, 25, "Date: %mm/%dd/%yyyy Time: %hh:%ii")
    TextGadget(2, 10, 200, 200, 50, "")
    Repeat
      event = WaitWindowEvent()
      If event = #PB_EventGadget And EventGadgetID() = 1
        selDateTime = GetGadgetState(1)
        selDateTime$ = FormatDate("%yyyy/%mm/%dd  %hh:%ii", selDateTime)
        SetGadgetText(2, "DateGadget has changed to" + #CRLF$ + selDateTime$)
      EndIf
    Until event = #PB_Event_CloseWindow
  EndIf
EndIf

What can I say???

Posted: Tue Jan 03, 2006 5:56 am
by Fangbeast
"Thanks Fangles, but if it's all the same to you, I prefer to remain a living mortal for the time being"

Why set a precendent?? Oh, okay. You win.

"And as for being stuck inside a wall of concrete boxes, well (no offense to srod and Xombie) unless one of them is of the female gender, I'll take a pass on that too"

I've heard rumours about the two of them but diodn't want to say anything.

"This one can also be done without a callback due to the fact that, unlike the CalendarGadget, the DateGadget sends a #PB_EventGadget when a change occurs"

I knew about this one. But for the context in which it will sit, it needs to be an API solution. Easier to integrate it with the existing 2 gadgets and the auto-resize routines.

Will release an update to appointment minder soon illustrating the point.