visio insertlistmember in C# - c#

Does anyone know how to use the visio insertListMember method (below) in c#?
https://msdn.microsoft.com/en-us/library/office/ff768115.aspx
I have tried to execute the method with the following commands but it gives a "Run Time Error- 424 object required"
I have also used the dropIntoList method and it works fine but for specific purposes I need to use the insertListMember method. (to determine the height of the list)
static void Main(string[] args)
{
//create the object that will do the drawing
visioDrawing.VisioDrawer Drawer = new visioDrawing.VisioDrawer();
Drawer.setUpVisio();
Visio.Shape testShape;
Visio.Shape testShape1;
testShape = Drawer.DropShape("abc", "lvl1Box");
testShape1 = Drawer.DropShape("ccc", "Capability");
Drawer.insertListMember(testShape, testShape1, 1);
}
public void insertListMember(Visio.Shape outerlist, Visio.Shape innerShape, int position)
{
ActiveDoc.ExecuteLine(outerlist + ".ContainerProperties.InsertListMember" + innerShape + "," + position);
}
To obtain the shape:
public Visio.Shape DropShape(string rectName, string masterShape)
{
//get the shape to drop from the masters collection
Visio.Master shapetodrop = GetMaster(stencilPath, masterShape);
// drop a shape on the page
Visio.Shape DropShape = acPage.Drop(shapetodrop, 1, 1);
//put name in the shape
Visio.Shape selShape = selectShp(DropShape.ID);
selShape.Text = rectName;
return DropShape;
}
private Visio.Master GetMaster(string stencilName, string mastername)
{
// open the page holding the masters collection so we can use it
MasterDoc = MastersDocuments.OpenEx(stencilName, (short)Visio.VisOpenSaveArgs.visOpenDocked);
// now get a masters collection to use
Masters = MasterDoc.Masters;
return Masters.get_ItemU(mastername);
}

From your code, 'Drawer' looks to be some kind of Visio app wrapper, but essentially InsertListMember allows you to add shapes to a list that already exist on the page. Here's an example of the method and an alternative Page.DropIntoList if you just want to drop directly from the stencil:
void Main()
{
// 'GetRunningVisio' as per
// http://visualsignals.typepad.co.uk/vislog/2015/12/getting-started-with-c-in-linqpad-with-visio.html
// but all you need is a reference to the app
var vApp = MyExtensions.GetRunningVisio();
var vDoc = vApp.Documents.Add("wfdgm_m.vstx");
var vPag = vDoc.Pages[1];
var vCtrlsStencil = vApp.Documents["WFCTRL_M.VSSX"];
var vListMst = vCtrlsStencil?.Masters["List box"];
if (vListMst != null)
{
var vListShp = vPag.Drop(vListMst, 2, 6);
var vListItemMst = vCtrlsStencil.Masters["List box item"];
var insertPosition = vListShp.ContainerProperties.GetListMembers().Length - 1;
//Use InsertListMember method
var firstListItem = vPag.Drop(vListItemMst, 4, 6);
vListShp.ContainerProperties.InsertListMember(firstListItem, insertPosition);
firstListItem.CellsU["FillForegnd"].FormulaU = "3"; //Green
//or use DropIntoList method on Page instead
var secondListItem = vPag.DropIntoList(vListItemMst, vListShp, insertPosition);
secondListItem.CellsU["FillForegnd"].FormulaU = "2"; //Red
}
}
This is using the Wireframe Diagram template (in Visio Professional) and should result in the following:

In case people were wondering I ended up fixing the method up. However I believe that this method is not required if you are using visio Interop assemblies v15. (I am using v14)
public void insertListMember(int outerShpID, int innerShpID, int position)
{
acWindow.DeselectAll();
Visio.Page page = acWindow.Page;
acWindow.Select(page.Shapes.get_ItemFromID(innerShpID), (short)Microsoft.Office.Interop.Visio.VisSelectArgs.visSelect);
Debug.WriteLine("Application.ActivePage.Shapes.ItemFromID(" + outerShpID + ").ContainerProperties.InsertListMember ActiveWindow.Selection," + position);
ActiveDoc.ExecuteLine("Application.ActivePage.Shapes.ItemFromID(" + outerShpID + ").ContainerProperties.InsertListMember ActiveWindow.Selection," + position);
}

Related

c#, autocad plugins, Updating text of object properties

I need to write AutoCAD plugin to display the area of the object.
Below is my code.
It works fine, but test is static. I need to keep tracking the area of the circle cir.Area.ToString();.
Currently, If I change the size of the circle latter on, the text does not change anymore.
For example, the area of my circle is 10. I run code, it displays 10. But if I change the radius of circle, the text remains 10.
How can I make it working.
[CommandMethod("displayarea")]
public static void Displayarea()
{
var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var filter = new SelectionFilter(new[] { new TypedValue(0, "Circle") });
var selection = ed.GetSelection(filter);
if (selection.Status != PromptStatus.OK)
return;
using (var tr = db.TransactionManager.StartTransaction())
{
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
foreach (var id in selection.Value.GetObjectIds())
{
var ids = new ObjectIdCollection(new[] { id });
Circle cir = (Circle)tr.GetObject(id, OpenMode.ForRead) as Circle;
var _centerPosition = cir.Center;
using (DBText acText = new DBText())
{
acText.Position = _centerPosition;
acText.TextString = cir.Area.ToString();
acText.Height = 0.5;
curSpace.AppendEntity(acText);
tr.AddNewlyCreatedDBObject(acText, true);
}
}
tr.Commit();
}
}
Also you can use oEntity.Modified += OEntity_Modified;
Find this: Find which properties changed on modified event
You need to use fields.
Find this:
https://www.keanw.com/2007/07/accessing-the-a.html
It works by replacing
cir.Area.ToString();
to
string circarea = "%<\\AcObjProp Object(%<\\_ObjId "
+ CircleId
+ ">%).Area \\f \"%lu2\">%";

iText7 Knowing if a table has extended in more pages

is possible in itext7 knowing if a table (added to document) occupies 1 or more pages and in which page has placed ?
I've tried in an Handler on END_PAGE:
IRenderer pRenderer = TableData.CreateRendererSubTree().SetParent(doc.GetRenderer());
LayoutResult pLayoutResult = pRenderer.Layout(new LayoutContext(new LayoutArea(0, PageSize.A4)));
float y = pLayoutResult.GetOccupiedArea().GetBBox().GetY();
float x = pLayoutResult.GetOccupiedArea().GetBBox().GetX();
float xBottom = pLayoutResult.GetOccupiedArea().GetBBox().GetBottom();
float xHeight = pLayoutResult.GetOccupiedArea().GetBBox().GetHeight();
int pageNumber= pLayoutResult.GetOccupiedArea().GetPageNumber();
I've tried with table only on first page and with table extended on first and second page.
pageNumber is always = 0.
Thanks in advance.
This is certainly possible. iText 7 allows you to override rendering logic, one of the simplest applications of which is knowing where on the page your elements are going to be placed.
As a helper means to store the information about pages on which our table is placed, we can define a small class:
private static class LayoutInfo {
Collection<Integer> occupiedPages = new ArrayList<>();
public void addPage(int pageNum) {
occupiedPages.add(pageNum);
}
public Collection<Integer> getOccupiedPages() {
return occupiedPages;
}
}
Now, we can define our custom table renderer which is going to store the page numbers into this LayoutInfo object:
private static class CustomTableRenderer extends TableRenderer {
private LayoutInfo layoutInfo;
public CustomTableRenderer(Table modelElement, LayoutInfo info) {
super(modelElement);
this.layoutInfo = info;
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
layoutInfo.addPage(occupiedArea.getPageNumber());
}
#Override
public IRenderer getNextRenderer() {
return new CustomTableRenderer((Table) modelElement, layoutInfo);
}
}
You have to set the custom renderer to the table after all the cells have been added into it and the table is ready to be added to the document:
table.setNextRenderer(new CustomTableRenderer(table, info));
Full high level code:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
Document document = new Document(pdfDocument);
LayoutInfo info = new LayoutInfo();
Table table = new Table(2);
for (int i = 0; i < 200; i++) {
table.addCell("Row number ");
table.addCell(i + "");
}
table.setNextRenderer(new CustomTableRenderer(table, info));
document.add(table);
document.close();
System.out.println("The table is placed on the following pages: " + info.getOccupiedPages().toString());
Output of the code:
The table is placed on the following pages: [1, 2, 3, 4, 5, 6]
Note that the code is in Java but translating into C# is mostly a matter of changing cases of characters in a couple of places.

Selecting a POI on Map using a cluster

I am currently using the Map Sample from Microsoft. This sample creates clusters of pins on the map to save space.
I am finding it difficult to be able to select a POI that is on the map and get the properties of the POI.
There are over 1000, POIs so I need clustering, but the sample is not clear on how to select the POI in question.
Code is below:
private async Task LoadPlaceInfoAsync()
{
Uri dataUri = new Uri("ms-appx:///places.txt");
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(dataUri);
IList<string> lines = await FileIO.ReadLinesAsync(file);
// In the places.txt file, each place is represented by three lines:
// Place name, latitude, and longitude.
for (int i = 0; i < lines.Count; i += 3)
{
PlaceInfo place = new PlaceInfo
{
Name = lines[i],
Location = new PlaceLocation(double.Parse(lines[i + 1]), double.Parse(lines[i + 2]))
};
places.Add(place);
}
}
private void refreshMapIcons()
{
// Erase the old map icons.
myMap.MapElements.Clear();
// Create an icon for each cluster.
foreach (var cluster in GetClustersForZoomLevel(previousZoomLevel))
{
MapIcon mapIcon = new MapIcon
{
Location = new Geopoint(cluster.Location.Geoposition),
CollisionBehaviorDesired = MapElementCollisionBehavior.RemainVisible,
};
if (cluster.Places.Count > 1)
{
// The cluster represents more than one place. Use a custom marker that shows
// how many places are represented by this cluster, and place the marker
// centered at the cluster.
mapIcon.Image = numberIconReferences[Math.Min(cluster.Places.Count, 9) - 2];
mapIcon.NormalizedAnchorPoint = new Point(0.5, 0.5);
}
else
{
// The cluster represents a single place. Label the cluster with the place name.
mapIcon.Title = cluster.Places[0].Name;
}
myMap.MapElements.Add(mapIcon);
}
}

Word.Shape.Name taking maximum 18 characters

I am using Word.Interop library. If I assign less than 18 characters to 'Word.Shape.Name' then it work perfect but when I assign more than 18 characters then 'Word.Shape.Name' throw exception.
e.g
Word.Shape.Name = "This is a test value to assign";
throw exception
"System.UnauthorizedAccessException: Access is denied.
(Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))".
What I should do to resolve this problem?
Whole method is
objTargetDocument, ref Scripting.Dictionary dicMarkers, ref Alias.Document objSourceDocument)
{
bool blnRetVal = false;
string strModel = ndModel.Name;
int lngModel = 0;
int lngNextModel = 0;
int lngStart;
int lngEnd;
Alias.Document objTemp;
Microsoft.Office.Interop.Word.Range objRange;
Shape objShape;
Object[] astr;
int n;
bool bLastModel;
/*'--------------------------------------------------------------------------------------------------
' 1. Find model's model marker and the next marker (if any)
'--------------------------------------------------------------------------------------------------*/
astr = dicMarkers.Keys();
for (n = astr.GetLowerBound(0); n <= astr.GetUpperBound(0); n++)
{
if (string.Compare(astr[n].ToString(), strModel, true) == 0)
{
lngModel = (int)dicMarkers.get_Item(astr[n]); //PNDC //dicMarkers.Item(astr(n))
if (n < astr.GetUpperBound(0))
{
if (string.Compare(astr[n + 1].ToString(), "#end", true) == 0)
{
lngNextModel = 0;
bLastModel = true;
}
else
{
lngNextModel = (int)dicMarkers.get_Item(astr[n + 1]);
bLastModel = false;
}
}
else
{
lngNextModel = 0;
}
break;
}
}
/*'--------------------------------------------------------------------------------------------------
' 2. Copy model from original document to new document
'--------------------------------------------------------------------------------------------------*/
if (lngModel > 0)
{
lngStart = objSourceDocument.Sections[lngModel].Range.Start;
if (lngNextModel == 0)
{
var key = "#end";
var value = dicMarkers.get_Item(key);
lngEnd = value;
}
else
lngEnd = objSourceDocument.Sections[lngNextModel].Range.Start; //objSourceDocument.Sections.Last.Index;
//--------------------------------------------------------------------------------------------------
//copy original
objSourceDocument.ActiveWindow.Selection.SetRange(lngStart, lngEnd);
objSourceDocument.ActiveWindow.Selection.Copy();
bool bInsertSection = false;
//paste (append) copied model to the document
if (objTargetDocument.Sections.First.Index == objTargetDocument.Sections.Last.Index)
{
//Target document only has 1 (default) section
bInsertSection = true;
}
else
{
if (objTargetDocument.Sections.Last.PageSetup.SectionStart == WdSectionStart.wdSectionNewPage)
{
//Last section is a nextpage section
if ((objTargetDocument.Sections.Last.Range.End - (objTargetDocument.Sections.Last.Range.Start) <= 1))
//Empty section
bInsertSection = false;
else
bInsertSection = true;
}
else
{
//Last section isn't a nextpage
bInsertSection = true;
}
}
objTargetDocument.ActiveWindow.Selection.Start = objTargetDocument.Range().End;
if (bInsertSection)
{
objTargetDocument.ActiveWindow.Selection.InsertBreak(WdBreakType.wdSectionBreakNextPage);
objTargetDocument.ActiveWindow.Selection.Start = objTargetDocument.Range().End;
}
objTargetDocument.ActiveWindow.Selection.Collapse();
objRange = objTargetDocument.ActiveWindow.Selection.Range.Duplicate; //remember range for model marker anchor
objTargetDocument.ActiveWindow.Selection.Paste();
objTargetDocument.Variables.Add(m_strModelMarker + strModel);
// .TextFrame.ContainingRange
//place model marker (so that we can find our model again)
objShape = objTargetDocument.Shapes.AddTextbox(Microsoft.Office.Core.MsoTextOrientation.msoTextOrientationUpward, 0, 0, 0, 0, objRange);
objShape.Name = m_strModelMarker + strModel; // This Line Trowing Exception
objShape.Visible = Microsoft.Office.Core.MsoTriState.msoFalse;
UpdateFields(ref objTargetDocument, ref ndModel);
blnRetVal = true;
}
else
new Modules.Globals().MsgBoxEx("Kan het bestaande model '" + strModel + "' niet kopieren.", MessageBoxButtons.OK);
return blnRetVal;
}
I haven't been able to find any reference to a 18-character limitation in the Name property. Also, after a quick test, it seems to work fine (even by inputting a much longer length):
Word.Shape oShape = oDoc.Shapes.AddLine(0, 0, 0, 0);
oShape.Name = "This is a test value to assign - This is a test value to assign";
Thus, the error you are mentioning is most likely provoked by a different part of your code.
In any case, I am not sure that you understand the exact meaning of the Name property. This is not something you would be seeing in the Word document at all; this is something for "internal reference purposes". The Shapes array is actually a Dictionary which can be accessed by typing either the index or the name of the given shape; that is, if oShape, as defined above, is the first shape in the document, I can access it by using any of the folowing options:
Word.Shape oShape2 = oDoc.Shapes[1];
Word.Shape oShape2 = oDoc.Shapes["This is a test value to assign - This is a test value to assign"];
For this reason, writing too long names is not necessary anyway.
There is an old discussion here about Word 2003 which seems to be similar.
In that discussion, it suggests storing the name in a document variable object (as in Document.Variables).
Something like:
Variables vars = Doc.Variables;
var = vars.Add("myShapeName", "This is a test value to assign");
and then assign var.Value to Word.Shape.Name somehow.
Edit
On re-reading that linked discussion, there is no way of directly assigning a Doc.Variable to the Name property. What you can set the shape's Name to a short unique identifier and use it to retrieve your long string from the Variables wherever you need it.
void SetLongName(Shape shape, string uniqueId, string longName)
{
shape.Name = uniqueId;
Variables vars = Doc.Variables;
var = vars.Add(uniqueId, longName);
}
string GetLongNameOfShape(Shape shape)
{
return GetLongNameById(shape.Name);
}
string GetLongNameById(string uniqueId)
{
Variables vars = Doc.Variables;
return vars.get_Item(uniqueId).Value;
}

Read cell Items from data grid in SysListView32 of another application using C#

I am trying to read data grid items in SysListView32 of another process using C# .net ui-automation and winapi
C# code using ui-automation
http://pastebin.com/6x7rXMiW
C# code using winapi
http://pastebin.com/61RjXZuK
using this code you just have to place your Mouse pointer on SysListView32 on screen and press Enter.
now both code returns empty on the cell item which have following properties
pastebin.com/Rw9FGkYC
but both code works on following properties
pastebin.com/L51T4PLu
the only difference i noted that the name property contains the same data as in cell but problem occurs when name property is empty.
Is there any other way to read the cell ? or any changes I can make, Please elaborate.
I would also suggest the Inspect tool. If you see this:
IsLegacyIAccessiblePatternAvailable: true
you can use the LegacyIAccessiblePattern. Other posts seem to indicate that it is not yet in the Client UI Automation Api, but it is in the core. You can use the core in .NET by wrapping it. I added this into my build to begin using it:
"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\tlbimp.exe" %windir%\system32\UIAutomationCore.dll /out:..\interop.UIAutomationCore.dll"
I can add more details if this pattern is indeed supported.
Well, then you are probably good.
Here is some sample code:
// C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\UIAutomationClient.h
public const int UIA_LegacyIAccessibleNamePropertyId = 30092;
public const int UIA_LegacyIAccessibleValuePropertyId = 30093;
public const int UIA_IsTextPatternAvailablePropertyId = 30040;
public const int UIA_IsItemContainerPatternAvailablePropertyId = 30108;
public const int UIA_AutomationIdPropertyId = 30011;
public const int UIA_NamePropertyId = 30005;
public const int UIA_IsInvokePatternAvailablePropertyId = 30031;
public const int UIA_ItemContainerPatternId = 10019;
public const int UIA_TextPatternId = 10014;
public const int UIA_LegacyIAccessiblePatternId = 10018;
public const int UIA_ValuePatternId = 10002;
public const int UIA_InvokePatternId = 10000;
public const int UIA_ButtonControlTypeId = 50000;
uiAutomationCore = new UiAutomationCore();
cacheRequest = UiAuto.CreateCacheRequest();
cacheRequest.AddPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
cacheRequest.AddProperty(WindowsConstants.UIA_LegacyIAccessibleNamePropertyId);
cacheRequest.AddProperty(WindowsConstants.UIA_LegacyIAccessibleValuePropertyId);
cacheRequest.TreeFilter = UiAuto.ContentViewCondition;
trueCondition = UiAuto.CreateTrueCondition();
// A Pinvoke GetChildWindows call because it is
// the fastest way to traverse down to a handle
foreach (var child in GetChildWindows(someIUIAutomationElement.GetMainWindowHandle()))
{
var sb = new StringBuilder(100);
// get the name of each window & see if it is an ultragrid
// (get the name because the getchildwindows call only gets the handles
User32.GetClassName(child, sb, sb.Capacity);
var foundProperGrid = false;
if (Win32Utils.GetText(child) != "UltraGrid1")
continue;
// if this is an ultragrid, create a core automation object
var iuiae = UiCore.AutoElementFromHandle(child);
// get the children of the grid
var outerArayOfStuff =
iuiae.FindAllBuildCache(interop.UIAutomationCore.TreeScope.TreeScope_Children,
trueCondition,
cacheRequest.Clone());
var countOuter = outerArayOfStuff.Length;
// loop through the grid children
for (var counterOuter = 0; counterOuter < countOuter; counterOuter++)
{
// make a core automation object from each
var uiAutomationElement = outerArayOfStuff.GetElement(counterOuter);
// hacky - see if this grid has a GroupBy Box as first 'row'
// - if so, this is the proper grid
// - ignore other grids
if (!foundProperGrid && uiAutomationElement.CurrentName.Equals("GroupBy Box"))
{
foundProperGrid = true;
}
else if (foundProperGrid)
{
// 'cast' the object to a core 'legacy msaa' object
IUIAutomationLegacyIAccessiblePattern outerLegacyPattern =
uiAutomationElement.GetCachedPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
Log.Info("OUTER, CachedName = " + outerLegacyPattern.CachedName);
try
{
// select the 'row' to give visual feedback
outerLegacyPattern.Select(3);
}
catch (Exception exc)
{
Log.Info(exc.Message);
}
// get the cells in a row
var arrayOfStuff =
uiAutomationElement.FindAllBuildCache(TreeScope.TreeScope_Children,
trueCondition,
cacheRequest.Clone());
// loop over the cells in a row
var count = arrayOfStuff.Length;
for (var counter = 0; counter < count; counter++)
{
// get a cell
var currIUIA = arrayOfStuff.GetElement(counter);
// 'cast' cell to a core 'legacy msaa' object
IUIAutomationLegacyIAccessiblePattern legacyPattern =
currIUIA.GetCachedPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
// dump cell name & value for reference
var name = legacyPattern.CachedName;
Log.Info(counter + ") CachedName = " + name);
var value = legacyPattern.CachedValue;
Log.Info("CachedValue = " + value);
// check if cell name corresponds to what is being checked
if (name.Equals("Date"))
{
//if (!value.StartsWith("5/23/2012"))
if (!value.StartsWith("5/25/2012"))
errorList.AppendLine("Bad Date = " + value);
}
if (name.Equals("XXX"))
{
if (!(value.Equals("1") || value.Equals("2")))
errorList.AppendLine("Bad XXX= " + value);
}
if (name.Equals("YYY"))
{
if (!value.Equals("ZZZ"))
errorList.AppendLine("Bad YYY = " + value);
}
}
}
}
foundProperGrid = false;
}
var stopTime = DateTime.Now;
var duration = stopTime - startTime;
Log.Info("duration = " + duration);
if (!"".Equals(errorList.ToString()))
{
Log.Info("errorList = " + errorList);
Assert.Fail("Test errors");
}
}

Categories