Announcement

Collapse
No announcement yet.

GetProp SetProp RemoveProp Enumprop

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

    GetProp SetProp RemoveProp Enumprop

    I'm using properties quite a lot to avoid global storage. So far I'm not using Atoms, all properties are dwords of one sort or another. It struck me that Enumprop would be a tidy way to remove all properties from a dialog, having the Propenumproc call Removeprop for each property. This would certainly make program development & maintenance easier, but in my hands it certainly doesn't work. Looking at the WIn32 Programmer's reference for RemoveProp, I find:
    An application must free the data handles associated with entries removed from a property list. The application can remove only those properties it has added. It must not remove properties added by other applications or by Windows itself.
    Is there some way in which Emumprops/RemoveProp can be "tamed" to just remove all of the properties which I have added to the window? Then this can be called in the WM_DESTROY handler and everytrhing will be sweet.

    I suppose one (nasty) way of doing it would be to use a macro or function to call SetProp which also stuck the property identifier and hwnd into an array declared static, with the array address passed via a property itself.

    Is there a better way?

    #2
    Is there some way in which Emumprops/RemoveProp can be "tamed" to just remove all of the properties which I have added to the window?
    Huh? According to the doc you quoted, this what happens.

    Let's say you EnumProps and in your callback RemoveProp fails because it's not one you added. So what?

    Besides, the Microsoft Example shows exactly that..
    Code:
    case WM_DESTROY: 
     
        EnumPropsEx(hwndSubclass, DelPropProc, NULL); 
     
        PostQuitMessage(0); 
        break; 
     
    // DelPropProc is an application-defined callback function 
    // that deletes a window property. 
     
    BOOL CALLBACK DelPropProc( 
        HWND hwndSubclass,  // handle of window with property 
        LPCSTR lpszString,  // property string or atom 
        HANDLE hData)       // data handle 
    { 
        hData = RemoveProp(hwndSubclass, lpszString); 
    //
    // if appropriate, free the handle hData
    //
     
        return TRUE;
    Show code which 'does not work.'
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


      #3
      MCM, thanks for that, I had completely overlooked the example and gone my own (wrong) way.

      However, I'm still not getting it, this code gives a memory access violation when attempting to read the property id:

      Code:
      '
      ' program to show a problem with RemoveProc in a enumproc
      ' attempts to get the ids of enumerated procs in a global string
      ' then display it.
      ' Chris Holbrook 17 Mar 2008
      ' PBWin 8.04
      #COMPILE EXE
      #DIM ALL
      
      #IF NOT %DEF(%WINAPI)
          #INCLUDE "WIN32API.INC"
      #ENDIF
      
      %IDD_DIALOG1 =  101
      %IDC_LABEL1  = 1001
      %IDC_BUTTON1 = 1002
      
      
      GLOBAL sdebug AS STRING
      '
      
      FUNCTION RemoveAProp(BYVAL hWnd AS DWORD, BYVAL lpsz AS ASCIZ PTR, BYVAL hData AS DWORD) AS LONG
          sdebug = sdebug + ":" + @lpsz  ' this is where it get the memory access violation
          RemoveProp( hWnd, @lpsz)
      END FUNCTION
      '----------------------------------------------------------------------------------
      ' remove all properties for a given window. Call this in %WM_DESTROY
      SUB RemoveAllProps(BYVAL hWnd AS DWORD)
          EnumProps hWnd, CODEPTR(RemoveAProp)
      END SUB
      '----------------------------------------------------------------------------------
      
      CALLBACK FUNCTION ShowDIALOG1Proc()
      
          SELECT CASE AS LONG CBMSG
              CASE %WM_INITDIALOG
                  setprop CBHNDL, "FIRST", 0
                  setprop CBHNDL, "SECOND", 0
      
              CASE %WM_COMMAND
                  SELECT CASE AS LONG CBCTL
                      CASE %IDC_BUTTON1
                          IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                              RemoveAllProps( CBHNDL)
                              CONTROL SET TEXT CBHNDL, %IDC_LABEL1, "properties removed " + sdebug
                          END IF
                  END SELECT
          END SELECT
      END FUNCTION
      
      FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
          LOCAL lRslt AS LONG
      
          LOCAL hDlg  AS DWORD
      
          DIALOG NEW hParent, "Properties problem 17 Mar 2008 ", 181, 124, 196, 85, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
              %WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
              %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
          CONTROL ADD LABEL,  hDlg, %IDC_LABEL1, "", 10, 5, 180, 50
          CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "remove properties", 145, 60, 45, 20, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _
              %BS_TEXT OR %BS_MULTILINE OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR %WS_EX_LTRREADING
      
          DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
      
          FUNCTION = lRslt
      END FUNCTION
      '=========================================
      FUNCTION PBMAIN()
          ShowDIALOG1 %HWND_DESKTOP
      END FUNCTION

      Comment


        #4
        OK, I'm not entirely sure why as yet (although my guess is there's a property there that was added by another process and the string data is therefore outside your program's memory space, so accessing it is a no-no) but changing your function to the following seems to work.

        Code:
        FUNCTION RemoveAProp(BYVAL hWnd AS DWORD, BYVAL lpsz AS ASCIZ PTR, BYVAL hData AS DWORD) AS LONG
            IF lstrlen(@lpsz) <> 0 THEN
               sdebug = sdebug + ":" + @lpsz  ' this is where it get the memory access violation
               RemoveProp( hWnd, @lpsz)
           END IF
           FUNCTION = 1
        END FUNCTION
        Note also the FUNCTION = 1 to continue enumeration.

        Regards,

        Pete.

        Comment


          #5
          Pete, brilliant! Thanks.

          Comment


            #6
            Originally posted by Peter Jinks View Post
            ...seems to work.
            and so it does, but surely to read the length of the string one would have the same problem as copying it if access to that memory was denied.

            The other funny thing is that having transplanted that bit of code (the functions RemoveaProp and RemoveAllProps) into the "real" appplication, it's failing again in exactly the same way, as soon as @lpsz is referenced to determine its length - now that would accord with the idea that my process does not have permission to read the memory containing the property id.

            I have a workaround, which is to call removeprop explicitly for each named property which I have created with setprop, but you can put me down as curiously intrigued by the pnenomenom.

            Comment


              #7
              to read the length of the string one would have the same problem
              Yeah... you did notice that small caveat:
              not entirely sure why
              didn't you?

              Anyway, I knew there was a function I'd prefer to use, but I couldn't find it for the life of me. Now I've found two: IsBadStringPtr, IsBadReadPtr. The String one seems most likely, but according to WIN32API.inc it takes a parameter of ASCIIZ, which means you'd have to pass @lpsz, which would presumably cause the same problem. For the Read one, it appears you need to know how long the string is, which returns us to the previous problem.

              So I'm a bit stumped really. I can't see the point of the enumeration function if you can't read the strings to see if it's something you added or not.

              I'll keep trying and let you know if I find anything useful.

              Regards,

              Pete.

              ADDED: You could try using IsBadReadPtr with a length of 1. That should give enough information.
              Last edited by Peter Jinks; 16 Mar 2008, 06:50 PM.

              Comment


                #8
                3rd time lucky?

                I can't see the point of the enumeration function if you can't read the strings to see if it's something you added or not
                But of course, it might not be a string, might it? It might be an atom, as is clearly stated in the documentation....

                In which case:
                Code:
                FUNCTION RemoveAProp(BYVAL hWnd AS DWORD, BYVAL lpsz AS ASCIZ PTR, BYVAL hData AS DWORD) AS LONG
                   LOCAL lResult AS LONG
                   LOCAL szAtomName AS ASCIIZ * 255
                   
                   lResult = GetAtomName(lpsz, szAtomName, 255)
                   IF lResult <> 0 THEN
                      sDebug = sDebug + ":Atom '" + szAtomName + "' Ignored"
                   ELSE
                       sdebug = sdebug + ":" + @lpsz  ' this is where it get the memory access violation
                       RemoveProp( hWnd, @lpsz)
                   END IF
                   FUNCTION = 1
                END FUNCTION
                Sorry for leading you astray. But then again, if I read the documentation, what fun is it?

                Regards,

                Pete.

                Comment


                  #9
                  Originally posted by Peter Jinks View Post
                  .. It might be an atom
                  Yes, I thought that too, but you beat me with the actual code, I shall try it in the morning. Thanks again!

                  Comment


                    #10
                    Originally posted by Chris Holbrook View Post
                    ...in the morning.
                    OK, it works! But it also makes me doubt whether my original idea was a good one, as it may be possible to remove other people's properties of this window with unknown consequences. Other people being Windows, DDT? The one I find in both the example application and the one I'm developing is the atom, #43288.

                    Comment


                      #11
                      Code:
                      IF lpsz< &h10000 THEN
                        it's an atom
                      ELSE
                        it's a string
                      END IF
                      MCM
                      Tucson AZ
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                        #12
                        MCM you are SUPPOSED to be on Vacation.

                        Back awaaaaaaay from the computer

                        Have fun on Vacay
                        Engineer's Motto: If it aint broke take it apart and fix it

                        "If at 1st you don't succeed... call it version 1.0"

                        "Half of Programming is coding"....."The other 90% is DEBUGGING"

                        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                        Comment

                        Working...
                        X
                        😀
                        🥰
                        🤢
                        😎
                        😡
                        👍
                        👎