I've implemented "ChangeCase" keyboard shortcut (like Shift+F3 in MS WORD) for RichTextBox, which changes the text either selected by mouse, or the last word before caret's position. The problem is, it SOMETIMES loses the selection, or moves the caret one word left.
Once it changes the textcase without this changing of caret position, then it never changes the caret position (propably some WPF's internal caching.), so it can only happen the first time i run this function to a portion of text.
The code used is the solution mentioned in here WPF Flowdocument "change case" feature .
One problematic section of code is certainly
end = this.CaretPosition;
EditingCommands.MoveLeftByWord.Execute(null, this);
start = this.CaretPosition;
this.CaretPosition = end;
However I have no idea why it only occurs sometimes and how to fix this.
I thing it has something to do with the execution speed of this Execute() method and some side effects, because at my WPF app it only happens sometimes, but when hosting this WPF control in Winforms, moving the caret one word left happens all the time (if I hold Shift+F3, the cursor moves word by word to the very beginning of the document)
Other problem can be related with changing text of a TextRange, which is resulting in losing the selection? But again, it doesnt happen all the time and I have no clue how to fix it.
Any ideas?
I ended up with 2 options, ignoring this error or implementing the
MoveLeftByWord
logic manully without touching the
CaretPosition
Related
I'm learning how to code C# from scratch. Right now, I'm learning how to build a scene on the command line and update it as necessary.
Part of what i want to do is to "scroll text as it is generated".
The scene is a square command line (Size 100 by 40) and outlined by a box of "#" characters. This is the canvas on which everything is presented.
As the user interacts via simple inputs, the program will provide textual feedback, like a text-based game.
However, unlike a normal text-based game, I cannot allow for the natural flow of the command line to move the canvas. In other words, if I allow for the command line to act naturally, then the canvas would slowly travel upwards until it's no longer visible.
I need a way to read whatever is already being presented on the screen and storing it on memory. Then, I can delete a portion of the screen an paste the previously copied information shifted upwards, making space for new information.
Here is a mockup of what I want to do:
Image 1: desirable outcome
My question is: Is there a way to "read" only a specific portion of the command space and store into memory?
I know you can store whatever is being printed at the moment of printing, or I could keep track of a certain number of previously displayed information and print it again, but I would like to "copy, then paste shifted" a portion of the screen.
PS: This is what I'm trying to avoid
Image 2: Undesirable outcome
Since the top line needs to be moved too, really the only way to do this is to clear the screen and redraw everything. Instead of printing directly to the screen, save the new line to a list, clear the screen, then print that list to the screen, together with the border.
While I haven't found a way to store a portion of the command line to a variable for later use, I've succesfully "scrolled" the text, and found a workaround to "store" it.
Simply put, Console.MoveBufferArea() allows one to select a portion of the command line buffer and move it somewhere else on the buffer.
This way I can:
-Clear whatever space i need at the top by moving the cursor to, say, (1,1) and writing a box of spaces via a string.
-Console.MoveBofferArea() the portion of the buffer a few rows upwards
-Write the new text at the bottom
As a byproduct, i can also "store" a portion of the screen for late use by:
-Setting the buffer to a wider area with Console.SetBufferSize()
-Use Console.MoveBufferArea() to the buffer portion that is outside of normal view
-Do whatever i need to do on the screen
-Use Console.MoveBufferArea() to retrieve the "stored" portion back to where i need it
-Reduce the buffer area (I could also just leave it be)
I am implementing a custom drag and drop interface with winForm Buttons and after viewing several solutions on how to obtain mouse position and check it against control bound have not been able to get it to work.
I have tried:
button.ClientRectangle.Contains(PointToClient(Cursor.Position))
and
button.ClientRectangle.Contains(PointToClient(Control.MousePosition))
Both of these have failed to work. Checking the mouse bounds seem like a simple operation, but I really am stumped.
My speculation of the unexpected values are:
Process of obtaining cursor position may be in wrong corner of cursor image
Method/Function does not work on Buttons for some reason
You are using the wrong object reference, calculating the mouse position relative to the form instead of the button. And you are writing it in a way that make this very hard to debug. Fix:
var pos = button.PointToClient(Cursor.Position);
System.Diagnostics.Debug.WriteLine(pos); // Now it is easy
if (button.ClientRectangle.Contains(pos)) {
// etc...
}
On the CodedUI WpfEdit class there is a way to get the selected text, but I cannot find a way to get the cursor position when nothing is selected (i.e. the index of the caret in the text). Is there anything available for that in the CodedUI framework?
My goal is to assert the position of the cursor in the text contained by the control.
There isn't a codedui method for that but try the following:
add the reference:
using System.Windows.Forms
in the code where you need to get the moue coordinated type:
Point p = new Point(Cursor.Position.X, Cursor.Position.Y);
remember that this is not a relative position to the control but the position of the mouse on the screen.
calculating the position of the point relative to control shouldn't be much problem.
I'm not sure there is a way, and I would imagine that there is a different requirement than actually finding the cursor position.
If you are trying to insert some text, you can always copy the text out to the test method, insert the text, and write it back.
Or, if you need to not do that, you could always use the Keyboard.SendKeys method to send a home command and then any number of right arrow commands you need to place the cursor where you'd like it.
Can you elaborate further as to what exactly you need with the cursor position?
Part of my particular dilemma is that I would like to be able to get the initial position of a drag gesture. Depending on the initial position of that drag gesture, the application would either 1) pan the view or 2) display a menu, but not perform these gestures at the same time (which is where part of struggle lies).
For example, if the user initiated a drag from the very left side of their screen and dragged inwards, a menu would pop in instead of the view panning.
I would also like to be able to execute a double tap gesture without also activating a tap gesture, if that's at all possible. I've tried working with boolean flags - for example,
// ...
if (gesture.GestureType == GestureType.DoubleTap)
{
isDoubleTap == true;
}
// ...
public static Vector2 Tap
{
get
{
if (!isDoubleTap)
return gesture.Position;
// ...
But that doesn't work.
I've tried using TouchCollection - if anyone would like me to elaborate on my issues with that I can, but for now I'll say what I tried hasn't worked. It's entirely possible I may have just goofed as I am a novice when it comes to working with touch input.
I've been working on this for a few days and have done as much searching as I can, and nothing I've found has alleviated my issue - if I happened to have missed something, I apologize.
Thank you for your time!
Concerning start position of a drag:
There is a gesture for a drag ending, so if you receive a drag and its the first one since the last drag ended, thats the initial position.
Concerning tap/doubletap:
MonoGame works the same way as XNA as documented here:
The user tapped the screen twice in quick succession. This
always is preceded by a Tap gesture.
This sounds like a input-bindings design problem more than a technical question imo. Consider also what you can move to instead occur on press or release rather than only making use of gestures.
I have a Pivot which contains a WebBrowser control that practically takes up the whole page (appart from the Pivot header of course).
I would like to figure out how to make the WebBrowser control allow for the user to swipe left/right to activate the Pivot control. Currently it just pans the WebBrowser control left/right
Can this be done??
Thank
While I cannot tell you exactly how to pass the swipes to the pivot, I can tell you how to do a part of the job: how to catch/analyze/disable custom gestures over the WebBrowser.
If I remember correctly, in the 7.0:
the WebBrowser component consisted almost only of an internal TileHost wrapped in some grids/borders
the TileHost did all the work related to processing touch events
the TileHost did it completely internally (in the native layer), without the .Net seeing any manipulation-events (I think), or at least it ignored all the attempts to handle/override the manipulation-event on the upper layer. The WebBrowserInterop class was mostly empty in these matters.
Now, in the 7.5 that I have (maybe on 7.1 too, I dont know), it seems that the MS is working really hard on some WebBrowser manipulation problems --- I think they are working towards having the scrolling/swiping fully processed by the .Net layer. They have written a special class PanZoomContainer and injected them into the VisualTree of WebBrowser's internal template. The WebBrowserInterop was greatly enriched with many tunnels for event notifications. The WebBrowserInterop hooks into PanZoomContainer's ManipulationEvents, then passes them to the native layer. Also, it listens to events/commands from the native layer, called for example "ZoomAndScroll" or "ShowSIP" - and mostly passes them back to the PanZoomContainer. The idea is crystal clear right? They have rewired the event handling from completely-internal to a bit of spaghetti, but have achieved passing them through the PanZoomC.
Now, whats in that for me/us?
It is the PanZoomContainer, whose Mani-Events are inspected. The TileHost does not capture them now. In this version of the WebBrowser control, it's VisualTree consists of some borders, grids, a PanZoomContainer and a TileHost (the renderer). It is similar to that:
WebBrowser
PanZoom
ContentPresenter
Border/Name="border" <- you want this one
TileHost
I've skipped a few Borders and Grids, they are mostly irrelevant to the problem. Now, if the PanZoomContainer's Mani-Events are listened to, let's block them!
Using VisualTreeHelper, just dig deeper and deeper until you find a FrameworkElement.Name=="border". This is the border that wraps the TileHost that is the "renderer" that takes 99% space of the control. Be warned that there's a ContentPresenter, so you may have to wait until the controltemplate gets instantiated (ie. Loaded/LayoutUpdated).
Once you have your hands on that Border, attach all Mani-Event handlers to it: started, delta and completed. PanZoom is a normal xaml/silverlight/.net/etc control, so it actually obeys e.Handled = true :) Now, if you want to disable ie. vertical scrolling, filter the Delta and Completed events for Translation.Y<>0. If you want to disable tapping but leave srolling/panning - filter X==0&Y==0.
And that was the easy part.
The hard part is to experiment with filtering on different Start/Delta/Stop and adjusting the behaviour to your likes.
Although it might look very nice and tempting, this will NOT get you any real/nice results easily. For example, I wrote "if you want to disable vertical scrolling, then set a filter 'if y==0 then e.handled=true' ". Great? easy? Not!
Assume we want to "disable bouncy horizontal panning" while leaving "vertical scrolling". or vice versa, whatever, it is only an example:
Here's a small rectangular device with a sensitive touchscreen. Please make such a vertical swipe/pan/drag on the screen, that the resulting X-compound will be ZERO. If you set such filter, it will be almost impossible to it properly. Your users will want to kill you for forcing them to retry-that-vertical-scrolling for five or more times, until they make a perfect vertical swipe.
Of course you can make it not ==0, but leave some small margin. ok. But if you make the margin too big, the control will catch the intermediate offaxis movement and make a tiny horizontal pan also.. After a few unlucky vertical swipes, the total horizontal pan may accumulate from those small leftovers will accumulate and the diplacement maybe will be noticeable.
But there's some another vile side effects:
Saying shortly, you have commited e.Handled=true. The event is GONE. Dead. Deased. if you just wanted the WebBrowser to SKIP for example horizontal swipes, so that the outer (Pivot) control notices them and processes..... whoops. The event is GONE. Earlier, the TileHost/PanZoomC have extinguished the events, now you have it done yourself. Sounds like a bad joke, eh?
Fortunatelly:
since you have attached your handlers to the bottommost "border", they may not only block the events, but may also actually listen&publish them elsewhere. That is, if those handlers detect an interesting movement, they may e.Handled=true on it, but at the same time they can notify your custom objects about that discovery, and ie. start your storyboards.
mani-events are at hand, but there is also a second layer that listens to the manipulations: the GestureListener/GestureService from the Silverlight Toolkit. It reports events after they are handled by mani-events, but it reports them with no regard to any e.Handled=true that were set on them. It is completely separate gesture-listening mechanism, and you can also use it to detect manipulations that were 'cancelled'
.. and so the fun goes like that and maybe even a little further.
This is similar to putting a Map inside a Pivot - which is discussed here - http://mine.tuxfamily.org/?p=111 - already mentioned in quite a few questions - https://stackoverflow.com/search?q=mine.tuxfamily.org
In general, the advice seems to be usability based:
try to avoid putting controls which use Touch inside the PivotItem's
As an aside, if you are just using the web browser control for a very small amount of static html (so you don't need any scrolling at all) then you could just remove HitTesting from the web browser.
I do not know WP7 Pivot, but are there any Preview* events on the Pivot control that allow you to handle the touches and mark them as processed?
Call the below method and pass your parameter as PivotControl x:name and WebBrowserControl x:name to this method.
Here the WebBrowserControl is placed in second pivot item i.e. Pivot Index is 1 and I am trying to swipe left or right and reach to pivot index 2 or 1 respectively.
public static void SwipteLeftRight(Microsoft.Phone.Controls.Pivot pivotControl, Microsoft.Phone.Controls.WebBrowser webBrowserControl)
{
var gesListener = GestureService.GetGestureListener(webBrowserControl);
gesListener.Flick += ((sen, args) =>
{
if (args.Direction == System.Windows.Controls.Orientation.Horizontal)
{
if (args.HorizontalVelocity < 0)
{
if (((Microsoft.Phone.Controls.PivotItem)(pivotControl.SelectedItem)).Header.ToString().Trim() == "Pivot Item name")
{
pivotControl.SelectedIndex = 2; //Next Pivot item
}
}
else if (args.HorizontalVelocity > 0)
{
if ((Microsoft.Phone.Controls.PivotItem)(pivotControl.SelectedItem)).Header.ToString().Trim() == "Pivot Item name")
{
pivotControl.SelectedIndex = 0; // Previous Pivot Item
}
}
}
});
}
It worked for me. Cheers