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

时间:2011-04-11 04:41:21

标签: c++ c gtk wxwidgets

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

我想知道如何在Linux等其他环境中做同样的事情。目前,这只需要在 X Window System 之上运行的桌面环境中完成,例如 GNOME KDE XFCE 。有办法吗?在这些DE上,谁像文本编辑那样绘制控件?它是由X管理还是由特定DE设计?

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

嗯,这是可能的,但你需要实现一个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);

如您所见,此特定实现不考虑单行文本条目,这就是您在创建wxTE_MULTILINE控件时需要使用wxTextCtrlExt样式的原因。

嗯,下面是如何使用它。让我们m_Text2成为wxTextCtrlExt class:

的子对象的指针
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环境的基本框架:在屏幕上绘制和移动窗口以及与鼠标和键盘交互。

答案 1 :(得分:0)

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

wxTextCtrl继承自提供wxWindow::GetPosition()wxWindow。父母是wxWindow::GetParent找到的。

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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