Announcement

Collapse
No announcement yet.

Global WM_SETFOCUS and WM_KILLFOCUS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Global WM_SETFOCUS and WM_KILLFOCUS

    I've got multiple windows with ten-plus controls (mostly textboxes, but some comboboxes, etc.) used for data entry. I wanted to set the font of the label for each control to bold when it has the focus. My issue is that from my understanding, I need to include a WM_SETFOCUS and WM_KILLFOCUS for EACH control. This is not un-doable, but I would prefer only one set of WM_SETFOCUS and WM_KILLFOCUS that handle all controls on the page. Is this possible?

    Thanks!

    -JT
    LOCAL MyEMail AS STRING
    MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")

  • #2
    One way to do this is to subclass the controls and use the same subclassed procedure
    for all of them.
    But in order for this to work, you will have to save the pointer to the original procedure
    for each control as a window property. For example,
    Code:
    SetProp hWndControl, "OLDWNDPROC", SetWindowLong(hWndControl, %GWL_WNDPROC, CODEPTR(SubclassProc))
    Then the subclass procedure will look something like this
    Code:
    FUNCTION SubclassProc _
      ( _
      BYVAL hWnd    AS DWORD, _ ' control handle
      BYVAL uMsg    AS DWORD, _ ' type of message
      BYVAL wParam  AS DWORD, _ ' first message parameter
      BYVAL lParam  AS LONG _   ' second message parameter
      ) EXPORT AS LONG
    
      LOCAL lpOldWndProc    AS DWORD    ' address of original window procedure
    
      lpOldWndProc = GetProp(hWnd, "OLDWNDPROC")
    
      SELECT CASE uMsg
        CASE %WM_SETFOCUS
          
        CASE %WM_KILLFOCUS
            
        CASE %WM_DESTROY
          ' Remove control subclassing
          SetWindowLong hWnd, %GWL_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")
      END SELECT
    
      FUNCTION = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
    
    END FUNCTION
    Dominic Mitchell
    Phoenix Visual Designer
    http://www.phnxthunder.com

    Comment


    • #3
      Try:
      Assign IDs of controls as even numbers, IDs of associated label plus 1.
      For 16, or less, controls; ID range could be 1024 to 1057. Assign other controls to IDs outside this range.

      Logic OR cbctl with 1 to get ID of label.

      example:
      Code:
      %ID_TxtBx1 = 1024
      %ID_Label1 = 1025
      %ID_TxtBx2 = 1026
      %ID_Label2 = 1027
      ...
      %ID_Button1 = 1058
        ...
        ...
          case %WM_COMMAND
            'bold label for control with focus
            if (cbctl > 1023) and (cbctl < 1057) then 'range of controls with this behavier
              if cbctlmsg = %EN_SETFOCUS then
                 control post cbhndl, cbctl or 1, %WM_SETFONT, hFontBold, 0
              elseif cbctlmsg = %EN_KILLFOCUS then
                 control post cbhndl, cbctl or 1, %WM_SETFONT, hFontNormal, 0
              end if
            end if
            select case as long cbctl '<-- usual control processing code
              case %ID_Button1
        ...
      (changed cbctlmsg names, see next 2 posts)
      Last edited by Dale Yarker; 4 May 2008, 11:09 AM. Reason: change control send to control post
      Dale

      Comment


      • #4
        For edit (textbox) controls you don't want to look for WM_COMMAND + WM_SET|KILL FOCUS, you want to look for WM_COMMAND + EN_SET|KILL FOCUS

        >control post cbhndl, cbctl or 1, %WM_SETFONT, hFontBold, 0

        OR 1?

        Message will be posted to CtrlId + 1 ("the wrong control") when CtrlID is an even number. Oops. (But it will be just fine for odd-numbered controls.)

        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Re: WM_SET|KILL FOCUS vs EN_SET|KILL FOCUS, you are correct, I just copied/pasted from original post. (that wipes out a dozen ataboys )

          Yeah only odd controls. When a textbox or combo box (even numbered) gets focus, the label (odd numbered) for that control gets a bold font. And the label for the control that lost focus is returned to normal weight font. And done without repeating the code in the CASE for each textbox/combobox.
          Last edited by Dale Yarker; 4 May 2008, 11:08 AM.
          Dale

          Comment


          • #6
            >When a textbox or combo box (even numbered) gets focus
            Code:
                    if (cbctl > 1023) and (cbctl < 1057) [B]AND (cbctl mod 2 = 0)[/B] THEN
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Since the labels (as used in this range) won't be getting focus, I didn't worry about filtering them out. They fail the next nested IF.

              If you want, try instead:
              Code:
              if (cbctl > 1023) and (cbctl < 1057) AND ((cbctl AND &h00000001) = 0)THEN
              When possible I use logic operators rather than arithmetic operators. For powers of 2, AND with mask is equivilent to MOD, and faster than dividing.

              With some more thinking, and using other than bit 0 to differentiate between a textbox and it's associated label, the greater than and less than could be replaced too. But it wouldn't be as clear to the original poster.

              C U L -
              Dale

              Comment


              • #8
                Actually, there is no need to worry about control identifiers.
                In a data entry dialog, the label controls are used to inform the user about the purpose
                of the edit field. They also provide the mnemonic that is used to set the focus to the
                edit field when the user presses the Alt+<mnemonic> keys. In order for the correct edit
                field to receive the focus when the user presses the mnemonic, the edit control is created
                immediately after its associated label.
                This means that if the dialog is laid out properly, the subclass procedure would look like
                that shown below.
                The same logic can be used for EN_SETFOCUS/EN_KILLFOCUS.

                Note:
                g_hFontBold -> global variable for bold font
                g_hFont -> global variable for normal font


                Code:
                FUNCTION SubclassProc _
                  ( _
                  BYVAL hWnd    AS DWORD, _ ' control handle
                  BYVAL uMsg    AS DWORD, _ ' type of message
                  BYVAL wParam  AS DWORD, _ ' first message parameter
                  BYVAL lParam  AS LONG _   ' second message parameter
                  ) EXPORT AS LONG
                
                  LOCAL hWndLabel       AS DWORD  
                  LOCAL lpOldWndProc    AS DWORD    ' address of original window procedure
                
                  lpOldWndProc = GetProp(hWnd, "OLDWNDPROC")
                
                  SELECT CASE uMsg
                    CASE %WM_SETFOCUS
                      hWndLabel = GetWindow(hWnd, %GW_HWNDPREV)
                      SendMessage hWndLabel, %WM_SETFONT, g_hFontBold, %TRUE
                  
                    CASE %WM_KILLFOCUS
                      hWndLabel = GetWindow(hWnd, %GW_HWNDPREV)
                      SendMessage hWndLabel, %WM_SETFONT, g_hFont, %TRUE
                  
                    CASE %WM_DESTROY
                      ' Remove control subclassing
                      SetWindowLong hWnd, %GWL_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")
                  END SELECT
                
                  FUNCTION = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)
                
                END FUNCTION
                Dominic Mitchell
                Phoenix Visual Designer
                http://www.phnxthunder.com

                Comment

                Working...
                X