Author Topic: Find Text and Select Objects with acdbTextFind using F#  (Read 1829 times)

0 Members and 1 Guest are viewing this topic.

kaefer

  • Guest
Find Text and Select Objects with acdbTextFind using F#
« on: November 13, 2010, 07:22:13 AM »
Hello there,

this is in application of jgr's API signature of the internal text finder, http://www.theswamp.org/index.php?topic=31886.msg388707#msg388707 (many thx!).

Command acquires a search string and an optional selection set and sets the implied selection accordingly, either with the found text object or with the parent object if it's an attribute in a block or a text in a dimension.

What would be required to extend that to nested text in blocks or xrefs?  Phrased differently, what does the prepackaged FIND command do?

Have fun, Thorsten
Code: [Select]
module FindSelectCommand

open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime

open System.Runtime.InteropServices

type acApp = Autodesk.AutoCAD.ApplicationServices.Application

type AC_SRCH =
| AC_SRCH_BLOCK      = 0x01uy
| AC_SRCH_DIM_TEXT   = 0x02uy
| AC_SRCH_TEXT       = 0x04uy
| AC_SRCH_LINK_DESC  = 0x08uy
| AC_SRCH_LINK_URL   = 0x10uy
| AC_SRCH_MATCH_CASE = 0x20uy
| AC_SRCH_WHOLE_WORD = 0x40uy
| AC_SRCH_DEFAULT    = 0x1Fuy

[<DllImport(
    "acdb18.dll",
    CallingConvention = CallingConvention.Cdecl,
    CharSet = CharSet.Unicode,
    EntryPoint ="?acdbTextFind@@YA_NPAVAcDbDatabase@@AAV?$AcArray@VAcDbObjectId@@V?$AcArrayMemCopyReallocator@VAcDbObjectId@@@@@@PB_W2EABV2@@Z")>]
let acdbTextFind
    (   pDb: nativeint,
        resultSet: nativeint,
        [<In;MarshalAs(UnmanagedType.LPWStr)>] findString: string,
        [<In;MarshalAs(UnmanagedType.LPWStr)>] replaceString: string,
        searchOptions: AC_SRCH,
        selSet: nativeint ) = false

[<CommandMethod "FindSelect">]
let findSelect() =
   
    let doc = acApp.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor

    let pstrr =
        new PromptStringOptions(
            "\nSearch for: ",
            AllowSpaces = true )
        |> ed.GetString
    if pstrr.Status = PromptStatus.OK then

        let psr = ed.GetSelection()
        let psr =
            if psr.Status <> PromptStatus.Error then psr
            else ed.SelectAll()
        if psr.Status = PromptStatus.OK then

            use oidIn = new ObjectIdCollection(psr.Value.GetObjectIds())
            use oidOut = new ObjectIdCollection()
            let ret =
                acdbTextFind(
                    db.UnmanagedObject,
                    oidOut.UnmanagedObject,
                    pstrr.StringResult,
                    null,
                    AC_SRCH.AC_SRCH_DEFAULT,
                    oidIn.UnmanagedObject )
            if ret then

                use tr = db.TransactionManager.StartTransaction()

                let rec objInCurrentSpace (oid: ObjectId) =

                    let dbo = tr.GetObject(oid, OpenMode.ForRead)
                    let ownerId = dbo.OwnerId

                    if ownerId = db.CurrentSpaceId then Some oid
                    elif ownerId.IsNull then None
                    else objInCurrentSpace ownerId
                       
                let sSet =
                    oidOut
                    |> Seq.cast<_>
                    |> Seq.choose objInCurrentSpace
                    |> Seq.toArray
                    |> SelectionSet.FromObjectIds

                ed.SetImpliedSelection sSet
                ed.WriteMessage(
                    "\n{0} found, {1} selected. ", oidOut.Count, sSet.Count )

                tr.Commit()