Получение координат клиентской области позиции символа из текстового элемента управления



Мне нужно написать функцию, которая может получить координаты экрана из положения символа в элементе управления редактированием текста. Я использую управление редактированием текста, предоставляемое платформой wxWidgets. wxTextCtrl не предоставляет никаких функций API, которые могут предоставить эту информацию. В Windows я могу получить информацию, отправив EM_POSFROMCHAR в текстовый элемент управления.



Мне интересно, как то же самое можно сделать в других средах, таких как Linux. Пока это нужно делать только на рабочем столе среды, которая работает поверх X Window System, как GNOME, KDE и XFCE. Есть ли способ сделать это? И на этих DE, кто рисует элементы управления, как текстовое редактирование? Управляется ли он X и стилизован конкретным DE?

Любая помощь будет признательна.

538   4  

4 ответов:

Ну, это возможно, но вам нужно реализовать производный элемент управления 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 не предписывает пользовательский интерфейс сам по себе. Он обеспечивает базовую структуру для построения графических сред: рисование и перемещение окон на экране и взаимодействие с мышью и клавиатурой.

Мне не совсем ясно, какая позиция персонажа ищется, но решение, скорее всего, будет включать wxTextCtrl::XYToPosition() и/или wxTextCtrl::PositionToXY(), но неясно, в какой системе координат должен быть выражен результат.

wxTextCtrl наследует от wxWindow, который предлагает wxWindow::GetPosition(). Родитель находится по wxWindow::GetParent.

Между многими из них, я подозреваю, ответ легко получить.

Прошло некоторое время с момента моего последнего опыта с wxWidgets, но если вы не можете найти более простой (короткий) способ, будет ли вычисление экстента текста перед кареткой (например, с помощью wxDC:: GetTextExtent ()) возможным подходом к поиску позиции, которую вы ищете? Это даст вам позицию относительно начала текста в wxTextCtrl. Возможно, вам придется учитывать размеры границ и расстояние между границей и фактическим текстом. Если необходимо уточнить через wxTextCtrl:: HitTest()?
КСТАТИ Насчет wxStyledTextCtrl?

Рассматривали ли вы возможность выполнения бинарного поиска с помощью функции HitTest? Не очень элегантный, но он должен быть быстрым, и HitTest реализован для wxGTK2, поэтому он должен работать.

Comments

    Ничего не найдено.