I'm looking for the source code to collapse every methods of my active document using the VS2010 Addin.
For the moment I parse the text content of the document trying to match if the line is a method signature. If it is the case, I collapse the method.
TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;
var editPoint = selection.ActivePoint.CreateEditPoint();
editPoint.MoveToLineAndOffset(1, 1);
while (!editPoint.AtEndOfDocument)
{
editPoint.StartOfLine();
var line = editPoint.GetText(editPoint.LineLength).TrimStart();
if (line.StartsWith("public"))
{
selection.MoveToLineAndOffset(editPoint.Line, 1);
_applicationObject.ExecuteCommand("Edit.ToggleOutliningExpansion");
}
// go to the next line
}
Does anyone could tell me if I'm on the good way or if there is an easiest way ?
Maybe I asked not so well my question. My real goal was to collapse all the code : properties, methods, comments with ///, using; but not the regions.
Here is one solution :
// reduce everything like Ctrl+M+O
_applicationObject.ExecuteCommand("Edit.CollapsetoDefinitions");
// save the cursor position
TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;
var selectedLine = selection.ActivePoint.Line;
var selectedColumn = selection.ActivePoint.DisplayColumn;
// open the regions
selection.StartOfDocument();
while (selection.FindText("#region", (int)vsFindOptions.vsFindOptionsMatchInHiddenText))
{
// do nothing since FindText automatically expands any found #region
}
// put back the cursor at its original position
selection.MoveToDisplayColumn(selectedLine, selectedColumn);
I hope this could help
Related
The code works for Word and Outlook but fails with PowerPoint in that only the first character or first word of the textbox ever gets selected. Is this a bug? Is there any workaround? Try this on a simple PowerPoint slide in PowerPoint 2013.
private static async Task<string> getText(double x, double y)
{
string result = null;
try
{
var location = new System.Windows.Point(x, y);
AutomationElement element = AutomationElement.FromPoint(location);
object patternObj;
if (element.TryGetCurrentPattern(TextPattern.Pattern, out patternObj))
{
var textPattern = (TextPattern)patternObj;
var range = textPattern.RangeFromPoint(location);
range.ExpandToEnclosingUnit(TextUnit.Word);
range.Select();
var text = range.GetText(-1).TrimEnd('\r');
return text.Trim();
}
else
{
return "no text found";
}
}
catch (Exception ex)
{
return ex.Message;
}
}
You cannot see it from the screenshot, but the mouse is on "first" not "stuck", but regardless of where the mouse is placed, it always is stuck. Maybe this is fixed in PowerPoint 2016?
When I look at the bounding box for the range it is always the whole element, rather than the selected word. That could be part of the problem of why RangeToPoint is not working.
Original posted in MSDN but no response...
Update. If I use
text = printRange(range, text);
while (range.Move(TextUnit.Word, 1) > 0)
{
text += Environment.NewLine;
text = printRange(range, text);
}
I get
This behavior is probably due to a limitation in PowerPoint 2013, and I expect you can't work around it using UIA. When you call RangeFromPoint(), the UIA provider hit beneath the mouse, (ie the one that's implementing IUIAutomationTextPattern::RangeFromPoint(),) is meant to return a degenerative (ie empty) range where the mouse cursor is. Then the UIA client can expand the returned range to get the surrounding character, word, line or paragraph.
However, as you point out, PowerPoint 2013 isn't doing that. I've just written the test code below, (using a managed wrapper for the native Windows UIA API generated by tlbimp.exe,) and found that PowerPoint apparently returns a TextRange for the entire text box beneath the cursor. When I ran the code, I found that I did get the expected word beneath the cursor in WordPad, Word 2013 and PowerPoint OnLine, but not PowerPoint 2013. I got the same results when I ran the Text Explorer tool that's part of the Inspect SDK tool. The image below shows Text Explorer reporting that the text returned from PowerPoint 2013 is the entire text in the a text box, when the mouse is hovering over one of those words.
(I should add that for the test code below to work at all, I think the current display scaling setting needs to be at 100%. I've not added code to account for some other scaling being active.)
I don't know if this is fixed in PowerPoint 2016, I'll try to look into that and let you know.
Thanks,
Guy
private void buttonGetTheText_Click(object sender, EventArgs e)
{
labelText.Text = "No text found.";
IUIAutomation uiAutomation = new CUIAutomation8();
Point ptCursor = Cursor.Position;
tagPOINT pt;
pt.x = ptCursor.X;
pt.y = ptCursor.Y;
// Cache the Text pattern that's available through the element beneath
// the mouse cursor, (if the Text pattern's supported by the element,) in
// order to avoid another cross-process call to get the pattern later.
int patternIdText = 10014; // UIA_TextPatternId
IUIAutomationCacheRequest cacheRequestTextPattern =
uiAutomation.CreateCacheRequest();
cacheRequestTextPattern.AddPattern(patternIdText);
// Now get the element beneath the mouse.
IUIAutomationElement element =
uiAutomation.ElementFromPointBuildCache(pt, cacheRequestTextPattern);
// Does the element support the Text pattern?
IUIAutomationTextPattern textPattern =
element.GetCachedPattern(patternIdText);
if (textPattern != null)
{
// Now get the degenerative TextRange where the mouse is.
IUIAutomationTextRange range = textPattern.RangeFromPoint(pt);
if (range != null)
{
// Expand the range to include the word surrounding
// the point where the mouse is.
range.ExpandToEnclosingUnit(TextUnit.TextUnit_Word);
// Show the word in the test app.
labelText.Text = "Text is: \"" + range.GetText(256) + "\"";
}
}
}
I can suggest only Python code getting caption text of the slide (for example). Sorry, I have no time to re-write it on C#. You can play with the PowerPoint.Application COM object and MSDN example of Power Point automation.
from __future__ import print_function
import win32com.client as com
pp = com.Dispatch('PowerPoint.Application')
print(pp.Presentations[0].Slides[8].Shapes[0].TextFrame.TextRange.Text)
This may be a noobish question, but in my records in Coded UI Tests, I have recorded a lot of controls that don't have enough defined properties to be found in playback.
For exemple:
public HtmlEdit UIItemEdit
{
get
{
if ((this.mUIItemEdit == null))
{
this.mUIItemEdit = new HtmlEdit(this);
#region Search Criteria
this.mUIItemEdit.SearchProperties[HtmlEdit.PropertyNames.Id] = null;
this.mUIItemEdit.SearchProperties[HtmlEdit.PropertyNames.Name] = null;
this.mUIItemEdit.SearchProperties[HtmlEdit.PropertyNames.LabeledBy] = null;
this.mUIItemEdit.SearchProperties[HtmlEdit.PropertyNames.Type] = "SINGLELINE";
this.mUIItemEdit.FilterProperties[HtmlEdit.PropertyNames.Title] = null;
this.mUIItemEdit.FilterProperties[HtmlEdit.PropertyNames.Class] = null;
this.mUIItemEdit.FilterProperties[HtmlEdit.PropertyNames.ControlDefinition] = "type=\"text\" value=\"\"";
this.mUIItemEdit.FilterProperties[HtmlEdit.PropertyNames.TagInstance] = "5";
this.mUIItemEdit.WindowTitles.Add("http://cms.home.psafe.com/");
#endregion
}
return this.mUIItemEdit;
}
In this post, I learned about SearchProperties, but it doesn't look to be an appropriate solution in this case.
Is there any other way to wrap these controls properly?
You might be able to find it if its containing element can be found. You can use the containing element to scope the search. So, find that element's parent, then find an input type=text within it:
var container = new HtmlControl(bw); //where bw is the browser window
HtmlDiv parentDiv = new HtmlDiv(container);
parentDiv.SearchProperties[HtmlDiv.PropertyNames.Id] = "theIdOfYourDiv";
HtmlEdit edt = new HtmlEdit(parentDiv); //the search scope is narrowed down to the div only. This may be enough to find your control with the search property.
edt.SearchProperties[HtmlEdit.PropertyNames.Type] = "SINGLELINE";
You have two options:
Try crowcoder's solution of searching in the parent. The problem with this solution is when you move a control around you're going to be changing code a lot.
Add an Id property to all your controls in the HTML, this will make your Coded UI more robust and responsive to changes in the UI.
I am having trouble type casting and using the right interfaces. I have a function that loops through all text elements with a specific property set. Once a match is found, I want to be able to select this text element or make it active or highlighted or whatever on the map. Code below.
protected override void OnClick(Item item)
{
IMxDocument pDoc = ValidateInterface.GetMxDocument();
IActiveView pLayout = (IActiveView)pDoc.PageLayout;
IGraphicsContainer pGraphicsCont = (IGraphicsContainer)pDoc.PageLayout;
pGraphicsCont.Reset();
IElementProperties _ElemProps = null;
while ((_ElemProps = (IElementProperties)pGraphicsCont.Next()) != null)
{
if (_ElemProps.CustomProperty is IPropertySet2)
{
ITextElement _textElement = (ITextElement)_ElemProps;
IPropertySet2 _propertySet = (IPropertySet2)_ElemProps.CustomProperty;
MessageBox.Show("Before I compare item to string");
if (item.Caption == Convert.ToString(_propertySet.GetProperty(NAME_STRING)))
{
//Problems start here
MessageBox.Show("Inside the IF statement");
IGraphicsContainerSelect _SelectMyElement = null; // = (IGraphicsContainerSelect)pGraphicsCont;
ITextElement _newTextElement = (ITextElement)pGraphicsCont;
IElement TestElement = _newTextElement as IElement;
_SelectMyElement.SelectElement(TestElement);
}
}
}
}
Nothing is being selected though on my map. I'm looping through each graphic element (IGraphicContainer) on the map. Once I find a match, I want to select that Graphic Element. I am trying to utilize IGraphicContainerSelect to do this. It takes an IElement variable type as a parameter, thus why I'm trying to cast it. But again, noting is being selected. This all happens when I click a button.
Any help on this would be greatly appreciated. Thanks in advance.
Try to refresh your map.
I think the better way using pLayout.PartialRefresh or pScreenDisplay.Invalidate methods.
pLayout.PartialRefresh(esriViewDrawPhase.esriViewGraphicSelection,null,pLayout.Extent)
OR
IScreenDisplay pScreenDisplay = pLayout.ScreenDisplay;
pScreenDisplay.Invalidate(null,false,esriViewGraphicSelection);
pScreenDisplay.UpdateWindow();
See help :http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000242000000
FastColoredTextbox is an user-control that can be downloaded in this url, it looks like this:
Its an amazing control but only can select one word when doubleclicking on the text, can't hold the mouse to select more words, so it only selects the entire current word over the mouse pointer even if you try to move the mouse cursor to left or right to select more text.
I have not found any information explaining the problem, and all of the official example projects has this problem.
Nobody means how to make an AutoWordSelection equivalent of a default TextBox for a FastcoloredTextbox control, but even the most important thing is:
How to select just more than one word with the mouse?
UPDATE:
#mostruash answer is very instructive but in all this time I could not carry out the modifications by myself.
I need a huge help from a C# programmer to carry out this task, my knowledge of C# is very low and the modifications that I made to the source did not work (don't compiled), I went back to the original user-control source to not end up spoiling more. I hate to say this but this time I need the job done, this source is too much for me.
If I'm requesting for too much then maybe with the necesary extended instructions of a C# developer, explaining how to accomplish this step by step, maybe I could carry it out by myself.
UPDATE
A video that demostrates the problem:
https://www.youtube.com/watch?v=Cs2Sh2tMvII
UPDATE
Another demo, I show what the FastColoredTextBox can't do but I would like to do like every other text-editor can do:
I've checked the source code of the project. Dragging is cancelled if a double click occurs and SelectWord is called.
You could modify the source code to include the feature that you request. (https://github.com/PavelTorgashov/FastColoredTextBox). In that case:
You must trace selections that start with double clicks.
Instead of calling SelectWord function, use the Selection class and draggedRange attribute to mark the selected word in OnMouseMove.
You also must handle deselection of words in OnMouseMove.
You must also select spaces between words in OnMouseMove.
The double click is handled in the code piece below:
if (!isLineSelect)
{
var p = PointToPlace(e.Location);
if (e.Clicks == 2)
{
mouseIsDrag = false; //Here, drag is cancelled.
mouseIsDragDrop = false;
draggedRange = null; //Drag range is nullified
SelectWord(p); //SelectWord is called to mark the word
return;
}
if (Selection.IsEmpty || !Selection.Contains(p) || this[p.iLine].Count <= p.iChar || ReadOnly)
OnMouseClickText(e);
else
{
mouseIsDragDrop = true;
mouseIsDrag = false;
}
}
EDIT:
This may require a lot of work to accomplish. So maybe you should use another tool/library. I have not studied the whole source code so there will probably be additional steps to those provided above.
For example, to trace double clicks you can do the following:
Define a class variable/property in FastColoredTextbox.cs: bool isDoubleClick.
Set it to true in OnMouseDown under if(e.Clicks == 2) condition. Set it to false in all other conditions.
Set it to false in OnMouseClick or OnMouseUp or in other relevant mouse event handlers.
That way you will know if series of mouse events had started with a double click event or not. Then you would act accordingly in OnMouseMove because that is where you (un)mark characters or (un)mark words.
LAST WORDS OF CAUTION:
The author of that project did not include any inline comments or any other means of documentation so you will be studying the code line by line to understand what each function/part does.
Add the following statement between Line 5276 and line 5277 in the class FastColoredTextBox.cs:
SelectWord(p);
mouseIsDrag = true; // here
return;
Note that implementing the ultimate behavior would require a good bunch of coding. Whereas the workaround mentioned above might satisfy your needs.
As #mostruash points out in his answer, that is the place where author cancels the mouse drag. Not sure why he deliberately prevents this feature. Only he knows.
if (e.Clicks == 2)//Line 5270
{
mouseIsDrag = false;
mouseIsDragDrop = false;
draggedRange = null;
SelectWord(p);
return;
}
I didn't read whole code, and I have no reason to do it. I just checked quickly and removed them. And it works as you expect.
if (e.Clicks == 2)//Line 5270
{
//Comment or remove completely.
//mouseIsDrag = false;
//mouseIsDragDrop = false;
//draggedRange = null;
SelectWord(p);
return;
}
Note: Am not sure this breaks something else, I've not tested. At least that works. Test it yourself.
My solution is a bit tweaky, but seems to work at first glance.
You have to make some changes in the Code:
Add mouseIsWholeWordSelection flag and a Range variable which can store the initial selected range after double click (best after line 100, I guess):
private bool mouseIsWholeWordSelection;
private Range mouseIsWholeWordSelectionBaseRange;
Change the selection code for double click event as stated above and extend it a bit (line 5222):
if (e.Clicks == 2)
{
//mouseIsDrag = false;
mouseIsDragDrop = false;
mouseIsWholeWordSelection = true;
//draggedRange = null;
SelectWord(p);
mouseIsWholeWordSelectionBaseRange = Selection.Clone();
return;
}
Add evaluation of dragging event for recreating selection (line 5566):
else if (place != Selection.Start)
{
if (mouseIsWholeWordSelection)
{
Selection.BeginUpdate();
var oldSelection = Selection.Clone();
SelectWord(place);
if (Selection.End >= mouseIsWholeWordSelectionBaseRange.End)
{
Selection.Start = (mouseIsWholeWordSelectionBaseRange.Start > Selection.Start) ? mouseIsWholeWordSelectionBaseRange.Start : Selection.Start;
Selection.End = mouseIsWholeWordSelectionBaseRange.End;
}
else if (Selection.Start < mouseIsWholeWordSelectionBaseRange.End)
{
Selection.Start = new Place(Selection.End.iChar, Selection.End.iLine);
Selection.End = mouseIsWholeWordSelectionBaseRange.Start;
}
Selection.EndUpdate();
DoCaretVisible();
Invalidate();
}
else
{
Place oldEnd = Selection.End;
Selection.BeginUpdate();
if (Selection.ColumnSelectionMode)
{
Selection.Start = place;
Selection.ColumnSelectionMode = true;
}
else
Selection.Start = place;
Selection.End = oldEnd;
Selection.EndUpdate();
DoCaretVisible();
Invalidate();
}
return;
}
Add at every place where isMouseDrag is being set to false:
isMouseWholeWordSelection = false;
And there you go.
I am using Microsoft Visio as a COM object in my C# application. I want to auto arrange shapes on a Visio page. What should I code for this task? The shapes are database entities.
userView.Shapes.SomeMethod();
userView is name of COM object but what should SomeMethod be?
I know this is an 'older' question, but
I'm working on something quite similar, and have managed to 'Auto-Layout' a flow chart with the following code:
public enum GraphStyles { TopDown, LeftRight };
public void ArrangeGraph(GraphStyles Style)
{
if (Style == GraphStyles.TopDown)
{
// set 'PlaceStyle'
var placeStyleCell = VisApp.ActivePage.PageSheet.get_CellsSRC(
(short)VisSectionIndices.visSectionObject,
(short)VisRowIndices.visRowPageLayout,
(short)VisCellIndices.visPLOPlaceStyle).ResultIU = 1;
// set 'RouteStyle'
var routeStyleCell = VisApp.ActivePage.PageSheet.get_CellsSRC(
(short)VisSectionIndices.visSectionObject,
(short)VisRowIndices.visRowPageLayout,
(short)VisCellIndices.visPLORouteStyle).ResultIU = 5;
// set 'PageShapeSplit'
var pageShapeSplitCell = VisApp.ActivePage.PageSheet.get_CellsSRC(
(short)VisSectionIndices.visSectionObject,
(short)VisRowIndices.visRowPageLayout,
(short)VisCellIndices.visPLOSplit).ResultIU = 1;
}
else if (Style == GraphStyles.LeftRight)
{
// set 'PlaceStyle'
var placeStyleCell = VisApp.ActivePage.PageSheet.get_CellsSRC(
(short)VisSectionIndices.visSectionObject,
(short)VisRowIndices.visRowPageLayout,
(short)VisCellIndices.visPLOPlaceStyle).ResultIU = 2;
// set 'RouteStyle'
var routeStyleCell = VisApp.ActivePage.PageSheet.get_CellsSRC(
(short)VisSectionIndices.visSectionObject,
(short)VisRowIndices.visRowPageLayout,
(short)VisCellIndices.visPLORouteStyle).ResultIU = 6;
// set 'PageShapeSplit'
var pageShapeSplitCell = VisApp.ActivePage.PageSheet.get_CellsSRC(
(short)VisSectionIndices.visSectionObject,
(short)VisRowIndices.visRowPageLayout,
(short)VisCellIndices.visPLOSplit).ResultIU = 1;
}
else { throw new NotImplementedException("GraphStyle " + Style.ToString() + " is not supported"); }
VisApp.ActivePage.Layout();
}
Hopefully this saves someone some time.
It took me awhile to figure it out.
I'm using visio 2010 and visual studio 2010
This might help
Pertinent quote
To lay out a subset of the shapes of a page, master, or group,
establish a Selection object in which the shapes to be laid out are
selected, and then call the Layout method. If the Layout method is
performed on a Selection object and the object has no shapes selected,
all shapes in the page, master, or group of the selection are laid
out.
EDIT: noonand 2012-09-21 Added information about the LayoutIncremental method
Just had another look at the object model and it appears the method you want is the LayoutIncremental method
Excerpt from the relevant help topic says:
Page.LayoutIncremental(AlignOrSpace, AlignHorizontal, AlignVertical, SpaceHorizontal, SpaceVertical, UnitsNameOrCode)
I needed to do something similar a while ago..
I used Microsofts Glee library for the layout. There are very good samples included with the download which show you how to add nodes and relations and make them "auto arrange". However do note that Glee is not free for commercial use.
http://research.microsoft.com/en-us/downloads/f1303e46-965f-401a-87c3-34e1331d32c5/default.aspx
And then I used this example for converting the calculated positions from Glee to a Visio drawing.
http://www.syntaxwarriors.com/2012/generating-visio-uml-diagrams-from-c/
Basically what I do is add all my nodes and relations too Glee and then get a list of nodes and their positions and add them to Visio using the second link.
Here is a graph example of what Glee can do: