If I click inside a TRichEdit control, how can I get the Line index (I clicked on) from the mouse client coordinates?
In other words, how do I convert a client coordinate to a Line Index?
***EDIT
I'm actually not clicking inside the TRichEdit control, I'm clicking in another control and need to synch with the TRichEdit control's line number.
Send EM_CHARFROMPOS and EM_LINEFROMCHAR messages to the RichEdit, eg:
POINTL pt = ...; // client coordinates
int pos = RichEdit1->Perform(EM_CHARFROMPOS, 0, (LPARAM)&pt);
int idx = RichEdit1->Perform(EM_LINEFROMCHAR, pos, 0);
Related
I have a simple implementation for the OnPaint event in my Borland C++ (Delphi) program. In OnPaint in an MDI child, a grid is drawn and inside the grid I show a number of bitmaps.
When I open/create a new Window, this is what happens:
The window is shown.
There is an OnPaint event, in which I draw the grid and the bitmaps, but some of the bitmaps do not show completely, there are some lines in the window where the part of the bitmap is not shown.
Then there is a next OnPaint event, the same code is called and now all the bitmaps are drawn completely.
Other users of the program report more than 2 OnPaint events, with similar failures in the bitmaps.
I included a counter, the counter shows that OnPaint is, in my case, always called twice when I create a new window, when the window is redrawn as result of moving, OnPaint is only called once. I disabled some of the drawing code to see if something here is causing the second call, but this is not the case.
Is there an explanation for this behavour, and better, a cure ?
void __fastcall TfrmSpoor::FormPaint(TObject *Sender)
{
... do some calculations
HorzScrollBar->Increment = PixelsPerHokX;
HorzScrollBar->Range = PixelsPerHokX * Railplan->xGrootte;
VertScrollBar->Increment = PixelsPerHokY;
VertScrollBar->Range = PixelsPerHokY * Railplan->yGrootte;
CanvasOffsetX = (int)-HorzScrollBar->Position % PixelsPerHokX;
CanvasOffsetY = (int)-VertScrollBar->Position % PixelsPerHokY;
Canvas->Lock(); // reserveert de Canvas voor deze thread
OnPaintTeller++;
Color = temp.GeefSymboolKleur(Vormgeving->SymboolGrootte);
... do some more calculations
{
TekenRaster(Canvas, Deelplan);
TekenRailplan(Canvas, Deelplan, true);
}
// Set some Buttons to visible:
ToonESTWRegels(Vormgeving->SymboolGrootte == SG_ESTW && Vormgeving->ESTWButtons);
Canvas->Unlock(); // release Canvas
}
I'm using the Embarcadero RAD Studio C++ builder XE7 compiler. In an application project, I'm using the both Windows GDI and GDI+ to draw on several device contexts.
My drawing content is something like that:
On the above sample the text background and the user picture are drawn with GDI+. The user picture is also clipped with a rounded path. All the other items (the text and the emojis) are drawn with the GDI.
When I draw to the screen DC, all works fine.
Now I want to draw on a printer device context. Whichever I use for my tests is the new "Export to PDF" printer device available in Windows 10. I prepare my device context to draw on an A4 viewport this way:
HDC GetPrinterDC(HWND hWnd) const
{
// initialize the print dialog structure, set PD_RETURNDC to return a printer device context
::PRINTDLG pd = {0};
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hWnd;
pd.Flags = PD_RETURNDC;
// get the printer DC to use
::PrintDlg(&pd);
return pd.hDC;
}
...
void Print()
{
HDC hDC = NULL;
try
{
hDC = GetPrinterDC(Application->Handle);
const TSize srcPage(793, 1123);
const TSize dstPage(::GetDeviceCaps(hDC, PHYSICALWIDTH), ::GetDeviceCaps(hDC, PHYSICALHEIGHT));
const TSize pageMargins(::GetDeviceCaps(hDC, PHYSICALOFFSETX), ::GetDeviceCaps(hDC, PHYSICALOFFSETY));
::SetMapMode(hDC, MM_ISOTROPIC);
::SetWindowExtEx(hDC, srcPage.Width, srcPage.Height, NULL);
::SetViewportExtEx(hDC, dstPage.Width, dstPage.Height, NULL);
::SetViewportOrgEx(hDC, -pageMargins.Width, -pageMargins.Height, NULL);
::DOCINFO di = {sizeof(::DOCINFO), config.m_FormattedTitle.c_str()};
::StartDoc (hDC, &di);
// ... the draw function is executed here ...
::EndDoc(hDC);
return true;
}
__finally
{
if (hDC)
::DeleteDC(hDC);
}
}
The draw function executed between the StartDoc() and EndDoc() functions is exactly the same as whichever I use to draw on the screen. The only difference is that I added a global clipping rect on my whole page, to avoid the drawing to overlaps on the page margins when the size is too big, e.g. when I repeat the above drawing several times under the first one. (This is experimental, later I will add a page cutting process, but this is not the question for now)
Here are my clipping functions:
int Clip(const TRect& rect, HDC hDC)
{
// save current device context state
int savedDC = ::SaveDC(hDC);
HRGN pClipRegion = NULL;
try
{
// reset any previous clip region
::SelectClipRgn(hDC, NULL);
// create clip region
pClipRegion = ::CreateRectRgn(rect.Left, rect.Top, rect.Right, rect.Bottom);
// select new canvas clip region
if (::SelectClipRgn(hDC, pClipRegion) == ERROR)
{
DWORD error = ::GetLastError();
::OutputDebugString(L"Unable to select clip region - error - " << ::IntToStr(error));
}
}
__finally
{
// delete clip region (it was copied internally by the SelectClipRgn())
if (pClipRegion)
::DeleteObject(pClipRegion);
}
return savedDC;
}
void ReleaseClip(int savedDC, HDC hDC)
{
if (!savedDC)
return;
if (!hDC)
return;
// restore previously saved device context
::RestoreDC(hDC, savedDC);
}
As mentioned above, I expected a clipping around my page. However the result is just a blank page. If I bypass the clipping functions, all is printed correctly, except that the draw may overlap on the page margins. On the other hands, if I apply the clipping on an arbitrary rect on my screen, all works fine.
What I'm doing wrong with my clipping? Why the page is completely broken when I enables it?
So I found what was the issue. Niki was close to the solution. The clipping functions seem always applied to the page in pixels, ignoring the coordinate system and the units defined by the viewport.
In my case, the values passed to the CreateRectRgn() function were wrong, because they remained untransformed by the viewport, although the clipping was applied after the viewport was set in the device context.
This turned the identification of the issue difficult, because the clipping appeared as transformed while the code was read, as it was applied after the viewport, just before the drawing was processed.
I don't know if this is a GDI bug or a wished behavior, but unfortunately I never seen this detail mentioned in all the documents I read about the clipping. Although it seems to me important to know that the clipping isn't affected by the viewport.
I am trying to find a way to get the corresponding screen location of the caret-position in a text area in JavaFX. I need the location to show Popups in text at the caret location.
I found request or it here:
https://bugs.openjdk.java.net/browse/JDK-8090849
and some workarounds here:
https://community.oracle.com/thread/2534556
They work somehow, but there are a few issues with location not updating correctly sometimes. Does anyone have a suggestion of how to get the caret position in terms of screen X and Y?
Just wanted to follow-up with an answer to this question for TextField controls in JavaFX. I'm sure the same could apply to other text input controls as well. I got the idea from looking at some code that involved changing the default colour of the caret using a subclass of TextFieldSkin class. If you look closely, the TextFieldSkin superclass holds a reference to the Path instance which represents the caret in a protected field called caretPath. Although this is kind of a hack'ish solution, it does provide developers with the absolute coordinates of the Caret in a much safer way than most of the hacks I've seen out there.
public class TextFieldCaretControlSkin extends TextFieldSkin {
public TextFieldCaretControlSkin(TextField textField, Stage stage) {
super(textField);
Popup popup = new Popup();
// Make the popup appear to the right of the caret
popup.setAnchorLocation(PopupWindow.AnchorLocation.CONTENT_BOTTOM_LEFT);
// Make sure its position gets corrected to stay on screen if we go out of screen
popup.setAutoFix(true);
// Add list view (mock autocomplete popup)
popup.getContent().add(new ListView<String>());
// listen for changes in the layout bounds of the caret path
caretPath.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> observable,
Bounds oldValue, Bounds newValue) {
popup.hide();
// get the caret's x position relative to the textfield.
double x = newValue.getMaxX();
// get the caret's y position relative to the textfield.
double y = newValue.getMaxY();
Point2D p = caretPath.localToScene(x, y);
/*
* If the coordinates are negatives then the Path is being
* redrawn and we should just skip further processing.
*/
if (x == -1.0 || y == -1.0)
return;
// show the popup at these absolute coordinates.
popup.show(textField,
p.getX() + caretPath.getScene().getX() +
caretPath.getScene().getWindow().getX(),
p.getY() + caretPath.getScene().getY() +
caretPath.getScene().getWindow().getY() -
newValue.getHeight()); // put the popup on top of the caret
}
});
}
}
To use you'd have to embed this in some sort of subclassed text input control and remember to do textField.setSkin(new TextFieldCaretControlSkin(textField)). There may be better ways to do this since I am not a JavaFX expert but I just wanted to share this solution with the rest of the world just in case it provided some insight.
Hope this helps!
This is how you use RichTextFX to position a popup window 4px to the right of the caret:
InlineCssTextArea area = new InlineCssTextArea();
Popup popup = new Popup();
popup.getContent().add(new Label("I am a popup label!"));
area.setPopupWindow(popup);
area.setPopupAlignment(PopupAlignment.CARET_CENTER);
area.setPopupAnchorOffset(new Point2D(4, 0));
You still need to control the visibility of the popup window yourself by calling
popup.show(ownerWindow);
popup.hide();
See also this working demo.
I want to change the Horizsize/VertSize of my Series Points in a TChart.
I can change it on a manual way, but not in the c++-code itself.
The series Pointer sub-component property is only available in certain series-type classes, such as the TLineSeries class.
Hence you need to cast your series-pointers to the appropriate derived-type first.
For a standard line chart:
// TChart * pChart - pointer to your chart component.
// Cast to appropriate derived series-type.
TLineSeries* pLineSeries = dynamic_cast<TLineSeries*>( pChart->Series[index_of_series]);
// Now you can reach the Pointer sub-component property: pLineSeries->Pointer
// Seems like each individual point(TSeriesPointer) on the series can be accessed.
// Set Vertical size and Horizontal size:
pLineSeries->Pointer->operator [](index_of_point)->VertSize = 5;
pLineSeries->Pointer->operator [](index_of_point)->HorizSize = 5;
Is there a way to draw in a canvas with a layout. I mean that I have an object that moves and constant axis. Everybody knows when the object moves from point A to point B we should fill the rectangle by some color. One attentive user may notice that image blinks.
One way: If I have a constant canvas with a set of objects like axis, grids etc... and another one with the moving objects.
I can combine them like
SumCanvas.Pixels[i, j] = ConstCanvas.Pixels[i, j] + MovingCanvas.Pixels[i, j]
filling only the MovingCanvas.
Maybe there is another way?
UPD
A piece of code:
Self is inherited from.
// ...
Canvas.Rectangle(-1, -1, Self.Width, Self.Height);
// Fill all area of canvas by
// clWhite. This is a reason of an image blinking.
// ...
Shape.position := position; // the coordinate of permanently moving object;
// ...
{The constant part}
AddGrid; // drawing a constantCanvas (axis and grids);
for Shape in FListOfShapes do // TListOfShapes = TList<IShape>
shape.draw; // a set of another shape with constant coordinates.
// ...