So I'm building a custom control in C# (not WPF), and I basically want to implement text highlighting with the mouse.
How do I efficiently find the character at a given Point (say where the mouse is clicked) in a string? I have the layout rectangle of the string as it was drawn and I could calculate the length of the string up to every character until I find the one closest to where the mouse is clicked... but there has to be a better way. Any suggestions?
If I had to do this, I would look at it backward.
I'd keep the text entered as a string member in the control, so at all times I know what is actually entered in the control (like the Text property in a TextBox).
Then I would use the TextRenderer.MeasureText() method (http://msdn.microsoft.com/en-us/library/7sy6awsb.aspx) and I would keep measuring the length of the string repeatedly until I pass the X coordinate of the mouse within the control, right then I know how many characters are chosen.
For example, assume the user has the text Hello written in the control.
And the X coordinate hit right between the l and the o, which could be of value 20.
Then I would repeatedly calling MeasureText() on the following strings:
H: width of 5 pixels.
He: width of 10 pixels.
Hel: width of 14 pixels.
Hell: width of 17 pixels.
Hello: width of 22 pixels.
Then I know the mouse was hit between the l and the o, so I would then highlight the text Hell.
Sorry for the distasteful example =)
UPDATE:
You can optimize this a bit by calculating the lengths in a binary-search-tree-like fashion.
Just like you would look up a name in the phonebook, you don't look page by page, but rather split in half as you go along, getting closer and closer until it's definitely between these two pages.
Similarly, especially for long string values of the control, calculate the width of the entire string, then half its length, and split there. I think that would be O(n log n) at that point.
Of course it would be O(1) if the text is of fixed width =)
Another thing you can do to build upon BeemerGuy's great suggestion is to precalculate an array of offsets. As the string is changed (the user types or the property is set in code) you can recalculate the offset array. That will save you the call to MeasureFont on the mouse clicks and will make finding the character trivial. You basically iterate the array until you find the nearest character. Since the offsets are implicitly sorted by value you can even use a binary search to make it more effective.
Related
So, I have some simple figure (circle, ellipse, rectangle of closed polygon) and I need to fill only part of it.
I mean, I have GraphicsPath or similar object (set of points) and now I can simply fill the whole figure with, for example, orange color.
What I need: user enters 25% and I fill only 25% of the figure, starting from some side (top/bottom).
Maybe, it will be nessesary to find some sub-figure or (bad idea, I know) check all the points in on the field and fill them (only those which inside figure) one by one untill their amount will be 1/4 from the area of the figure. But it won't be so fast especially when image is about 5-6000 pixels from one side.
Here's sample what I have now and what I need for 25%. Important: instead of 25% can be any value.
Project: C# .net 3.5 WinForms
UPD:
Basic usecase.
User draws a figure (circle, ellipse, rectangle, polygon)
User enters value from 0 to 100 (percents)
I fill figure from bottom to the top until I filled amount of area (!), which is equal to user's value
I'm open for any ideas even without code.
As part of my self-education of programming I decided to make a snake in C#. The problem I have is about the client size of the game form.
I want player to be able to scale the window of the game, which is divided into 25 x 25 grid (every coordinate is like "one pixel") - it means, that at any moment, the window is divided into 25 x 25 identical squares.
The problem I get is near this code:
int SquareSide = (ClientSize.Width / 25);
When I set the ClientSize strictly to for example 600 x 600, which is a multiple of 25, everything goes OK. But when I don't (for example by manual resizing, which can change the size to, for example, 711 x 711), it creates at the right side a 'strip', which seems to be the rest of pixels, which can't be used because we are dividing to integer number.
My question is - is there any not-extremely-hard way to achieve dividing ANY client size of form into 25 x 25 grid without this problem? I tried using double, but FillRectangle method doesn't accept it.
I hope my question is understandable and thank you for replies.
To tell you the truth, there is
g.FillRectangle(Brush b, RectangleF rect)
RectangleF is a rectangle whose coordinates are float.
So you can use:
float SquareSide = (ClientSize.Width * 1f / 25);
I would try to simply handle OnResize event of the window, and at the moment user finishes rezise it, force the size that program need for perfect fit of the grid.
So for example at the moment user releases mouse and you figure out that one dimensions of the window 711x711, bring it to nearest correct fit 700x700.
In this way you guarantee good user experience on different monitor resolutions and for you guarantee a correct fit of the grid you draw.
Hope this helps.
Switch to float coordinates for everything. Make sure your game looks OK when lines do not have whole pixel coordinates. Make sure you "find next cell" code also works with floats, including mouse position detection if needed.
The other approach is to be happy with integer coordinates (and cells of the same size) and make page layout flexible to accomodate some unused space for odd 711x711 layouts (i.e. just center the field and keep some variable width border).
I am custom drawing a text box and now I am implementing the part where the user can click on a line and have the cursor move to where he clicked.
I know how to get the row of text he clicked on because the character height is constant across all fonts, but not the column, because I'm not sure how to say "get me all the text that can be drawn before this amount of pixels," and because character width is not consistent unless you're using a fixed-width font, which is not a guarantee.
So I have the point from which I'm drawing the string (0) then I have the point that the user clicked. How do I get the string index of the character they clicked on?
Extra info: I am drawing the text by storing the lines in a List then iterating the list and using Graphics.DrawString on each line.
There is no simple method to find the character at a pixel.
However you can find the pixels that a string will fill. Use the Graphics.MeasureCharacterRanges method. You can perform a binary search on your string until you find the string where MeasureCharacterRanges returns your cursor position.
Note: You might see the Graphics.MeasureString method and be tempted to use that. DON'T! That method doesn't return accurate measurements. I can't remember why, but you will do your head in if you try!
I want to programmatically place text on an image in an area where there is least "going on". It has been some time since I took Computer-Vision, could someone point me in the right direction. Either with respect to C# or Matlab?
I suggest dividing the image into distinct regions, each the size of the space you need for the text overlay. Calculate some measure of visual "energy", such as standard deviation, and choose the region with the lowest value. You could also slide a window around, looking for an arbitrary space of low energy, but this would be computationally much more expensive.
If you have the image processing toolbox for Matlab, you can run an entropy filter (ENTROPYFILT) on the image, matching the filter size to the size of your text. Then, all you need to do is find the filter-result with the smallest value, and you have the center of where you want to put the text.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
split a console in two parts for two outputs
I want to divide my console screen in four part and each part work separately,
I think in this we use thread but I am not getting how to use?
You can't just divide the console, but you have enough control over it to do it yourself.
See Console class reference. You can SetCursorPosition, set window position and size. Make your own method - something like WriteToArea(int area, string text). Track bounds of areas and wrap text to stay inside of area. Each area must have its own cursor position, track it too. And think how you will handle area overflow (or you need just four columns?)
Edit: I'm not going to give you fish, but here is your fishing rod ^_^
Get dimensions of console window (Console.WindowWidth) in columns
Divide that by four to get each area's width and calculate start and end column of each area. For example, if your console is 80 columns wide, you should get [0, 19], [20, 39], [40, 59], [60, 79] - these pairs are bounds of each area.
Next, store cursor position for each area (initially that would be [left bound, 0])
Implement method writeToArea(int area, String text):void. That's the hardest part. First, you SetCursorPosition into stored position for that area. Next, break text into parts that fit into area. Take into account how much space is left on current column. Write text with series of Console.Write, line by line. Then update cursor position for that area [CursorLeft, CursorTop].
Write, debug and have fun!
Well, theres libraries for this sort of thing. But you can't just split up the console window.
If you want more information about the library, check it out at sourceforge.