Announcement

Collapse
No announcement yet.

Property Get problem

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

  • Property Get problem

    Hi,

    I'm trying my hand at COM programming. The examples seem to work fine, but I'm having a little trouble with Property Get statements in the real world.

    I am trying to open (and see some properties of) an ESRI ShapeFile using the OCX provided by the OpenSource MapWindow project. The COM browser looked it over, liked it, and generated a .INC file for the OCX.

    The following is an excerpt from the .INC file:

    Code:
        INTERFACE IShapefile $IID_MapWinGIS_IShapefile
        INHERIT IDISPATCH
    
        PROPERTY GET NumShapes <1> () AS LONG
        PROPERTY GET NumFields <2> () AS LONG
        PROPERTY GET Extents <3> () AS IExtents
        PROPERTY GET ShapefileType <4> () AS LONG
        PROPERTY GET Shape <5> (BYVAL ShapeIndex AS LONG) AS IShape
        PROPERTY GET EditingShapes <6> () AS INTEGER
        PROPERTY GET LastErrorCode <7> () AS LONG
        PROPERTY GET CdlgFilter <8> () AS STRING
        PROPERTY GET GlobalCallback <9> () AS ICallback
        PROPERTY SET GlobalCallback <9> (BYVAL pVal AS ICallback)
        PROPERTY GET Key <10> () AS STRING
        PROPERTY SET Key <10> (BYVAL pVal AS STRING)
        METHOD OPEN <11> (BYVAL ShapefileName AS STRING, OPT BYVAL cBack AS ICallback) AS INTEGER
        METHOD CreateNew <12> (BYVAL ShapefileName AS STRING, BYVAL ShapefileType AS LONG) AS INTEGER
        METHOD SaveAs <13> (BYVAL ShapefileName AS STRING, OPT BYVAL cBack AS ICallback) AS INTEGER
        METHOD CLOSE <14> () AS INTEGER
    I was overjoyed when the "OPEN" method worked in my little piece of code that follows. Then, I wanted to view one of the properties of the shapefile. I must have missed something because the "ShapeCount =" line near the end of the code below returns an error at the .ShapeCount item saying that a method or property is expected.

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "MapWinInc.inc"
    
    GLOBAL ShapeName AS STRING
    
    DECLARE FUNCTION OpenShp() AS INTEGER
    
    FUNCTION PBMAIN () AS LONG
    
        'MSGBOX "Got Here"
         IF COMMAND$ = "" THEN
             shapename = "c:\newmaps\B-L Little 08 Harvest.shp"
         ELSE
             ShapeName = COMMAND$
         END IF
    
        openshape
    
    END FUNCTION
    
    FUNCTION OpenShape() AS INTEGER
    
        LOCAL DispVar AS DISPATCH
        LOCAL ShapeCount AS LONG
        
        LOCAL mShapeCallBack AS ICallBack
    
        LET DispVar = NEWCOM "IShapefile"
    
        OBJECT CALL DispVar.open(ShapeName, mShapeCallBack)
    
        ShapeCount = DispVar.ShapeCount              'Error shows up in this line
    
        FUNCTION = 1
    
    END FUNCTION
    I'm sure I am missing something, but at this point, I can't figure out what it might be...

    Some helpful comments would sure be appreciated!

    Ken
    Ken S. Elvehjem
    [email protected]

  • #2
    Hi Ken,

    Try using the direct v-table methods or use OBJECT GET.
    Code:
    Function PBMain () As Long
      Local O As IShapefile
      Local ShapeCount As Long
      Local mShapeCallBack As ICallBack
    
      o = NewCom $PROGID ' or use CLSID
      o.Open(ShapeName, mSShapeCallback)
    
      ShapeCount = o.ShapeCount
    
      Function = 1
    End Function
    Sincerely,

    Steve Rossell
    PowerBASIC Staff

    Comment


    • #3
      You're mixing apples with oranges, i.e. you have generated an interface definition for direct interface calls use and then you are using OBJECT CALL for the Open method, and then a direct interface call for the ShapeCount property but with a variable dimmed as DISPATCH instead of an interface.

      Try the following:

      Code:
      LOCAL DispVar AS IShapeFile
      LOCAL ShapeCount AS LONG
      
      DispVar = NEWCOM "IShapefile"
      DispVar.open(UCODE$(ShapeName), NOTHING)
      ShapeCount = DispVar.ShapeCount
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        Property Get problem

        Steve & José,

        Thank you for your responses.

        I can see that I *should* have attached my BAS and INC files....

        Both of your proposed solutions seem to give an error.

        José, I understand what you mean about the Apples and Oranges, but I somehow keep missing what my mistake *is*.

        Please note the attached files.

        Sincerely,

        Ken
        Attached Files
        Ken S. Elvehjem
        [email protected]

        Comment


        • #5
          I don't see any property called ShapeCount in the MapWinInc include file. Probably NumShapes is what you have to use.
          Forum: http://www.jose.it-berater.org/smfforum/index.php

          Comment


          • #6
            Property Get problem

            OK, fixed *that*.

            Now, when debugging, I get the error that follows when I get to this line:

            DispVar.open(UCODE$(ShapeName), NOTHING)

            I can't tell why this is a memory access violation...

            Ken

            Component Files:
            ----------------
            C:\POLYEX~1\PolyExtract.bas
            C:\POLYEXTRACT\MAPWININC.INC
            ==============================
            Compile succeeded at 2:24:48 PM on 7/9/2009

            Begin Debug at 2:24:48 PM on 7/9/2009
            Exception: Memory Access Violation
            Program tried to read or write an invalid memory address
            End Debug at 2:24:52 PM on 7/9/2009
            Ken S. Elvehjem
            [email protected]

            Comment


            • #7
              Check if DispVar contains a valid reference, e.g.

              Code:
              IF ISNOTHING(DispVar) THEN EXIT FUNCTION   ' Not a valid object
              You are using DispVar = NEWCOM "IShapefile" to create the object, yet there is no such a ProgID in the include file (in fact, there is not any ProgID).

              Probably you will have to use:

              Code:
              DispVar = NEWCOM CLSID $CLSID_MapWinGIS_Shapefile
              Forum: http://www.jose.it-berater.org/smfforum/index.php

              Comment


              • #8
                José

                That last worked just great.

                I can now have it returning the rest of the info re: the shapefile.

                Thanks once again for the solution to this problem!

                Ken
                Ken S. Elvehjem
                [email protected]

                Comment


                • #9
                  A few days later...

                  I am trying to use one of the Methods(SelectShapes) to select individual shape items from within the ShapeFile.

                  I have a Variant variable named Result() dimensioned as a LOCAL, and redimensioned to "some reasonable value". (I used 250)

                  When I use that variable in the Method call, however, I am told it is "Undeclared" (error 519) on compiling.

                  Code:
                      LOCAL Result() AS VARIANT
                      LOCAL xxmin, yymin, xxmax, yymax AS DOUBLE
                      REDIM Result(250)
                  .
                  .
                  .
                      xxMin = -91.85
                      yyMin =  42.62
                      xxMax = -91.80
                      yyMax =  42.63
                      Extents1.SetBounds(xxmin, yymin, 0, xxmax, yymax, 0)
                      
                      DispVar.SelectShapes(extents1, 0.0, %INTERSECTION, Result )
                  The include file I am using was posted to this thread earlier.

                  José, I read some of your posts and Michael M's on a previous thread :


                  I suspect that this is "sort of" the same kind of problem, but I can't see it from here.

                  Any comments would be greatly appreciated.

                  Ken
                  Ken S. Elvehjem
                  [email protected]

                  Comment


                  • #10
                    When I use that variable in the Method call, however, I am told it is "Undeclared" (error 519) on compiling.
                    Of course. The parameter is a variant and you are trying to pass an array of variants. Just pass a variant.

                    A different matter is if that variant must hold a reference to an array of something or not, or if the method just wants a variant and will return a safearray int it, or whatever. Hard to say without having documentation and without being able to test.
                    Forum: http://www.jose.it-berater.org/smfforum/index.php

                    Comment


                    • #11
                      OK, I understand that...

                      Fixed it, and it compiles. It crashes when I try to run it.

                      Used debug to run it...

                      Then it stops on that line and sez:

                      Begin Debug at 11:49:26 AM on 7/17/2009
                      Exception: Memory Access Violation
                      Program tried to read or write an invalid memory address
                      End Debug at 11:49:33 AM on 7/17/2009


                      Here's where that method is explained...


                      I notice that the VB.Net reference shows it as an integer.

                      Ken
                      Ken S. Elvehjem
                      [email protected]

                      Comment


                      • #12
                        Your link only shows how to call the method using VB.NET or VB6, but doesn't explain what kind of variant wants. I have no idea of what VB does under the hood.
                        Forum: http://www.jose.it-berater.org/smfforum/index.php

                        Comment


                        • #13
                          Check also if extents1 is a valid object. Are you creating an instance of it? You aren't showing any code.
                          Forum: http://www.jose.it-berater.org/smfforum/index.php

                          Comment


                          • #14
                            José,

                            Sorry 'bout that.

                            I *did* declare it... see code below. That doesn't mean it's valid...;>)

                            The theory being that a shapefile containing individual shapes (points, lines, polygons, etc.) in an X,Y,Z format can be queried with the SelectShapes method.

                            Being still new at this, I find the .INC file a little intimidating. Nevertheless, I have tried to get it to select these shapes for me, based on a bounding rectangle. Part of my problem is that the "extents" shows up as a "class" in the .inc file.

                            This means I am not sure that I am specifying those extents correctly.

                            I am including my code here, and attaching the .inc file.

                            Ken


                            Code:
                            #COMPILE EXE
                            #DIM ALL
                            #INCLUDE "MapWinInc.inc"
                            
                            GLOBAL ShapeName AS STRING
                            
                            DECLARE FUNCTION OpenShp() AS INTEGER
                            
                            FUNCTION PBMAIN () AS LONG
                            
                                LOCAL d$
                            
                                'MSGBOX "Got Here"
                                 IF COMMAND$ = "" THEN
                                     'shapename = "c:\newmaps\B-L Little 08 Harvest.shp"
                                     d$ = DIR$("c:\MissProfit\Data\*.shp")
                                     DO WHILE LEN(d$)
                                         ShapeName = "c:\MissProfit\Data\" & d$
                                         OpenShape
                                         d$ = DIR$
                                     LOOP
                                 ELSE
                                     ShapeName = COMMAND$
                                     OpenShape
                                 END IF
                            
                            '    openshape
                            
                            END FUNCTION
                            
                            FUNCTION OpenShape() AS INTEGER
                            
                                LOCAL DispVar AS IShapeFile
                                LOCAL DBVar AS ITable
                                LOCAL CSVName AS STRING
                                LOCAL ShapeCount, ShapeType, NumFields AS LONG
                                LOCAL NumPoints AS LONG
                                LOCAL PointAvx, PointAvy AS DOUBLE
                                LOCAL Extents AS IExtents
                                LOCAL Extents1 AS IExtents
                                
                                LOCAL OneShape AS Ishape, OnePoint AS IPoint, OneTable AS ITable
                            
                                LOCAL DBF AS STRING, DBFRows AS LONG, DBFFields AS LONG
                            
                                LOCAL a, b AS LONG
                                LOCAL t AS INTEGER
                                LOCAL Zval AS DOUBLE, ZV AS VARIANT, success AS LONG
                            
                                LOCAL Result AS VARIANT
                                LOCAL xxmin, yymin, xxmax, yymax AS DOUBLE
                                
                                
                                DBF = UCASE$(ShapeName)
                                REPLACE ".SHP" WITH ".DBF" IN DBF
                            
                                CSVName = UCASE$(ShapeName)
                                REPLACE ".SHP" WITH ".CSV" IN CSVName
                            
                            
                                'DispVar = NEWCOM "IShapefile"
                                DispVar = NEWCOM CLSID $CLSID_MapWinGIS_Shapefile
                            '    IF ISNOTHING(DispVar) THEN MSGBOX "It's nothing"
                            
                                DispVar.open(UCODE$(ShapeName), NOTHING)
                            '    IF ISNOTHING(DispVar) THEN MSGBOX "It's nothing"
                            
                                 ShapeCount = DispVar.NumShapes
                               ' MSGBOX "Number of Shapes: " & STR$(ShapeCount)
                                ShapeType = DispVar.ShapeFileType
                               'MSGBOX "Type of Shape: " & STR$(ShapeType)
                                 NumFields = DispVar.NumFields
                                'MSGBOX "Number of Fields: " & STR$(NumFields)
                                 Extents = DispVar.Extents
                                'MSGBOX STR$(Extents.xMin) & "   " & STR$(Extents.xMax) & $CR & $LF &  STR$(Extents.yMin)  & "   " & STR$(Extents.yMax)
                            
                            
                            'DBF Stuff *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
                                DBVar = NEWCOM CLSID $CLSID_MapWinGIS_Table
                                DBVar.open(UCODE$(DBF), NOTHING)
                                DBFRows = DBVar.NumRows
                                DBFFields = DBVar.NumFields
                                'Msgbox str$(DBFRows) & STR$(DBFFields)
                            'DBF Stuff *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
                            
                            
                            'Select Shapes Stuff *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
                            '    METHOD SetBounds <1> (BYVAL xMin AS DOUBLE, BYVAL yMin AS DOUBLE, BYVAL zMin AS DOUBLE, BYVAL xMax AS DOUBLE, BYVAL yMax _
                            '        AS DOUBLE, BYVAL zMax AS DOUBLE)
                            
                            '    METHOD SelectShapes <18> (BYVAL BoundBox AS IExtents, OPT BYVAL Tolerance AS DOUBLE, OPT BYVAL SelectMode AS LONG, OPT _
                            '        BYREF IN result AS VARIANT) AS INTEGER
                            
                                xxMin = -91.85
                                yyMin =  42.62
                                xxMax = -91.80
                                yyMax =  42.63
                                Extents1.SetBounds(xxmin, yymin, 0, xxmax, yymax, 0)
                                
                                success = DispVar.SelectShapes(extents1, 0, %INTERSECTION, BYREF Result )
                                
                            
                            'Select Shapes Stuff *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
                            
                            GOTO JumpOut
                            
                                t = FREEFILE
                                OPEN CSVName FOR OUTPUT AS #t
                            
                                FOR a = 0 TO ShapeCount - 1
                                    OneShape = DispVar.Shape(a)
                                    NumPoints = OneShape.numpoints
                                    'if a < 5 then MSGBOX "Vertices in Shape "  & str$(a) & "=" & str$(OneShape.NumPoints)
                                    PointAVx = 0
                                    PointAVy = 0
                                    'print #t, a, NumPoints, " Points"
                                    FOR b = 0 TO NumPoints - 1
                                        OnePoint = OneShape.Point(b)
                                        PointAVx = PointAVx + onepoint.x
                                        PointAVy = PointAVy + onepoint.y
                                        'PRINT #t, OnePoint.x, onepoint.y, PointAVx, PointAVy
                            
                                    NEXT b
                                    pointAVx = PointAVx / NumPoints
                                    pointAVy = PointAVy / NumPoints
                            
                                    ZV = DBVar.CellValue(3, a)
                                    ZVal = VARIANT#(ZV)
                                   ' if a < 10 then msgbox str$(ZVal)
                            
                                    PRINT #t, PointAVx; ","; PointAVy; ","; ZVal   ' "  == Averages"
                            
                                    'IF a < 5 THEN MSGBOX STR$(OnePoint.x) & "   " & STR$(OnePoint.y)
                                    'IF a < 5 THEN MSGBOX STR$(PointAVx) & "   " & STR$(PointAVy)
                            
                            
                                NEXT a
                                CLOSE #t
                            JumpOut:
                            
                            
                                FUNCTION = 1
                            
                            END FUNCTION
                            Attached Files
                            Ken S. Elvehjem
                            [email protected]

                            Comment


                            • #15
                              I *did* declare it... see code below. That doesn't mean it's valid...;>)
                              I mean if it contains a valid reference. Just declaring it, initializes it with a NULL reference, and calling a method using a null object variable only leads to a crash.

                              You will have to use:

                              exents1 = NEWCOM CLSID $CLSID_MapWinGIS_Extents
                              Forum: http://www.jose.it-berater.org/smfforum/index.php

                              Comment


                              • #16
                                Part of my problem is that the "extents" shows up as a "class" in the .inc file.
                                What class? I see it as an interface:

                                Code:
                                ' Interface Name  : IExtents
                                ' Description     : IExtents Interface
                                ' ClassID         : $CLSID_MapWinGIS_Extents
                                Interface IExtents $IID_MapWinGIS_IExtents
                                    Inherit IDispatch
                                
                                    Method SetBounds <1> (Byval xMin As Double, Byval yMin As Double, Byval zMin As Double, Byval xMax As Double, Byval yMax _
                                        As Double, Byval zMax As Double)
                                    Method GetBounds <2> (ByRef xMin As Double, ByRef yMin As Double, ByRef zMin As Double, ByRef xMax As Double, ByRef yMax _
                                        As Double, ByRef zMax As Double)
                                    Property Get xMin <3> () As Double
                                    Property Get xMax <4> () As Double
                                    Property Get yMin <5> () As Double
                                    Property Get yMax <6> () As Double
                                    Property Get zMin <7> () As Double
                                    Property Get zMax <8> () As Double
                                    Property Get mMin <9> () As Double
                                    Property Get mMax <10> () As Double
                                    Method GetMeasureBounds <11> (ByRef mMin As Double, ByRef mMax As Double)
                                    Method SetMeasureBounds <12> (Byval mMin As Double, Byval mMax As Double)
                                End Interface
                                Forum: http://www.jose.it-berater.org/smfforum/index.php

                                Comment


                                • #17
                                  Worked Great!

                                  So...

                                  for this "extents1" object to be valid, I have to:

                                  declare it: LOCAL Extents1 AS IExtents
                                  load it: Extents1 = NEWCOM CLSID $CLSID_MapWinGIS_Extents
                                  Then use it: Extents1.SetBounds(xxmin, yymin, 0, xxmax, yymax, 0)

                                  Right?

                                  Now,

                                  According to the debug facility, the variable "Result" in the SelectShapes Method returns a "Safe Array" item.

                                  How do I access the elements of that array in my program?

                                  Ken
                                  Ken S. Elvehjem
                                  [email protected]

                                  Comment


                                  • #18
                                    Try this:

                                    Code:
                                    DIM rgResult(0) AS LONG
                                    rgResult() = Result
                                    If you are lucky, you will get an array of long values.
                                    Forum: http://www.jose.it-berater.org/smfforum/index.php

                                    Comment


                                    • #19
                                      José

                                      That did the trick. I can now select the appropriate polygons from a group of 25,000 polygons in about zero seconds!

                                      I tried to do similar stuff before that OCX was available, and almost had a nervous breakdown. In fact, I wore out keyboards entering line after line of glue and support code.

                                      Now, in 30 - 40 lines of code, it's all practically done for me.

                                      As Little Orphan Annie said, "I really think I'm gonna like it here!"

                                      Thanks for all your help!

                                      Ken
                                      Ken S. Elvehjem
                                      [email protected]

                                      Comment

                                      Working...
                                      X