I posted a question similar to this earlier, however, after thinking about it and testing the answers, I believe I misinterpreted the answers and the answerer(s) misinterpreted me. The original question is here. I think people believed that I just wanted to highlight strings, I didn't state my exact purpose. So, I will now:
What I've been trying to do lately is create a 100% from scratch text box in C++ CLR using GDI+. I've gotten to the challange of placing the caret when the user clicks in the textbox. Doing simple math (Where they clicked divided by line width) I can figure out which line they clicked. But in order to get the character clicked, I need (unless there are better ways) to compare the bounding rectangles of all the characters in the line and place the caret before the one the mouse fits into. In order to do this, I need to get the exact bounds of each individual character, not an entire string.
I've already tried a few things, none of which seemed to work:
Graphics::MeasureString is not recommended by anyone, nor does
it give what I want
TextRenderer::MeasureText is more accurate, but for this not accurate enough
Graphics::MeasureCharacterRanges has a 32 character
cap, and I'm expecting lines to be over 32 characters long in some
cases
I believe I can't use these methods, unless there are ways around their limitations. I hope I made my problem and expected solution a lot more clear than I previously did.
Because of the way text is kerned and anti-aliased, the boundary of a character depends on all of the characters to the left of it. However you don't need to know every character boundary, only the ones on either side of your click point. You can find those with a binary search - split your string in half, measure that (using TextRenderer::MeasureText), and determine if it's to the left or right of your click point. Keep narrowing down the size of the string until there's only one possibility remaining.
Related
I'm making a game in C++ console using UTF-16 characters to make it little bit more interesting, but some characters are different size then others. So, when I print the level, things after character are moved further than others. Is there any way how to add spacing between characters with some console function, I try to google something helpful, but I have not found nothing.
I tried to change font size by CONSOLE_FONT_INFOEX, but it changed nothing, maybe i implement it in the wrong way, or it not work with UTF-16 characters.
// i tried this
CONSOLE_FONT_INFOEX cfi;
cfi.cbSize = sizeof(cfi);
cfi.dwFontSize.X= 24;
cfi.dwFontSize.Y= 24;
Unfortunately I expect that this will heavily depend on the particular console you're using. Some less Unicode-friendly consoles will treat all characters as the same size (possibly cutting off the right half of larger characters), and some consoles will cause larger characters to push the rest of the line to the right (which is what I see in the linked image). The most reasonable consoles I've observed have a set of characters considered "double-wide" and reserve two monospace columns for those characters instead of one, so the rest of the line still fits into the grid.
That said, you may want to experiment with different console programs. Can I assume you are on Windows? In that case, you might want to give Windows Terminal a try. If that doesn't work, there are other console programs available, such as msys's Mintty, or ConEmu.
So, after some intense googling i found the solution. And solution is fight fire with fire. Unicode include character Thin Space, that is 1/5 of the normal space, so if i include two of them with one normal space after my problematic character, the output is diplaying how i want. If anybody runs into some simliar issue, unicode have lot of different sized spaces. I found Website that shows them all of them, with their propperties.
fixed output picture
The time of day that you have missed. Recently I began to study the expressive expressions, but the task before me is too complicated.
I think many people need the ability to quickly format texts of almost any type. Problem is not easy and I hope to get a solution to this problem from professionals.
If you use a limited breakdown for each line, then only large lines are broken which is much better. That is, to break only those lines that are larger than a certain size and which are more or less evenly broken Correct formatting of the text is quite Difficult to take into account a lot, I will go out for a long time. As you can see, there are small lines and they have to be sent back by connecting the previous line, but the problem is. And again have to apply formatting. But it is unclear whether this new formatting will create new problems.
All this is write in the macro via notepad ++ one after another and use.
However, it is necessary to solve the most important problems:
It is important to
I want to immediately note: textFX does not offer. My attempts to write a macro with textFX (including attempts with 75 or a number from the clipboard failed, the text was written with unreadable code), I sent a corresponding message to the site notepad ++ a day ago
Use a regular point also do not offer. The fact is that notepad ++ macro does not understand the point of replacing the indentation with spaces by default 4pcs. (Yes, the macro must also indent the text, but this is all right)
About soft wordwrap (not formatted just click) is also not worth talking about.
inscrease line indent 2-4
split lines
descrease line indet 2-4
^(.?)$\s+?^(?=.^\1$) null
2017 (\d+:\d+) 17
subscribe .+$ null
(^.{1,30}$)\R \1
\r\r\n \n
^ spaces\1
i create macro and solved more problems
I was wondering about this, so I did quite a bit of google searches, and came up with the SetWrapMode(self, mode) function. However, it was never really detailed, and there was nothing that really said how to use it. I ended up figuring it out, so I thought I'd post a thread here and answer my own question for anyone else who is wondering how to make an stc.StyledTextCtrl() have word wrap.
Ok, so first you need to have your Styled Text Control already defined, of course. If you don't know how to do this, then go watch some tutorials on wxPython. I recommend a youtuber called sentdex http://youtube.com/sentdex, who has a complete series on wxPython, as well as Zach King, who has a 4 episode series on making a text editor. Anyways, my definition of my text control looks like this: self.control = stc.StyledTextCtrl(self, style=wx.TE_MULTILINE). Yours could look a little different, but the overall idea is the same.
self.control = stc.StyledTextCtrl(self, style=wx.TE_MULTILINE)
Many places will tell you that it will need to be SetWrapMode(self, mode), but if you have self.CONTROLNAME at the beginning like I do, you will get an error if you also put self as an argument because self. at the beginning counts as the argument. However, if your control is defined with self.CONTROLNAME and you don't put the self.CONTROLNAME at the beginning of your SetWordWrap()function, you'll also get an error, so be careful with that. Mode just has to be 0 or 1-3. So for example, mine looks like this: self.control.SetWrapMode(mode=1). Word wrap mode options:
0: None |
1: Word Wrap |
2: Character Wrap |
3: White Space Wrap
My final definition and word wrap setup looks like this:
self.control = stc.StyledTextCtrl(self, style=wx.TE_MULTILINE)
self.control.SetWrapMode(mode=1)
And that's it! Hope this helped.
Thanks to #Chris Beaulieu for correcting me on an issue with the mode options.
I see you answered your own question, and you are right in every way except for one small detail. There are actually several different wrap modes. The types and values corresponding to them are as follows:
0: None
1: Word Wrap
2: Character Wrap
3: White Space Wrap
So you cannot enter any value above 0 to get word wrap. In fact if you enter a value outside of the 0-3 you should just end up getting no wrap as the value shouldn't be recognized by Scintilla, which is what the stc library is.
It would be more maintainable to use the constants stc.WRAP_NONE, stc.WRAP_WORD, stc.WRAP_CHAR and stc.WRAP_WHITESPACE instead of their numerical values.
There's a completion type that isn't listed in the vim help files (notably: insert.txt), but which I instinctively feel the need for rather often. Let's say I have the words "Awesome" and "SuperCrazyAwesome" in my file. I find an instance of Awesome that should really be SuperCrazyAwesome, so I hop to the beginning of the word, enter insert mode, and then must type "SuperCrazy".
I feel I should be able to type "S", creating "SCrazy", and then simply hit a completion hotkey or two to have it find what's to the left of the cursor ("S"), what's to the right ("Crazy"), regex this against all words in the file ("/S\w*Crazy/"), and provide me with a completion popup menu of choices, or just do the replace if there's only one match.
I'd like to use the actual completion system for this. There exists a "user defined" completion which uses a function, and has a good example in the helps for replacing from a given list. However, I can't seem to track down many particulars that I'd need to make this happen, including:
How do I get a list of all words in the file from a vim function?
Can I list words from all buffers (with filenames), as vim's complete does?
How do I, in insert mode, get the text in the word before/after the cursor?
Can completion replace the entire word, and not just up to the cursor?
I've been at this for a couple of hours now. I keep hitting dead ends, like this one, which introduced me to \%# for matching with the cursor position, which doesn't seem to work for me. For instance, a search for \w*\%# returns only the first character of the word I'm on, regardless of where I'm in it. The \%# doesn't seem to anchor.
Although its not exactly following your desired method in the past I've written https://github.com/mjbrownie/swapit which might perform your task if you are looking for related keywords. It would fall down in this scenario if you have hundreds of matches.
It's mainly useful for 2-10 possible sequenced matches.
You would define a list
:SwapList awesomes Awesome MoreAwesome SuperCrazyAwesome FullyCompletelyAwesome UnbelievablyAwesome
and move through the matches with the incrementor decrementor keys (c+a) (c+x)
There are also a few other cycling type plugins like swap words that I know of on vim.org and github.
The advantage here is you don't have to group words together with regex.
I wrote something like that years ago when working with 3rd party libraries with rather long CamelCasePrefixes in every function different for each component. But it was in Before Git Hub era and I considered it a lost jewel, but search engine says I am not a complete ass and posted it to Vim wiki.
Here it is: http://vim.wikia.com/wiki/Custom_keyword_completion
Just do not ask me what 'MKw' means. No idea.
This will need some adaptation to your needs, as it is looking up only the word up to the cursor, but the idea is there. It works for current buffer only. Iterating through all buffers would be sluggish as it is not creating any index. For those purposes I would go with external grep.
Well.. I know that title is not that clear, I couldn't think of better one.
I wanna know how to do this...
when you have edit box and it only can show 10 characters.
Something like this
ssssssssss
let just say i have more than 10 characters. Some of them will go in the back.
Like we have this string "123456789010" it will show just these ones "3456789010".
My problem is that some characters are small and don't take that much space and some do.
So i can't find a way to break the string and get some characters in the back.
any idea?
Try this in Style type in edit box use ES_MULTILINE for use multiple lines.
edit1=CreateWindowA("edit","edit box",WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE,120,160,200,200,hWnd,(HMENU)IDI_EDIT,hInstance,0);
You can calculate the display-length of the string in your control (there are several function for that) and adjust the size of the control accordingly.
you only want to see the far left or far right?
here is your string "0123456789"
you can only display 5 values due to pixel size of box....
do you want it to be "...56789" more like "56789"
or "01234..." more like "01234"?