从文本控件中检索字符位置的客户区坐标

发布于 2024-10-31 15:10:16 字数 457 浏览 3 评论 0原文

我需要编写一个函数,可以从文本编辑控件中的字符位置获取屏幕坐标。我正在使用 wxWidgets 框架提供的文本编辑控件。 wxTextCtrl 没有公开任何可以提供此信息的 API 函数。在 Windows 上,我可以通过发送 EM_POSFROMCHAR 来获取信息 到文本控件。

我想知道如何在 Linux 等其他环境上完成同样的事情。目前,这仅需要在运行于 X Window 系统之上的桌面环境上完成,例如 GNOMEKDEXFCE 。有办法做到吗?而在这些DE上,文本编辑之类的控件又是谁绘制的呢?它是由 X 管理并由特定 DE 设计的吗?

任何帮助将不胜感激。

I am in need of writing a function which can get screen coordinates from the character position in a text edit control. I am using text edit control provided by wxWidgets framework. The wxTextCtrl is not exposing any API functions which can provide this information. On Windows, I can get the information by sending EM_POSFROMCHAR to the text control.

I am wondering how the same can be done on other environments like Linux. For now this needs to be done on only the desktop environments which runs on top of X Window System like GNOME, KDE and XFCE. Is there a way to do it? And on these DE, who draws the controls like text edit? Is it managed by X and styled by particular DE?

Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

败给现实 2024-11-07 15:10:16

嗯,这是可能的,但是您需要实现一个 wxTextCtrl 派生控件,该控件依赖于任何特定 wxWidgets 端口(wxMSW、wxGTK 等)的底层平台功能。

所以,因为你询问了 Linux 的实现。让我解释一下如何在 wxGTK 2.9 中实现它。下面是 wxTextCtrlExt 控件定义:

#include <wx/textctrl.h>
#include <wx/gdicmn.h>

//-----------------------------------------------------------------------------
// wxTextCtrlExt
//-----------------------------------------------------------------------------

class wxTextCtrlExt : public wxTextCtrl
{
public:
    wxTextCtrlExt() : wxTextCtrl() { }
    wxTextCtrlExt(wxWindow* parent,
                  wxWindowID id,
                  const wxString& value = wxEmptyString,
                  const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
                  long style = wxTE_MULTILINE,
                  const wxValidator& validator = wxDefaultValidator,
                  const wxString& name = wxTextCtrlNameStr)
    : wxTextCtrl(parent, id, value, pos, size, style, validator, name ) { }

    wxPoint GetPositionCoords(long pos);
};

以及 wxGTK 实现:

#include "wxTextCtrlExt.h"
#include <wx/defs.h>

#include <gtk/gtk.h>

wxPoint wxTextCtrlExt::GetPositionCoords(long pos)
{
    if ( IsMultiLine() ) {
        GtkTextView* txtView = GTK_TEXT_VIEW(m_focusWidget);
        GtkTextBuffer* txtBuffer = gtk_text_view_get_buffer(txtView);

        GtkTextIter iter;
        gtk_text_buffer_get_iter_at_offset(txtBuffer, &iter, pos);

        GdkRectangle location; // output location in buffer coordinates
        gtk_text_view_get_iter_location(txtView, &iter, &location);

        return wxPoint(location.x, location.y);
    }

    return wxPoint(0,0);
}

您可能还想将缓冲区坐标转换为小部件的坐标:

    // If we need to convert our coordinates to 
    GdkPoint out;
    gtk_text_view_buffer_to_window_coords(txtView, GTK_TEXT_WINDOW_WIDGET, location.x, location.y, &out.x, &out.y );

    return wxPoint(out.x, out.y);

如您所见,此特定实现不考虑单行文本输入,这就是为什么在创建 wxTextCtrlExt 控件时需要使用 wxTE_MULTILINE 样式。

嗯,下面是如何使用它。让我们将m_Text2作为指向wxTextCtrlExt类的子对象的指针:

long iCharPos = m_Text2->GetInsertionPoint();
long iCharPosMax = m_Text2->GetLastPosition();
wxPoint pos = m_Text2->GetPositionCoords(iCharPos);

现在我们在pos中得到了字符位置坐标。就是这样!

您可能感兴趣的一些链接:

现在是关于你的第二个问题。

在这些 DE 上,谁绘制了文本编辑之类的控件?它是由 X 管理并由特定 DE 设计的吗?

这取决于您正在使用的 wxWidgets 端口。 wxMSW 和 wxGTK 移植分别使用 Win32 和 GTK+2 本机控件。基于wxUniversal的端口(例如wxX11,wxMGL)由wxWidgets本身绘制所有控件。 X Window System 本身并不强制要求用户界面。它提供了构建 GUI 环境的基本框架:在屏幕上绘制和移动窗口以及与鼠标和键盘交互。

Well, it is possible, but you need to implement a wxTextCtrl derived control that relies on underlaying platform capabilities for any particular wxWidgets port (wxMSW, wxGTK, etc).

So, because you have asked about Linux implementation. Let me explain how to implement it for wxGTK 2.9. Below is the wxTextCtrlExt control definition:

#include <wx/textctrl.h>
#include <wx/gdicmn.h>

//-----------------------------------------------------------------------------
// wxTextCtrlExt
//-----------------------------------------------------------------------------

class wxTextCtrlExt : public wxTextCtrl
{
public:
    wxTextCtrlExt() : wxTextCtrl() { }
    wxTextCtrlExt(wxWindow* parent,
                  wxWindowID id,
                  const wxString& value = wxEmptyString,
                  const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
                  long style = wxTE_MULTILINE,
                  const wxValidator& validator = wxDefaultValidator,
                  const wxString& name = wxTextCtrlNameStr)
    : wxTextCtrl(parent, id, value, pos, size, style, validator, name ) { }

    wxPoint GetPositionCoords(long pos);
};

And the wxGTK implementation:

#include "wxTextCtrlExt.h"
#include <wx/defs.h>

#include <gtk/gtk.h>

wxPoint wxTextCtrlExt::GetPositionCoords(long pos)
{
    if ( IsMultiLine() ) {
        GtkTextView* txtView = GTK_TEXT_VIEW(m_focusWidget);
        GtkTextBuffer* txtBuffer = gtk_text_view_get_buffer(txtView);

        GtkTextIter iter;
        gtk_text_buffer_get_iter_at_offset(txtBuffer, &iter, pos);

        GdkRectangle location; // output location in buffer coordinates
        gtk_text_view_get_iter_location(txtView, &iter, &location);

        return wxPoint(location.x, location.y);
    }

    return wxPoint(0,0);
}

You may also want to convert your buffer coordinates to a widget's ones:

    // If we need to convert our coordinates to 
    GdkPoint out;
    gtk_text_view_buffer_to_window_coords(txtView, GTK_TEXT_WINDOW_WIDGET, location.x, location.y, &out.x, &out.y );

    return wxPoint(out.x, out.y);

As you can see, this particular implementation does not account for a single line text entry, that's why you need to use a wxTE_MULTILINE style when you are creating the wxTextCtrlExt control.

Well, below is how to use it. Let's m_Text2 be the pointer to a child object of wxTextCtrlExt class:

long iCharPos = m_Text2->GetInsertionPoint();
long iCharPosMax = m_Text2->GetLastPosition();
wxPoint pos = m_Text2->GetPositionCoords(iCharPos);

Now we got our character position coordinates in pos. That's it!

Some links that maybe of any interest to you:

Now it is all about your second question.

And on these DE, who draws the controls like text edit? Is it managed by X and styled by particular DE?

This depends on the wxWidgets port you are using. The wxMSW and wxGTK ports use Win32 and GTK+2 native controls, respectively. The wxUniversal based ports (such as wxX11, wxMGL) draw all the controls by wxWidgets itself. X Window System does not mandate the user interface by itself. It provides the basic framework for building GUI environments: drawing and moving windows on the screen and interacting with a mouse and keyboard.

七度光 2024-11-07 15:10:16

我不完全清楚要寻找哪个字符位置,但解决方案可能涉及 wxTextCtrl::XYToPosition() 和/或 wxTextCtrl ::PositionToXY(),但不清楚结果应该用哪个坐标系表示。

wxTextCtrl继承自wxWindow,它提供wxWindow::GetPosition()。父级是通过 wxWindow::GetParent 找到的。

在他们中间,我怀疑答案很容易得出。

I'm not completely clear which character position is sought, but the solution will likely involve wxTextCtrl::XYToPosition() and/or wxTextCtrl::PositionToXY(), but it is unclear which coordinate system the result should be expressed in.

wxTextCtrl inherits from wxWindow which offers wxWindow::GetPosition(). The parent is found by wxWindow::GetParent.

Between the lot of them, I suspect the answer is easily derived.

看海 2024-11-07 15:10:16

自从我上次使用 wxWidgets 以来已经有一段时间了,但是如果您找不到更简单(更短)的方法,计算插入符号之前的文本范围(例如使用 wxDC::GetTextExtent())是一种可能的方法来查找你想要的职位是什么?这将为您提供相对于 wxTextCtrl 中文本开头的位置。您可能必须考虑边框大小以及边框与实际文本之间的间距。如果需要通过 wxTextCtrl::HitTest() 进行细化?

顺便说一句,wxStyledTextCtrl怎么样?

It's been a while since my last wxWidgets experience, but if you can't find an easier (shorter) way, would calculating the extent of the text before the caret (e.g. using wxDC::GetTextExtent()) be a possible approach to finding the position you're after? This would give you a position relative to the start of the text in the wxTextCtrl. You may have to take border sizes and spacing between border and actual text into account. If necessary refine through wxTextCtrl::HitTest()?

BTW What about wxStyledTextCtrl?

颜漓半夏 2024-11-07 15:10:16

您是否考虑过使用 HitTest 函数进行二分搜索?不是很优雅,但它应该很快,并且 HitTest 是为 wxGTK2 实现的,所以它应该可以工作。

Have you considered doing a binary search using the HitTest function? Not very elegant, but it should be fast, and HitTest is implemented for wxGTK2 so it should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文