I tried to draw a selected text using two TextOut call and TA_UPDATECP flag but when I move the selected area, the characters are moving a bit.
Does someone know the correct way to do that ?
According to the MSDN documentation, when you have set the TA_UPDATECP flag using SetTextAlign(), TextOut() ignores its position parameters in favor of the device context's current position. Without seeing your code, I suspect that your drawing algorithm calls TextOut() with a current position that differs slightly based on the selection.
As a debugging strategy, you can call GetCurrentPositionEx() just before you call TextOut() to obtain the current position and make sure it matches your expectation for where the text should be drawn.
I believe that antialiasing and ClearType can draw text at fractional pixel positions. If you draw a string of text, and then try to redraw a portion of the middle, there might not be a way for you to draw text starting at exactly the same position as those characters in the middle. The trick seems to be to redraw the entire string, but with a clipping region for the selected text.
Chapter 4 in this tutorial on writing a Win32 text editor goes into quite some detail on how to draw selected text.
Related
Can you change the position of a p5 text element after it is draw without redrawing the entire canvas? If so, how would I be able to?
I'm trying to make text appear under players set to their current position, but when they move I want it to change its position to the player's position. I have the events with that setup, I just don't know how to change the position of the element.
Unlike some libraries, such as fabric.js, graphical elements in p5.js are not persistent objects that can be moved or modified once they are drawn. Instead, everything in p5.js is drawn in immediate mode. So when you are drawing text you specify it's attributes at the time you draw it, using the Typography functions, and the text(). In order to "move" text you would clear the canvas, or re-paint the background (using clear() or background() respectively, and then re-drawing the text with different settings or parameters.
I couldn't find an example of a block of text not rendered to a rectangular area.
Ideally, it would be nice if ID2D1HwndRenderTarget.DrawText() would let me provide a polygon Geometry instead of a rectangle.
I've tried adding a Direct2D Layer with contentBounds, thinking it might skip rendering text within those layers. It didn't work as expected, it just blocked render to the area still emulating text underneath.
I've also tried applying a rectangular area to hwnd window itself. It too blocked render but didn't shift text.
IDWriteTextLayout only supports rectangular layouts, but DirectWrite supports any shape you can think of by using the lower level functions (text analysis, glyph measurement, glyph shaping). It's no easy task to write your own text layout from scratch, but I wrote a Windows 7 SDK sample containing a "FlowLayout" that demonstrates a circle and a few other simple shapes. It doesn't take arbitrary geometry, but you may be able to adapt it to your needs (see FlowLayoutSource::GetNextRect for computing the width of each line).
https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/multimedia/DirectWrite/CustomLayout
DirectWrite only supports rectangular layouts, so you can't get anything more complicated automatically. You'll have to implement layout functionality yourself if you want it to work differently. Clipping arguments, like you already observed, have nothing to do with text layout.
Is it possible to get the position of a ltk (Common Lisp basic GUI library) window (one of its corners), in pixels from the top left screen corner?
I'm trying to use mouse movement to control an applet I'm making (details here), but I can only find the mouse's position relative to the window, and I can only set it relative to the screen itself. I want to hide the cursor and return it to a fixed point after every move, noting how it has moved. I need to know the window position to correct for the different measurements.
The manual gives several options for manipulating the toplevel, such as moving the window around or finding its position and dimensions. The particular expression needed here is (geometry *tk*), which returns a list of the window's x and y position and size.
I have a general question (I know I should present specific code with a problem, but in my case the problem is of a more general nature).
In Processing, let's say I make an ellipse:
ellipse(30, 30, 10, 10);
Now, is there a way to get the pixels where this ellipse is on the canvas? The reason would be to have a way of creating user interaction with the mouse (for instance). So when someone clicks the mouse over the ellipse, something happens.
I thought of turning everything into objects and use a constructor to somehow store the position of the shape, but this is easier said than done, particularly for more complex shapes. And that is what I am interested in. It's one thing to calculate the position of an ellipse, but what about more complex shapes? Are there any libraries?
Check out the geomerative library. It has a way to check whether the mouse is inside any SVG shape. I can't remember off the top of my head but it works something like you make a shape:
myShape = RG.loadShape("shape.svg");
and a point:
RPoint p = new RPoint(mouseX, mouseY);
and the boolean function contains() will tell you if the point is inside the shape:
myShape.contains(p);
It's better to use a mathematical formula than pixel-by-pixel checking of the mouse position (it's much faster, and involves less code).
For a perfect circle, you can calculate the Euclidean distance using Pythagoras' theorem. Assume your circle is centred at position (circleX,circleY), and has a radius (not diameter) of circleR. You can check if the mouse is over the circle like this:
if(sq(mouseX-circleX)+sq(mouseY-circleY) <= sq(circleR)) {
// mouse is over circle
} else {
// mouse is not over circle
}
This approach basically imagines a right-angled triangle, where the hypotenuse (the longest side) runs from the centre of the circle to the mouse position. It uses Pythagoras' theorem to calculate the length of that hypotenuse, and if it's less than the circle's radius then the mouse is inside the circle. (It includes a slight optimisation though -- it's comparing squares to avoid doing a square root, as that can be comparatively slow.)
An alternative to my original mathematical answer also occurred to me. If you can afford the memory and processing power of drawing all your UI elements twice then you can get good results by using a secondary buffer.
The principle involves having an off-screen graphics buffer (e.g. using PGraphics). It must be exactly the same size as the main display, and have anti-aliasing disabled. Draw all your interactive UI elements (buttons etc.) to this buffer. However, instead of drawing them the normal way, give each one a unique colour which it uses for fill and stroke (don't add any text or images... just solid colours). For example, one button might be entirely red, and another entirely green. Any other RGB value works, as long as each item has a unique colour. Make sure the background has a unique colour too.
The user never sees that buffer, so don't draw it to the screen (unless you're debugging or something). When you want to detect what item the mouse is over, just lookup the mouse position on that off-screen buffer. Get the pixel colour at that location, and match it to the UI element.
After you've done all that, just go ahead and draw everything to the main display as normal.
It's worth noting that you can cut-down the processing time of this approach a lot if your UI elements never (or rarely) move. You only need to redraw the secondary buffer when something appears/disappears, animates, or changes size/position.
I have a Win32 GUI application that uses GDI havily. It needs to draw text over a bitmap at specified coordinates and later erase it and substitute with the original bitmap.
I proceed as follows:
select font (GetStockObject( DEFAULT_GUI_FONT)), brush, other stuff into the device context
call GetTextExtentPoint32() to compute the size of the text
now having the text starting point I can compute the expected text rectangle and store it
call TextOut() for the same device context with the same starting point and the same text
and later restore the bitmap for the store rectangle.
It works fine when ClearType antialiasing is off. But with ClearType on the size returned by GetTextExtentPoint32() is slightly smaller than the size actually occupied by the text when TextOut() is called. So when I later restore the original bitmap some small stripes of the text remain in place and I have artifacts.
Is there any cure to this without disabling ClearType?
You could also try DrawText with DT_CALCRECT to compute the string size. Maybe it works better.
Also you can then write the string with DrawText inside a rectangle with the sizes equal to the one you get with DT_CALCRECT and it will clip the text in case it is a bit larger.