MapInfo Pro Developers User Group

Expand all | Collapse all

How to add a map and a few legend frames to a layout

  • 1.  How to add a map and a few legend frames to a layout

    Posted 08-02-2019 07:06
      |   view attached
    Here is a small sample application that might give you a few hints to have to get started with the layout thru MapBasic.

    The tools creates a new layout, adds a map to it and then it adds to legend frames from two layers in the map next to the map frame.

    To achieve this, you basically need to use these MapBasic statements:
    • Layout Designer: Creates a new Layout window
    • Create Frame: Creates a new frame, in this case with a map, in the layout
    • Create Designer Legend: Create the first legend frame from a layer
    • Add Designer Frame: Adds additional legend frames from other layers
    You can also download the short sample application from below, including the example data used.

    Here is a picture of the final - very basic - layout.

    Break-down of the application

    We are using some constants from MapBasic.def and we also create a few variables to hold to the WindowIDs.
    Include "MapBasic.def"
    Dim nMapID, nMapIDInLayout, nLayoutID, nLegendID, i As Integer

    Initially, we loop thru the open windows until we get a map window. Typically, you might want to ask the user to pick the map or maybe you have already a variable with your Map Window ID.
       For i = 1 To NumWindows()
          If WindowInfo(WindowID(i), WIN_INFO_TYPE) = WIN_MAPPER Then
             nMapID = WindowID(i)
             Exit For
          End If
       Next
       Print "Map: " & WindowInfo(nMapID, WIN_INFO_NAME)

    Now we create the Layout Window. The position and size is not used if the window is tabbed.
       'Create Layout window
       Layout Designer
          Position (0.0,0.0) Units "in"
          Width 8 Height 8 Units "in"
       nLayoutID = WindowID(0)

       Set Layout
          Window nLayoutID
          Extents To Fit Zoom 100

       Set CoordSys Layout Units "in"
       Set Paper Units "In"

    Now we insert the Map Window we found earlier into a new frame in the Layout Window we created. We also grab the WindowID of the new Map Window. Remember that the new Layout Window doesn't refer back to the original Map Window but it contains a cloned copy of the Map Window. We do specify a size of the frame using the upper left and lower right corner of the frame. Notice that (6.5, 7.0) isn't the width and height but the position of the lower right corner of the frame.
       'Insert Map into Layout
       Create Frame Into Window nLayoutID
          (0.5,1.0) (6.5,7.0)
          Pen (1,2,0) Brush (2, 16777215, 16777215)
          From Window nMapID
          FillFrame On
       nMapIDInLayout = WindowID(0)

    Finally, it time to insert the legend frames for some of the layers. In this case we have hard coded which specific layers we want to add. In other cases you might want to insert a frame for all layers. In that specific case you would have to loop thru the layers and insert them one at a time using the structure below.
       'Creating the first legend frame in the layout window
       Create Designer Legend
          From Window nMapIDInLayout
          Custom
          Default Frame Style "Destillery Buffers"
          Font ("Arial",0,8,0)
          Frame From Layer 2
             Position (6.6,1.0) Units "in"
             Border Pen(1,2,0) Brush(2, 16777215, 16777215)
             Using column object
                 Label "Destillery Buffers"

       nLegendID = WindowID(0)

       'Adding another legend frame to the layout window
       Add Designer Frame
          Window nLegendID
          Custom
           Frame From Layer 1

             Position (6.6,1.35) Units "in"
             Border Pen(1,2,0) Brush(2, 16777215, 16777215)
             Using column object
                 Label "Destilleries"


    If you know exactly how many and which layers you want, you can insert them all using the Create Designer Legend statement and so avoid the Add Designer Frame statement.
    'Creating the two legend frames in the layout window
    Create Designer Legend
       From Window nMapIDInLayout
       Custom
       Default Frame Style "Destillery Buffers"
       Font ("Arial",0,8,0)
       Frame From Layer 2
          Position (6.6,1.0) Units "in"
          Border Pen(1,2,0) Brush(2, 16777215, 16777215)
          Using column object
          Label "Destillery Buffers"
       Frame From Layer 1
          Position (6.6,1.35) Units "in"
          Border Pen(1,2,0) Brush(2, 16777215, 16777215)
          Using column object
             Label "Destilleries"
    nLegendID = WindowID(0)


    There is one important thing to notice about the two statements above. If you want to specify the location of these frames, you will have to use the Custom keyword. If you do not use the Custom keyword, the Position element will be ignored.

    One of our engineers, @Michele Buselli has written a couple of other articles on working with the Layout thru MapBasic:

    Let us know if you are struggling achieving other things in the Layout Window thru MapBasic​.

    ------------------------------
    Peter Horsbøll Møller
    Pitney Bowes
    ------------------------------

    Attachment(s)

    zip
    Create Legend.zip   27K 1 version


  • 2.  RE: How to add a map and a few legend frames to a layout

    Posted 08-21-2019 07:50
    Hello Peter, please can you help?

    I'm struggling to alter text in a Layout Legend Designer Frame using Alter Designer Frame.  This is what I've posted to the MapInfo Pro and UK Users Group:

    I'm trialling MapInfo v 17.0.3 and needing to re-write some of our MapBasic tools. I don't know MapBasic so mainly need to copy and paste from the MapBasic window.

    We have been using an in-house tool with MapInfo v15 and earlier which runs a search on several layers, styles a map with the results and creates a Legend Designer which we could then insert into a Layout frame (created from a workspace).  Now, because the new Layout Designer does not take in old Legend Designer windows as frames, I want to make a new tool which, after we open our Layout workspace (which includes 2 map frames and 2 text frames), creates Legend Frames for all the map layers and then amends the text in each Legend Frame so that we have our standard legend back.

    I have managed to create the Legend Frames, but I am failing to alter the Legend Frame text. I have looked here
    http://support.pitneybowes.com/SearchArticles/VFP05_KnowledgeWithSidebarHowTo?id=kA180000000Xg0MCAS&popup=false;&lang=en_US
    but I think this only applies to Text Frames, not Legend Frames.

    The text for the Legend Frame creation, which works, is:
    Create Designer Legend Portrait Default Frame Title "#" Font ("Arial",0,8,0) Default Frame Region Height 11 Units "pt" Frame From Layer 1 Frame
    etc. for each layer

    I then have:
    Alter Designer Frame Id 1 Title "Data Enquiry" Font ("Arial", 0, 10, 0)
    Alter Designer Frame Id 1 Style Font("Arial", 0, 7, 0) ID 1 Text "Search Point" ID 2 Text "Search Area"
    etc. for each layer

    This is copied from the MapBasic window (apart from removing window ids like Window 3051) when I do it manually, but when I run this from the mbx, nothing happens - the text isn't changed.

    Am I using the wrong terms, or is it something to do with the Frame Ids?  How else do I identify them?  I really need to automate this as we run the process several times a day.

    Many thanks,
    Jane

    ------------------------------
    Jane Mason
    Biological Records Officer (GIS), Suffolk Biodiversity Information Service, UK
    ------------------------------



  • 3.  RE: How to add a map and a few legend frames to a layout

    Posted 08-21-2019 08:21
    Hi Jane

    I can give it a try.
    When I created the example above, I also was wondering why the labels for my legend swatches didn't match the text I specified in the statement.

    It turned out that MapInfo Pro doesn't currently allow you to specify an expression for a layer with a style override. That was what was causing my problem. We are considering changing this a bit to allow you to enter a fixed string as in my example above.

    The good thing is that there is a workaround. If you set the legend frames to by default use the layer name, you can change the friendly layer name and this will get reflected in the legend too.

    The default value for layer names is "#" as you already are using in your example above. You should be able to skip your Alter Designer Frame statements, or at least the part of these statements that relate to the text.

    In the image below, you can see how the legends are using the Friendly Layer Names.

    This is the sample code that does this:
    Create Designer Legend
       From Window nMapIDInLayout
       Custom
       Default Frame Style "#" Font ("Arial",0,8,0)
       Frame From Layer 2
          Position (6.6,1.0) Units "in"
          Title "Legend Frame Title" Font("Calibri",1,14,BLUE)
          SubTitle "Legend Frame SubTitle" Font("Calibri",1,12,RED)
          Border Pen(1,2,0) Brush(2, 16777215, 16777215)

    nLegendID = WindowID(0)


    Add Designer Frame
       Window nLegendID
       Custom
       Frame From Layer 1
          Position (6.6,1.35) Units "in"
          Border Pen(1,2,0) Brush(2, 16777215, 16777215)



    ------------------------------
    Peter Horsbøll Møller
    Pitney Bowes
    ------------------------------



  • 4.  RE: How to add a map and a few legend frames to a layout

    Posted 08-21-2019 08:29

    Thank you very much for your swift reply Peter – I shall have a look at this in a moment and let you know how I get on.

     

    Thanks again,

    Jane

     






  • 5.  RE: How to add a map and a few legend frames to a layout

    Posted 08-21-2019 11:43
    Thanks Peter I've managed to alter the layer legend Title with your help above, but I can't work out what I need to do to alter the labels to show as in the image below.  The example layer names are Data_Enquiry and Protected_Species.  After I have made and altered the Title for Data_Enquiry to 'Data Enquiry', I want to make the Labels for the points and areas in the layer to be 'Search Point' and 'Search Area'.  And I want to be able to alter the Labels for all subsequent 19 layers e.g. the Protected_Species layer label to 'Protected Species'.
    How do I replace my old text:
    Alter Designer Frame Id 2 Style ID 1 Text "Protected Species"

    Thank you!


    ------------------------------
    Jane Mason
    Biological Records Officer (GIS), Suffolk Biodiversity Information Service, UK
    ------------------------------



  • 6.  RE: How to add a map and a few legend frames to a layout

    Posted 08-22-2019 02:01
    Hi Jane

    You don't need to change all the legend texts manually. You only have to change the friendly name of the layers in your map and the legend text will reflect the friendly name.

    You can rename the friendly names with this command:

    Set Map Window FrontWindow() Layer Data_Enquiry FriendlyName "Data Enquiry"

    If your map and data are stored in a workspace, you can also manually rename your layers and save these friendly names to the workspace: Right-click the layer and select Rename from the context menu. In this way, you won't have to write any MapBasic code.

    Let me know how this goes


    ------------------------------
    Peter Horsbøll Møller
    Pitney Bowes
    ------------------------------



  • 7.  RE: How to add a map and a few legend frames to a layout

    Posted 08-22-2019 07:39
    Thanks Peter.  My problem now though, isn't with the Layer names (I do manage to make these friendly layer legend Titles with your help above), but I can't work out what I need to do to alter the style Labels to show as in the image I posted.

    In my current program I have this line to label these styles:
    Alter Designer Frame Id 1 Title "Data Enquiry" Style Id 1 Text "Search Point" Id 2 Text "Search Area"

    And for other layers like this:
    Alter Designer Frame Id 2 Style ID 1 Text "Protected Species"

    So I don't know how to replace this for MapInfo 17 - below is the Legend Frame Property box completed as I want it:



    ------------------------------
    Jane Mason
    Biological Records Officer (GIS), Suffolk Biodiversity Information Service, UK
    ------------------------------



  • 8.  RE: How to add a map and a few legend frames to a layout

    Pitney Bowes
    Posted 08-22-2019 07:52
    Hi Peter, Jane,

    I want to clarify something Peter mentioned above: When I created the example above, I also was wondering why the labels for my legend swatches didn't match the text I specified in the statement. It turned out that MapInfo Pro doesn't currently allow you to specify an expression for a layer with a style override. That was what was causing my problem.

    What Peter is referring to is this situation:

    Open Table "C:\Test Data\Ver17.0\Introductory Data\North America\Canada\CAN_CAPS" As CAN_CAPS
    Open Table "C:\Test Data\Ver17.0\Introductory Data\North America\Canada\CANADA" As CANADA
    Map From CAN_CAPS,CANADA

    ' turn on a style override for point layer
    Set Map Layer 1 Display Global Global Symbol (47,255,12,"MapInfo Cartographic",0,0)

    ' try to create legend for point layer CAN_CAPS using a label expression
    Create Designer Legend From Window FrontWindow() Portrait Default Frame Style "#" Font ("Arial",0,8,0) Frame From Layer 1 Using Label "My custom label"

    The Using Label clause was primarily added to let you get legend text from attribute data, but because the layer has a style override, text from a column would not make sense.  Because of the style override, we fall back to using Default Frame Style "#" to generate the legend text - in this case '#' gets replaced with the layer name.

    However, we should allow setting a constant string expression when there is an override.

    The other issue Jane mentions is that altering this text using Alter Designer Frame isn't working. This should be working even in an MBX. Make sure you are referring to the correct legend window. If you don't include a window id, the statement is applied to the top most legend designer window:
    Alter Designer Frame Id 1 Style ID 1 Text "My Custom Label"

    So to be safe, get the legend designer window id:
    Dim legendWinId as Integer
    Create Designer Legend From Window FrontWindow() Portrait Default Frame Style "#" Font ("Arial",0,8,0) Frame From Layer 1
    legendWinId = WindowId(0)
    Alter Designer Frame Window legendWinId Id 1 Style ID 1 Text "My Custom Label"


    There is another workaround for setting legend text with style overrides, but involves manually adding metadata to the TAB file.  This support was originally added for our data products, but if you're comfortable editing table metadata there's no reason why you can't use it. For my points table, I can specify the legend text by adding to the metadata section:

    "\Legend" = ""
    "\Legend\AllPoints" = "My custom points label"

    Then anytime the table has a style override, its legend text will come from this metadata. If you know you always want to use the same text whenever the table has a style override this could be useful, but there is no UI to modify it or remove it. Has to be done manually.

    There are similar tags for lines/regions and you can add all or only the data type you need.

    "\Legend\AllLines" = "legend text for line data"
    "\Legend\AllRegions" = "legend text for region data"

    There is online help for this under the topic "Advanced Options when Creating Map Legends"

    ------------------------------
    Michele Buselli
    PITNEY BOWES SOFTWARE, INC
    ------------------------------



  • 9.  RE: How to add a map and a few legend frames to a layout

    Posted 08-22-2019 10:26
    Thank you Michele.  I think that "Make sure you are referring to the correct legend window" is really my issue, so I can try to work on this using your and Peter's help above.  Also, the metadata option is interesting and a possibility.  For now, to save time, I circumvented the whole problem by taking a snapshot jpg of the legend designer in the v15 layout, and inserting that into a layout frame in v17 - not ideal, but it buys me time!



    ------------------------------
    Jane Mason
    Biological Records Officer (GIS), Suffolk Biodiversity Information Service, UK
    ------------------------------



  • 10.  RE: How to add a map and a few legend frames to a layout

    Posted 09-09-2019 04:04
    Thanks to all suggestions and that of Timothy Mashford on the MapInfo Pro Community  - just an update on my problem - I used WindowID(0) when altering the Designer Frame Window.  So the following now works to create my legend frames and alter the text:

    'After creating the Layout window

    'Insert Map into Layout
       Create Frame Into Window nLayoutID
          (0.822,0.646) (32.889, 26.494)
          Pen (1,1,0) Brush (1, 16777215, 16777215)
          From Window nMapID
          FillFrame On
       nMapIDInLayout = WindowID(0)

    'Creating the first legend frame in the layout window

    Create Designer Legend
       From Window nMapIDInLayout
       Custom
    'The default value for layer names is "#"
       Default Frame Style "#" Font ("Arial",0,8,0)
       Frame From Layer 1
          Position (13.214,0.254) Units "in"
          Title "Data Enquiry" Font("Arial", 0, 10, 0)
      Border Pen(1,1,0) Brush(2, 16777215, 16777215)

    nLegendID = WindowID(0)

    'Add subsequent frames for layers

    Add Designer Frame
       Window nLegendID
       Custom
       Frame From Layer 2
          Position (13.214,0.914) Units "in"
        Border Pen(1,1,0) Brush(2, 16777215, 16777215)

    'This is repeated for all Designer Frames (with altered positions)

    'Then grab the ID of the newly created legend window using WindowID(0)

    Alter Designer Frame Window WindowID(0)Id 1 Title "Data Enquiry" Font("Arial", 0, 10, 0)
    Alter Designer Frame Window WindowID(0)Id 1 Style Font("Arial", 0, 7, 0) ID 1 Text "Search Point" ID 2 Text "Search Area"
    Alter Designer Frame Window WindowID(0)Id 2 Title "Protected, Locally Scarce and Rare Species" Font("Arial", 0, 8, 0)
    Alter Designer Frame Window WindowID(0)Id 2 Style Font("Arial", 0, 7, 0) ID 1 Text "Record Locations (for grids of 6 fig. or greater)"

    'And so on
    Thank you!

    ------------------------------
    Jane Mason
    Biological Records Officer (GIS), Suffolk Biodiversity Information Service, UK
    ------------------------------