I dunno if this is an XP thing, because the following code runs fine under windows 98!
Sub cjcEnumPropsEx(ByVal hWndForm As Long, ByRef cText As String)
Local hResult As Long
hResult = EnumPropsEx(hWndForm,ByVal CodePtr(cjcPropEnumProcEx), ByVal VarPtr(cText))
If hResult = -1 Then
cText = "There are no Properties associated with this form"
End If
End Sub
'------------------------------------------------------------------------------------------------------------------------
Function cjcPropEnumProcEx(ByVal hwnd As Long,lpszString As Asciiz, ByVal hData As Long, ByVal dwData As Dword) As Long
Local pString As String Ptr
pString = dwData
@pString = @pString + lpszString + Chr$(13)
Function = %True
End Function
Under windows XP I get a 'application must close...' windows and the thing bombs. I've even changed the cjcPropEnumProcEx function to just do a MSGBOX showing the lpszString contents - still crashes. If I change the msgbox to show VarPtr(lpszString) I always get a number, so its not a null pointer issue. I'm a bit stumped.
Anyone come accross this before?
:cry:
As a bit more information: I have created a very simple version of this program in PB8 using DDT and - it all works fine! :?
I have isolated the problem to FireFly generated code. I cannot see what an earth is the problem as the setprop/getprop stuff is nothing to do with FF. The problem comes when accessing the memory pointed to by the lpstring parameter in the enumerating callback function. As soon as I access that variable the exception occurs.
I am wondering if FF is corrupting something somewhere which is causing this problem! I have my doubts, but I am baffled by this one. This is such a simple thing to do and yet XP crashes everytime, and I've tried several machines with this!
I'll keep digging to see if I can solve this one, but any idea's would be gratefully recieved. (I have tries using the IsBadReadPtr and IsBadStringPtr API's but I still get the GPF!)
I am not 100% sure but it probably relates to the fact that FireFly sets a prop in all controls/forms that it creates. It is called "FF_PTR". Maybe your function is iterating the window handle and picking up that prop when you actually mean to bypass it (i.e. I assume that you only want to pick up your own props and not FireFly's).
Likewise, if you have code that removes props then ensure that you do not remove any properties that you have not explicity set. You do not want to remove the FF_PTR prop by mistake.
Hi Paul
Actually it's an XP thing (suprise suprise :roll: )
Here is the powerbasic forum link with the info and code to overcome the problem.
http://www.powerbasic.com/support/forums/Forum4/HTML/012065.html
I dunno what it is, but XP sends a pointer to a memory location which gives me a GPF as soon as I try and look at it. Anyway, at least it's MS$ and not FF or PB!
You said it worked in DDT though didn't you? I'm still with Paul on the prop possibly causing it. If it is returned and you expect a function location which you call it will go boom.
Roger
The DDT thing was just a fluke! It turns out that XP can set its own properties (so it would seem) and that this has happened in the FF example but not the PB one. Anyway, the thing to remember is that it is the callback function which is being given a duff memory location (the one which holds the string of the property name). If this is below BFFF then you cannot read this address, so any access to the lpString in my function will cause a GPF. Anyway, Edwin reckons its a Atom which is being passed, and I would agree! Mind you, when I tried his suggestion of using the GlobalAtom function to examine it - BANG! GPF again, so XP is really not very happy with me accessing that location at all - odd really because XP gave the address to me in the first place :roll:
Still, the answer was fairly simple in the end, just test for the address of the lpString being on or below BFFF and if so, DON'T TOUCH!
Others reckon that there are more enumeration functions which can do this kind of thing! Ho Hum
Here are the finished functions for people to have a look at
SUB cjcEnumPropsEx(BYVAL hWndForm AS LONG, BYREF cText AS STRING)
LOCAL hResult AS LONG
hResult = EnumPropsEx(hWndForm,BYVAL CODEPTR(cjcPropEnumProcEx), BYVAL VARPTR(cText))
IF hResult = -1 THEN
cText = ""
END IF
END SUB
'------------------------------------------------------------------------------------------------------------------------
FUNCTION cjcPropEnumProcEx(BYVAL hwnd AS LONG,lpszString AS ASCIIZ, BYVAL hData AS LONG, BYVAL dwData AS DWORD) AS LONG
Local pString As String Ptr
Local lpBuffer As Asciiz * 80
pString = dwData
'// Valid?
If VarPtr( lpszString ) <= &hBFFF Then
@pString = @pString + "<!BadAdd: " + Format$(VarPtr(lpszString)) + ">" + $Cr
Function = %True
Exit Function
End If
'// Is it added as atom integer?, skip..
GlobalGetAtomName VarPtr( lpszString ), lpBuffer, SizeOf( lpBuffer )
If Trim$( lpBuffer ) > "" Then
@pString=@pString+"<!atom:" + lpBuffer + ">"+$Cr
Else
@pString = @pString + lpszString + $Cr
End If
Function = %True
END FUNCTION
'------------------------------------------------------------------------------------------------------------------------
' Returns a count of the number of properties associated with a window and creates
' an array with the names in. Does not return any of the error type properties (bad address, atom etc)
'------------------------------------------------------------------------------------------------------------------------
Function cjcPropEnumArray(ByVal hWnd As Long, ByRef cArray() As String) As Long
Local cText As String
Register nCount As Long
Register I As Long
cjcEnumPropsEx(hWnd, cText)
nCount = ParseCount(cText,$Cr)
If ( IsFalse Len(cText) ) Or (nCount=0) Then
Function = 0
Exit Function
End If
' Get count of lines and then break the string into the array
ReDim cArray(nCount)
Parse cText,cArray(),$Cr
' Now, remove any dudd entries and resize the array
Do While I <= nCount
If ( Left$(cArray(I),9) = "<!BadAdd:") Or ( Left$(cArray(I),7) = "<!atom:" ) Then
Array Delete cArray(I)
Decr nCount
Decr I
End If
Incr I
Loop
' We now need to resize the array if we have anything left
If nCount Then
ReDim Preserve cArray(nCount)
End If
Function = nCount
End Function
Use with caution, the've worked for me OK but I have not had the time to really test them out!