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

3
我需要编写一个函数,可以从文本编辑控件中的字符位置获取屏幕坐标。我正在使用由wxWidgets框架提供的文本编辑控件。wxTextCtrl没有公开任何API函数,可以提供此信息。在Windows上,我可以通过向文本控件发送EM_POSFROMCHAR来获取信息。
我想知道如何在其他环境(如Linux)中执行相同的操作。目前,这只需要在运行在X Window System上的桌面环境上完成,例如GNOME、KDE和XFCE。有没有方法可以做到这一点?在这些DE上,谁绘制了像文本编辑这样的控件?它是由X管理并由特定的DE进行样式设计吗?
任何帮助都将不胜感激。

你已经打上了“winapi”的标签。然而,这似乎是关于Linux的问题。 - ravenspoint
你正在开发的wxWidgets框架版本号是多少?是2.8、2.9还是svn? - ezpresso
@ezpresso:我正在2.8上开发。但是我可以升级到最新版本,甚至是svn版本。 - Navaneeth K N
4个回答

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);

正如您所看到的,这个实现并没有考虑单行文本输入,因此在创建控件时需要使用样式。
好的,下面是如何使用它。假设是类的一个子对象指针:
long iCharPos = m_Text2->GetInsertionPoint();
long iCharPosMax = m_Text2->GetLastPosition();
wxPoint pos = m_Text2->GetPositionCoords(iCharPos);

现在我们已经获得了角色位置坐标在pos中。就是这样!
以下是一些可能对您感兴趣的链接:
- GtkTextView — 显示GtkTextBuffer的小部件 - GtkTextBuffer — 存储带属性的文本以在GtkTextView中显示 现在关键是你的第二个问题。
引用:
“在这些DE上,谁绘制控件(如文本编辑)?它是由X管理并由特定的DE进行样式设置吗?”
这取决于您使用的wxWidgets端口。 wxMSW和wxGTK端口分别使用Win32和GTK+2本地控件。基于wxUniversal的端口(例如wxX11,wxMGL)通过wxWidgets自身绘制所有控件。X Window System本身不规定用户界面。它提供了构建GUI环境的基本框架:在屏幕上绘制和移动窗口以及与鼠标和键盘交互。

非常好的答案!我需要仔细阅读才能完全理解它。非常感谢。 - Navaneeth K N
还有一个问题:在KDE中呢?这个能在KDE中使用吗?KDE使用什么框架来绘制控件? - Navaneeth K N
@Appu,是的,GTK +应用程序在KDE中可以正常工作。 运行GTK +程序不需要桌面环境。 如果安装了所需的库,则GTK +程序可以在其他基于X11的DE或窗口管理器上运行(请参见[“GTK +”](http://en.wikipedia.org/wiki/GTK%2B))。 此外,您可以在此处找到有关如何使您的GTK +应用程序在KDE中看起来很棒的一些详细信息[here](http://artipc10.vub.ac.be/wordpress/2009/11/18/making-your-mixed-kde-and-gnome-desktop-look-cool/)。 - ezpresso
@Appu,在安装了GNOME、KDE或XFCE桌面环境的情况下,GTK+应用程序中的控件都是由GTK+库绘制的。 - ezpresso
非常感谢。这意味着您提供的代码对于使用X11的DEs来说已经足够了。对于Windows,我将基于“EM_POSFROMCHAR”添加不同的实现。再次感谢您的帮助。我从您的帖子中学到了很多,赏金归您! - Navaneeth K N

0

谢谢。但是PositionToXY()返回的是行列位置,而不是屏幕坐标。GetPosition()也没有用,因为它给出的是文本控件的位置,而不是插入符号所在的屏幕位置。看起来wxWidgets没有为这个问题暴露任何东西。这就是为什么我需要查看本地API的原因。在Windows上,发送我在帖子中提到的消息非常有效。我正在寻找其他平台(如GTK)的替代方法。 - Navaneeth K N
那么你想要什么?相对于什么来说的插入符位置? - wallyk
我已经获取了插入符的位置。现在我需要获取该位置的屏幕坐标,以便我可以在那里放置另一个控件。我正在构建一个自动完成菜单,当字符输入到文本框时会显示出来。使用列表框来保存完成候选项。如果我能获取屏幕位置,我就可以将列表框定位在那里。 - Navaneeth K N

0

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


wxStyledTextCtrl 是一个选项。但它有很多我可能不需要的不必要的东西。我也会看看它。 - Navaneeth K N

0

你考虑过使用HitTest函数进行二分查找吗?这不是很优雅,但应该很快,并且HitTest已经在wxGTK2中实现了,所以应该可以工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接