Announcement

Collapse
No announcement yet.

EnumChildWindow, GetClassName problems

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

  • EnumChildWindow, GetClassName problems

    Hi,

    Ok, I admit being spoiled with EZGUI which has a built in function to enumerate the control's class name but more distinctively than the way Windows does it.
    i.e. EZGUI distinguishes between checkboxes and option button. Actually any kind of button.

    Windows doesn't apparently. I was hoping that a frame, button, checkbox, image button, etc would all have their own unique class name but to no avail.

    So anybody has an idea on how to get this to work (without EZGUI ) ?
    So here we are, this is the end.
    But all that dies, is born again.
    - From The Ashes (In This Moment)

  • #2
    >Windows doesn't apparently

    ???

    Actually, it does, and you have the right answer, at least partway.

    If you execute EnumChildWindows against a window (dialog), your callback procedure will be called once for each child window. In your callback you can use the GetClassName function against the passed handle.

    To get the style of the button, you can call GetWindowLong with the GWL_STYLE parameter.

    Code:
    FUNCTION myCallBack ( byval hwnd AS long, BYVAL lparam AS LONG) AS LONG 
     LOCAL szClass AS ASCIIZ * 128, iStyle AS LONG 
    
          GetClassName   hWnd, szClass, SIZEOF(szClass)
           
          IF   UCASE$(szClass) = "BUTTON" THEN 
               iStyle = GetWindowLong (hWnd, %GWL_STYLE) 
               IF (iStyle AND %BS_CHECKBOX) THEN 
                   ' this is a check box
               ELSEIF (iStyle AND %BS_RADIOBUTTON) OR (iStyle AND %BS_AUTORADIOBUTTON) THEN 
                   ' this is a radio button 
               ELSEIF .....
    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      The API only returns the actual window class name, so the API doesn't do the trick.

      You have to compare the window style bits to get more detailed info about the control (ie. is it a button or a checkbox).

      Not overly difficult though.

      Use GetWindowLong (with GWL_STYLE flag) to get the controls window style.

      Take that value and test the first 4 bits which are significant to check the style of the control. Then compare the value with each of the API window styles to see what kind of control it is (checkbox, raido, button).

      One of the nice things about some classes is that they use the first few bits sequentially, rather than bitwise (ie. 1,2,3,4,5,6,7 rather than bit 0, bit 1, bit 2, etc.) so you can AND part of the window style and get a unique number which will match one of the window styles. Buttons do this.

      The proper way to do this is:

      Code:
                  SELECT CASE (GetWindowLong(hWnd&, %GWL_STYLE) AND 15)
                      CASE %BS_CHECKBOX, %BS_AUTOCHECKBOX
                          ' this is a CHECKBOX
                      CASE %BS_RADIOBUTTON, %BS_AUTORADIOBUTTON
                          ' this is a RADIO
                      CASE %BS_GROUPBOX
                          ' this is a FRAME
                      CASE ELSE
                  END SELECT
      Michaels code is not the correct way to test for styles which are sequential in value. It works for any bitwise values though.

      The problem with testing bits his way, is that more than one sequential value may have those bits set.

      Always check the API styles for any given class and see whether the specific styles you are testing for are sequential values (0,1,2,3,4,5, etc.) or bitwise (1,2,4,8, etc.). Then use the appropriate code to test for what you are looking for.
      Last edited by Chris Boss; 5 May 2009, 08:05 AM.
      Chris Boss
      Computer Workshop
      Developer of "EZGUI"
      http://cwsof.com
      http://twitter.com/EZGUIProGuy

      Comment


      • #4
        To appreciate what I said above, notice the styles for the button class:

        Code:
        %BS_TEXT            = &H0&
        %BS_PUSHBUTTON      = &H0&
        %BS_DEFPUSHBUTTON   = &H1&
        %BS_CHECKBOX        = &H2&
        %BS_AUTOCHECKBOX    = &H3&
        %BS_RADIOBUTTON     = &H4&
        %BS_3STATE          = &H5&
        %BS_AUTO3STATE      = &H6&
        %BS_GROUPBOX        = &H7&
        %BS_USERBUTTON      = &H8&
        %BS_AUTORADIOBUTTON = &H9&
        Notice something ?

        Sequential order of the first few styles, not bitwise!

        It is often assumed window styles are always bitwise, but this is not correct. Some classes use the first few bits for sequentail values, while other bits are used bitwise.
        Chris Boss
        Computer Workshop
        Developer of "EZGUI"
        http://cwsof.com
        http://twitter.com/EZGUIProGuy

        Comment


        • #5
          Thank you Michael and Chris !!
          So here we are, this is the end.
          But all that dies, is born again.
          - From The Ashes (In This Moment)

          Comment


          • #6
            Then I guess the test should be
            Code:
              IF  (iStyle AND %BS_AUTORADIOBUTTON) = %BS_AUTORADIOBUTTON THEN
            rather than
            Code:
              IF  [ISTRUE] (iStyle AND %BS_AUTORADIOBUTTON)  THEN
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Michael,

              You just can't test the styles that way, when they are sequential in value.

              To demonstrate.

              The code below does a bitwise compare for a value of 3 (our fake style value) and when tested Michaels way, it matches up 4 times (3,7,11,15).

              When compared to sequential values (ANDed with 15 to remove any extra high bits and then compared with a value) it only matches up once, with the correct value of 3.

              See the difference between testing for a style for bitwise or sequential values!

              Code:
              #COMPILE EXE
              #DIM ALL
              '
              %TestStyle =    3
              '
              FUNCTION PBMAIN () AS LONG
                  LOCAL FakeStyle&, CT&
                  CT&=0
                  FOR FakeStyle&=0 TO 15
                       IF (FakeStyle& AND %TestStyle) = %TestStyle THEN
                            CT&=CT&+1
                            MSGBOX "AND Match = "+STR$(FakeStyle&)+" ("+STR$(CT&)+" Count)"
                       END IF
                  NEXT FakeStyle&
                  CT&=0
                  FOR FakeStyle&=0 TO 15
                       IF (FakeStyle& AND 15) = %TestStyle THEN
                            CT&=CT&+1
                            MSGBOX "SEQ Match = "+STR$(FakeStyle&)+" ("+STR$(CT&)+" Count)"
                       END IF
                  NEXT FakeStyle&
              END FUNCTION
              Chris Boss
              Computer Workshop
              Developer of "EZGUI"
              http://cwsof.com
              http://twitter.com/EZGUIProGuy

              Comment

              Working...
              X