Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.56/9: Рейтинг темы: голосов - 9, средняя оценка - 4.56
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648

Как организовать автовыделение содержимого TEdit при получении фокуса от мыши?

08.11.2018, 11:37. Показов 1981. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем здравствуйте.

При попадании фокуса в TEdit от клавиши <TAB> и установленном свойстве AutoSelect происходит автовыделение содержимого окна TEdit. Задача: добиться того же самого при попадании фокуса в TEdit от мыши. Когда-то во времена VB-6 это делалось в две строчки:
Visual Basic
1
2
3
4
Private Sub Text1_GotFocus()
  Text1.SelStart = 0
  Text1.SelLength = Len(Text1.Text)
End Sub
Сейчас разработчики как Builder так и MSNet посчитали это ненужным: раз мышкой кликнул по окну, значит хочешь что-то выбрать из того что есть и нечего выделять всё содержимое.
Чтобы извернуться и решить задачу на форуме VBNet мне предложили пользоваться таймером:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
    Timer1->Interval = 50;
    Timer1->Enabled = false;
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    Timer1->Enabled = false;
    if(Edit1->Focused())  Edit1->SelectAll();
 
}
void __fastcall TForm1::Edit1Enter(TObject *Sender)
{
    Timer1->Enabled = true;
}
а если окон редактирования сотня? Может есть другое решение этой задачи?
Ещё один момент: Если содержимое окна полностью выделено и оно уже имеет фокус то клик по выделению должен это выделение снять. На всякий случай в архиве exe-шник на VB-6 для демонстрации как всё должно происходить.

Добавлено через 4 минуты
архив не прикрепляется, вот ссылка на него на облаке https://yadi.sk/d/JlThdT7FeZ236w
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.11.2018, 11:37
Ответы с готовыми решениями:

Как организовать автовыделение содержимого TextBox при получении фокуса?
Всем здравствуйте. На VB-6 автовыделение реализовывалось так: Private Sub Text1_GotFocus() Text1.SelStart = 0 Text1.SelLength =...

Как в коде разметки сделать, изменение ширины Grid при получении кнопкой фокуса
Здравствуйте форумчане. У меня такой вопрос: есть грид, в нем кнопка. Как в коде разметки сделать, к примеру, изменение ширины этого...

Событие текстбокса - при получении фокуса
Какое событие выполняется при установки фокуса на определенный текстбокс?

31
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
08.11.2018, 11:50
Лучший ответ Сообщение было отмечено jkrnd как решение

Решение

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// в заголовочном файле формы:
namespace Selectable_Edit
{
    class TEdit : public Stdctrls::TEdit
    {
    protected:
        DYNAMIC void __fastcall DoEnter(void)
        {
            Stdctrls::TEdit::DoEnter();
            ::PostMessage(Handle, EM_SETSEL, 0, -1);
        }
    };
};
#define TEdit Selectable_Edit::TEdit
 
// класс формы без изменений
Достаточно простое решение?

Цитата Сообщение от jkrnd Посмотреть сообщение
Сейчас разработчики как Builder так и MSNet посчитали это ненужным
Разработчики Билдера тут каким боком? Это разработчики ОС решили, что должно быть такое поведение, а Билдер всего лишь использует обертку над виндовым контролом...
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
08.11.2018, 14:38  [ТС]
volvo, супер. То что хотел. Осталось завести новое свойство Selectable и в зависимости от него переопределять DoEnter. Спасибо.

Добавлено через 25 минут
Пришлось перенести код с переопределением в Public секцию. Тогда заработало:
C++
1
2
3
4
5
6
        DYNAMIC void __fastcall DoEnter(void)
        {
            Stdctrls::TEdit::DoEnter();
            if(FSelected)
            ::PostMessage(Handle, EM_SETSEL, 0, -1);
        }
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
08.11.2018, 14:50
Очень странно, по докам оно должно быть в защищенной секции, у меня отработало именно так, обычно не требуется выносить в public...
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
08.11.2018, 18:41  [ТС]
Теперь пробую сделать так, чтобы при получении фокуса содержимое не только выделялось, но и выравнивалось по левому краю, а при потере фокуса опять выравнивалось по правому краю. Не получается состыковать с Вашим кодом
Выравнивание текста в TEdit
вставляю:
C++
1
2
3
4
5
6
7
8
9
10
        DYNAMIC void __fastcall DoEnter(void)
        {
            Stdctrls::TEdit::DoEnter();
            if(FSelected)
            {
                PostMessage(Handle, EM_SETSEL, 0, -1);
                FAlignment = ES_LEFT;
                RecreateWnd();
            }
        }
выравнивание влево происходит, но слетает выделение и исчезает каретка?

Добавлено через 3 часа 41 минуту
volvo, так и не получается совместить автовыделение содержимого по получению фокуса от мыши и выравнивания содержимого по левому краю а при потере фокуса - по правому краю.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
08.11.2018, 18:55
В этом случае нужно хитрее действовать, с RecreateWnd тут не прокатит, нужно на уровень WinAPI спускаться. Сделал так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
namespace Selectable_Edit
{
    class TEdit : public Stdctrls::TEdit
    {
    private:
        bool FSelected;
        TAlignment FAlignment;
 
        void __fastcall SetAlignment(TAlignment Value)
        {
            const DWORD Alignments[3] = {ES_LEFT, ES_RIGHT, ES_CENTER};
            if(FAlignment != Value)
            {
                FAlignment = Value;
                ::SetWindowLongPtr(Handle, GWL_STYLE,
                    (::GetWindowLongPtr(Handle, GWL_STYLE) & ~(ES_LEFT | ES_CENTER | ES_RIGHT)) | Alignments[Value]);
            }
        }
 
    protected:
        DYNAMIC void __fastcall DoEnter(void)
        {
            Stdctrls::TEdit::DoEnter();
            if(FSelected)
            {
                Alignment = taLeftJustify;
                ::PostMessage(Handle, EM_SETSEL, 0, -1);
            }
        }
        DYNAMIC void __fastcall DoExit(void)
        {
            if(FSelected)
            {
                Alignment = taRightJustify;
            }
            Stdctrls::TEdit::DoExit();
        }
    public:
        inline __fastcall virtual TEdit(TComponent* AOwner) : Stdctrls::TEdit(AOwner)
        {
        }
        __property bool IsSelected = {read = FSelected, write = FSelected};
        __property TAlignment Alignment = {read = FAlignment, write = SetAlignment};
    };
};
#define TEdit Selectable_Edit::TEdit
, и в OnCreate формы выставил:
C++
1
2
3
4
5
6
7
8
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    Edit1->IsSelected = true;
    Edit1->Alignment = taRightJustify;
 
    Edit3->IsSelected = true;
    Edit3->Alignment = taRightJustify;
}
, с Edit1/Edit3 все работает, как описано выше, остальные эдиты вообще обычные
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
08.11.2018, 20:02  [ТС]
volvo, Всё работает как задумано. Но теперь если в форме имею Edit1 с Alignment = taLeftJustify и я повешу на кнопку
C++
1
Edit1->Alignment = taCenter;
или
C++
1
Edit1->Alignment = taRightJustify;
ничего не изменяется

Добавлено через 4 минуты
в конструкторе перехватчика пишу
C++
1
FAlignment= taRightJustify;
а выравнивание всё равно при загрузке формы получается по по левому краю.
Фокус при загрузке падает не на окно редактирования - я проверил.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
08.11.2018, 20:39
Цитата Сообщение от jkrnd Посмотреть сообщение
FAlignment= taRightJustify;
Это ничего не даст. Нужно менять значение свойства, а не поля, чтобы отработал метод SetAlignment
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
08.11.2018, 21:14  [ТС]
volvo, вот проект, там три кнопки они перестали переключать выравнивание. Да и при первом запуске все TEdit с левым выравниванием. Не пойму, что не так.
Вложения
Тип файла: rar Ver1.1.rar (7.7 Кб, 1 просмотров)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
08.11.2018, 21:54
Как при запуске сделать выставленное выравнивание - еще не придумал, а вот если добавить

C++
1
2
3
4
5
6
7
8
9
10
11
        void __fastcall SetAlignment(TAlignment Value)
        {
            const DWORD Alignments[3] = {ES_LEFT, ES_RIGHT, ES_CENTER};
            if(FAlignment != Value)
            {
                FAlignment = Value;
                ::SetWindowLongPtr(Handle, GWL_STYLE,
                    (::GetWindowLongPtr(Handle, GWL_STYLE) & ~(ES_LEFT | ES_CENTER | ES_RIGHT)) | Alignments[Value]);
                Repaint(); // <--- Вот этот вызов
            }
        }
, то изменения выравнивания будут применяться нормально. В принципе, понятно, почему оно не отображается изначально: форма еще не показана, контролы соответственно тоже, надо будет попробовать при показе формы пройтись по всем Edit-ам и ТАМ назначить им выравнивание вправо, так должно сработать...
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
08.11.2018, 22:57  [ТС]
изменённый в SetAlignment код результатов не дал. Выравнивание работает только в теле кода класса-перехватчика.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
08.11.2018, 23:43
Цитата Сообщение от jkrnd Посмотреть сообщение
изменённый в SetAlignment код результатов не дал
Неправда. Взял твой код из предыдущего поста, добавил Repaint() в SetAlignment, и по нажатию Button2 текст прекрасно сместился в центр. Видео записать? BCB6 + Win7 32 bit, если что...

Добавлено через 16 минут
А если перенести вот эти действия:
C++
1
2
3
4
5
6
7
8
void __fastcall TForm1::FormShow(TObject *Sender)
{
    Edit1->Selected = true;
    Edit1->Alignment = taRightJustify;
 
    Edit2->Selected = true;
    Edit2->Alignment = taRightJustify;
}
именно в OnShow формы, а не делать это в конструкторе формы - то оно прекрасно отработает и покажутся именно right-aligned поля ввода... И это тоже в твоем проекте и с BCB6...
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.11.2018, 06:00  [ТС]
volvo, видео не нужно, но если не трудно пришлите Ваш работающий проект.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
09.11.2018, 10:30
Вот проекты. Первый - вместе с exe-шником, второй - только исходники (мало ли, может ты не запускаешь чужие exe-файлы, как и я сам
Вложения
Тип файла: zip Ver1.1.zip (1.15 Мб, 2 просмотров)
Тип файла: zip Ver1.1_src.zip (8.5 Кб, 2 просмотров)
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.11.2018, 11:52  [ТС]
volvo, попробовал на работе (WinXP, BCB6) - даже exeшник: по нажатию Button2 текст в центр не сместился, по нажатию Button3 текст вправо не сместился, чудеса какие-то. Проект - то же самое поведение. Что бы это могло быть?

Зато заработало в проекте, принесённом из дома. Сейчас разберусь.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
09.11.2018, 11:53
Не знаю. Что-то в системе. Какая ОС, кстати. Я слышал, что с выравниванием на WinXP до SP3 бывали проблемы. На Десятке тоже можно нарваться на непредсказуемые глюки (там вообще на любые глюки можно нарваться). Но я проверил на WinXP SP3/Win7 32/Win7 64/Win8 32, везде все работает. Остальные ОСи мне ни к чему, так что не держу их в виртуалке.
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.11.2018, 12:00  [ТС]
нашёл отличие между проектом из дома и тем что скачал у Вас:
у Вас
C++
1
Edit1->Alignment = taCenter;
- ноль реакции
у меня
C++
1
Edit1->Alignment = ES_CENTER;
- ожидаемая реакция
0
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
12.11.2018, 12:09  [ТС]
volvo, всё работает как Вы говорили. Я перепутал модули разных проектов и у меня получилось что-то вроде каши. Начал всё заново и всё заработало. Возник новый вопрос. Вот исправно работающий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
namespace Selectable_Edit
{
    class TEdit : public Stdctrls::TEdit
    {
    private:
 
        bool        FSelected;
        TAlignment  FAlignment;
 
        void __fastcall   SetAlignment(TAlignment Value)
        {
            const DWORD Alignments[3] = {ES_LEFT, ES_RIGHT, ES_CENTER};   
            if(FAlignment != Value)
            {
                FAlignment = Value;
                ::SetWindowLongPtr(Handle, GWL_STYLE,
                    (::GetWindowLongPtr(Handle, GWL_STYLE) & ~(ES_LEFT | ES_CENTER | ES_RIGHT)) | Alignments[Value]);   
                Repaint();
            }
        }
    protected:
        DYNAMIC void __fastcall DoEnter(void)
        {
            Stdctrls::TEdit::DoEnter();
            if(FSelected)
            {
                Alignment = taLeftJustify;
                ::PostMessage(Handle, EM_SETSEL, 0, -1);
            }
        }
        DYNAMIC void __fastcall DoExit(void)
        {
            if(FSelected)
            {
                Alignment = taRightJustify;
            }
            Stdctrls::TEdit::DoExit();
        }
    public:
        __fastcall virtual TEdit(Classes::TComponent* AOwner) : Stdctrls::TEdit(AOwner)
        {
            // Конструктор
            FSelected   = true;
            FAlignment  = taRightJustify;
        }
        __property bool Selected = {read = FSelected, write = FSelected};
        __property TAlignment Alignment = {read = FAlignment, write = SetAlignment};
 
        DYNAMIC void __fastcall Change(void)
        {
            // Ничего не переопределяющая заглушка
            Stdctrls::TEdit::Change();
        }
    };
};
#define TEdit Selectable_Edit::TEdit
если закомментировать переопределение свойства в секции Public,
C++
1
2
3
4
5
6
        DYNAMIC void __fastcall Change(void)
        
       //{
       //    // Ничего не переопределяющая заглушка
       //     Stdctrls::TEdit::Change();
       // }
то компилятор выдаёт ошибки:
C++
1
2
3
4
5
6
7
8
9
10
        void __fastcall   SetAlignment(TAlignment Value)
        {
            const DWORD Alignments[3] = {ES_LEFT, ES_RIGHT, ES_CENTER};    // array property missing ]  и Constant variable 'Alignments' must be initialized
            if(FAlignment != Value)
            {
                FAlignment = Value;
                ::SetWindowLongPtr(Handle, GWL_STYLE,
                    (::GetWindowLongPtr(Handle, GWL_STYLE) & ~(ES_LEFT | ES_CENTER | ES_RIGHT)) | Alignments[Value]);   // Invalid indirection
                Repaint();
            }
или у меня испорченный Builder?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
12.11.2018, 12:26
Комментировать надо полностью, а ты оставил заголовок. Как только его закомментируешь - проблема уйдет.

Кстати, чтобы сделать метод Change публичным, достаточно написать:
C++
1
2
    public:
        using Stdctrls::TEdit::Change;
, совершенно не обязательно писать заглушку, которая ничего кроме вызова метода предка не делает...
0
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
12.11.2018, 13:01  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Комментировать надо полностью
комментирую
C++
1
2
3
4
5
        //DYNAMIC void __fastcall Change(void)
        //{
        //    // Ничего не переопределяющая заглушка
        //    Stdctrls::TEdit::Change();
        //}
те же проблемы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.11.2018, 13:01
Помогаю со студенческими работами здесь

Дергание панели при получении фокуса
Столкнулся с такой проблемой, панель по определению не может иметь фокуса, поэтому вручную изменил, но при получении фокуса панелью,...

Обновление формы при получении фокуса
Условно есть 2 формы: в первой вносятся данные в поля во второй выполняются вычисления, в том числе используя данные из первой формы ...

Изменение цвета кнопки при получении фокуса при переходе по TAB
Здравствуйте! Подскажите пожалуйста: как настроить изменение цвета кнопки при получении фокуса при переходе по ТАВ (т.е. на клавиатуре,...

Изменение вида кнопки при получении и потере фокуса
Приветик всем. Возник вопросик по поводу кнопок. Хочу вставить нарисованные мною кнопки в проект, причем чтобы когда наводила на кнопку...

Запретить прокручивать скролл при получении фокуса (android)
Всем привет! Я заметил что при получении фокуса на textarea, в андроиде скролл автоматически перематывается, как поставить запрет на это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru