С Новым годом! Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24

Переключение между ячейками TStringGrid по нажатию Enter

17.12.2015, 12:57. Показов 2549. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Есть динамически создаваемые таблицы. Нужно сделать так, чтобы при вводе данных в ячейке любой из таблиц по нажатию Enter открывалось окно редактирования нижележащей ячейки (как в Excel). Мелочь, да, но это сильно повышает удобство пользования программой.

Так как таблицы динамические, видимо, нужно написать динамическое событие и подключать к нему вновь создаваемые таблицы.

Алгоритм примерно следующий:
1. Проверить, какая клавиша была нажата (if (key==VK_Resume));
2. Отследить, в какой таблице и в какой ячейке произошло событие (возможно, через TStringGrid(*Sender), ACol и ARow);
3. Закрыть окно редактирования текущей ячейки;
4. Переместить фокус на нижележащую ячейку;
5. Открыть окно редактирования выделенной ячейки.

Только вот, как реализовать такой алгоритм - ума не приложу. И, главное, как такое событие создать? Через OnKeyPress?

Помогите, пожалуйста!
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.12.2015, 12:57
Ответы с готовыми решениями:

DataGridView переключение между ячейками при нажатии Enter в режиме редактирования
Приведенный код работает при нажатии клавиши А, но при использовнии Enter дальше 5-го столбца не заходит, то есть отрабатывает только 1...

Сделать линию между ячейками TStringGrid толщиной в один пиксел
На форме не запущенного приложения - вроде тонкая линия, а как запускается - пиксела 2-3 точно, а там схема под ней...надо тоньше...

Переход между ячейками StringGrid-а по нажатию пробела
Как создать событие по переходу в следующую ячейку stringgrid по нажатию пробела?

13
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33369 / 21495 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
17.12.2015, 13:55
Не заморачивайся с созданием событий на каждый динамический компонент. Создай перехватчик, который для всех возможных гридов, как бы они не были созданы, подменит функционал автоматически:
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
// В h-файле, перед описанием класса формы
namespace TMyGrid
{
    class TMyInplaceEdit : public TInplaceEdit
    {
    public:
        __fastcall virtual TMyInplaceEdit(TComponent* AOwner)
            : TInplaceEdit(AOwner)
        {
        }
 
    protected:
        DYNAMIC void __fastcall KeyDown(System::Word &Key,
            System::Classes::TShiftState Shift)
        {
            TStringGrid *grid = static_cast<TStringGrid*>(Parent);
            if (Key == VK_RETURN)
            {
                if (grid->Row < grid->RowCount - 1) grid->Row += 1;
                else if (grid->Col < grid->ColCount - 1)
                {
                    grid->Col += 1;
                    grid->Row = grid->FixedRows;
                }
            }
            TInplaceEdit::KeyDown(Key, Shift);
        }
    };
 
    class TStringGrid : public Grids::TStringGrid
    {
    protected:
        virtual TInplaceEdit* __fastcall CreateEditor(void)
        {
            return new TMyInplaceEdit(this);
        }
    };
 
};
#define TStringGrid TMyGrid::TStringGrid
 
// тут класс формы, без изменений
1
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
18.12.2015, 00:58  [ТС]
Спасибо большое, volvo! Код заработал, очень красиво всё получилось. Но не без нюансов.

Как и ожидалось, Builder 6 твой код не переварил.
C++
1
System::Classes::TShiftState Shift)
[C++ Error] Unit1.h(23): E2316 'Classes' is not a member of 'System'

Погоревал, попечалился и пошёл ставить что-то поновее. В Rad Studio 10 их Builder мой проект вообще открывать отказался. Удалил его.

Потом пошёл поставил XE2. Худо-бедно что-то открылось. Но теперь программа работает слегка по-другому. Раньше у меня шапка таблицы заполнялась в конструкторе формы, а выравнивание текста в ячейке было в OnDrawCell. Теперь же, в XE2, текст не выравнивается. Точнее выравнивается, но в ячейке остаются два текста: как был и выравненный .

Не подскажешь напоследок, как это побороть?
Миниатюры
Переключение между ячейками TStringGrid по нажатию Enter  
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33369 / 21495 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
18.12.2015, 01:19
Цитата Сообщение от Enzi Посмотреть сообщение
Как и ожидалось, Builder 6 твой код не переварил
Надо было СРАЗУ говорить, что у тебя Builder 6, я бы привел код для него. Там всего-то нужно было убрать неймспейсы ненужные:
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
namespace TMyGrid
{
    class TMyInplaceEdit : public TInplaceEdit
    {
    public:
        __fastcall virtual TMyInplaceEdit(TComponent* AOwner)
            : TInplaceEdit(AOwner)
        {
        }
 
    protected:
        DYNAMIC void __fastcall KeyDown(Word &Key,
            Classes::TShiftState Shift)
        {
            TStringGrid *grid = static_cast<TStringGrid*>(Parent);
            if (Key == VK_RETURN)
            {
                if (grid->Row < grid->RowCount - 1) grid->Row += 1;
                else if (grid->Col < grid->ColCount - 1)
                {
                    grid->Col += 1;
                    grid->Row = grid->FixedRows;
                }
            }
            TInplaceEdit::KeyDown(Key, Shift);
        }
    };
 
    class TStringGrid : public Grids::TStringGrid
    {
    protected:
        virtual TInplaceEdit* __fastcall CreateEditor(void)
        {
            return new TMyInplaceEdit(this);
        }
    };
 
};
#define TStringGrid TMyGrid::TStringGrid
Это только что откомпилировалось и отработало в BCB6... По поводу XE2 - ищи поиском, я выкладывал неоднократно обработчик OnDrawCell для XE+, посмотри как там делается, сколько можн одно и то же писать? Тем более, что свой код обработчика ты не приводишь, оно мне или тебе нужно вообще?
1
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
18.12.2015, 10:44  [ТС]
Хорошо, давай по порядку

1. Я решаю актуальную производственную задачу. По своей инициативе и в индивидуальном порядке Но это только пока. Если же что-то выстрелит...

2. Почему я этим занимаюсь. Тупо время есть, со старой работы уволился, на новую пока что не устроился. Есть знания, представление о проблемах отрасли, готовая рабочая программа в Excel, но кому он сдался.

3. Ты меня сильно выручаешь. Хочешь, задоначу тебе что-нибудь. Пиши в личку.


Теперь, что касается данной темы. Договоримся, что речь идёт о Builder 6. Есть у меня 2 модуля программы. Один со статикой, в нём твой код отлично заработал. Во втором модуле, где таблицы динамические (про который я и писал в этой теме), компилятор выдаёт ошибку в обработчике события, где создаётся новая таблица.

C++
1
2
3
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        TStringGrid *SGnew = new TStringGrid(Form1);
[C++ Error] Unit1.cpp(139): E2125 Compiler could not generate default constructor for class 'TMyGrid::TStringGrid'

В приложении в письму - модуль с динамикой, как он есть, рабочий. Пока что без твоего кода. В этом примере, кстати, выпадающие списки реализованы через ComboBox.
Вложения
Тип файла: rar Геологические колонки.rar (360.8 Кб, 5 просмотров)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33369 / 21495 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
18.12.2015, 20:43
Лучший ответ Сообщение было отмечено Enzi как решение

Решение

Ну вот посмотри, как твой код будет выглядеть при использовании XE2:
Вложения
Тип файла: 7z geologic.7z (10.2 Кб, 11 просмотров)
1
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
18.12.2015, 21:35  [ТС]
Слушай, это просто праздник какой-то! Да, всё отлично работает.

Получается, ты все эти функции переносишь в описание класса, чтобы не думать, когда и как их вызывать. Это, наверное, сейчас так принято, хороший тон в программировании. Я когда-то давно посещал курсы по C++, тогда всё было слегка по-другому. И ещё, с 6 Builder'ом пора завязывать, перехожу на XE2.

Спасибо тебе большое! Пойду изучать твой код, хочу перенять стиль.

Кликните здесь для просмотра всего текста
Там есть только одна помарка. При создании новой таблицы на форме не появляется полоса прокрутки. Лечится установкой свойства формы AutoScroll->True


Кликните здесь для просмотра всего текста
Странно, скачал твой архив, а просмотров - 0
0
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
19.12.2015, 17:16  [ТС]
volvo, здравствуй! В продолжение этой темы хочу ещё кое-что спросить. Я взялся переделывать другой модуль программы с использованием твоего кода под Builder XE2. Вроде бы всё корректно перенёс, но почему-то вылетает ошибка в .h файле в твоём коде обработчика DrawCell. Будь так любезен, посмотри.

.h файл - 130 строка
C++
1
DrawText(Canvas->Handle, s.c_str(), s.Length(), &R, Format);
[BCC32 Error] Unit1.h(130): E2034 Cannot convert 'wchar_t *' to 'const char *'
[BCC32 Error] Unit1.h(130): E2342 Type mismatch in parameter 'lpchText' (wanted 'const char *', got 'wchar_t *')


К сообщению прилагается два проекта:
Data_old - это рабочий, как он был на Builder 6
Data - это новый на XE2, тот, который с ошибками.
Вложения
Тип файла: rar Data.rar (3.67 Мб, 4 просмотров)
Тип файла: rar Data_old.rar (4.47 Мб, 3 просмотров)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33369 / 21495 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
19.12.2015, 18:07
Project->Options, на закладке Directories and Conditionals переключить _TCHAR maps to в позицию wchar_t. Там же в строке Conditional defines добавить STRICT (иначе линкер начнет вякать на отсутствие реализации PaintWindow). Ну, и. наконец, привести главный файл проекта в соответствие настройкам юникодности: Project->View source исправить в двух местах:
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
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
#include <tchar.h> // добавить - раз
 
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) // название функции и тип lpTstr - два
{
        try
        {
                 Application->Initialize();
                 Application->CreateForm(__classid(TForm1), &Form1);
                 Application->Run();
        }
        catch (Exception &exception)
        {
                 Application->ShowException(&exception);
        }
        catch (...)
        {
                 try
                 {
                         throw Exception("");
                 }
                 catch (Exception &exception)
                 {
                         Application->ShowException(&exception);
                 }
        }
        return 0;
}
//---------------------------------------------------------------------------
1
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
19.12.2015, 18:16  [ТС]
Спасибо! Заработало!
0
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
21.12.2015, 16:29  [ТС]
volvo, здравствуй. Не подскажешь ещё кое-что?

Смотри, мне нужно, чтобы на форме DataInput в таблице (столбец "Колонка №") был динамический выпадающий список, значения которого формируются в зависимости от количества таблиц на форме Geology. К примеру, на форме Geology есть 3 таблицы, тогда в выпадающем списке присутствуют значения "1,2,3" - порядковые номера. Добавили ещё таблицу - стало 1,2,3,4.

Скажи, это вообще реально сделать? Или проще оставить костыли типа выпадающего списка с заведомо большим количеством значений (как оно сейчас есть)?

К сообщению прилагается проект, в котором задействованы обе формы. Все изменения конструктора класса TStringGrid перенесены в DataUnit.h.
Вложения
Тип файла: rar 0. ESoil.rar (4.52 Мб, 2 просмотров)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33369 / 21495 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
21.12.2015, 18:16
Цитата Сообщение от Enzi Посмотреть сообщение
это вообще реально сделать?
Для этого понадобится изменить всего 4 строки кода

1) в DataUnit.h добавляем
C++
1
2
3
#include "GeoUnit.h" // Вот эту строку
//---------------------------------------------------------------------------
namespace SG_ComboBoxes
2) там же в GetCbxItems меняем строку:
C++
1
2
3
4
5
6
7
8
9
                switch (ACol)
                {
                case 2:
                    // Items->CommaText = L"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20"; // Эту
                    for(int i = 1; i <= GetTableCount(); i++) Items->Add(IntToStr(i)); // на вот эту
                    break;
                case 8:
                    Items->CommaText = L" "в откосах" "без откосов" ";
                }
3) переходим в GeoUnit.h:
C++
1
2
3
int GetTableCount(); // перед подключением DataUnit - опишем прототип
 
#include "DataUnit.h"
4) в GeoUnit.cpp реализуем функцию GetTableCount:
C++
1
2
3
4
5
6
7
TGeology *Geology;
 
int GetTableCount()
{
    return Geology->im;
}
// ...
5) PROFIT!!!
1
1 / 1 / 2
Регистрация: 08.12.2015
Сообщений: 24
21.12.2015, 19:22  [ТС]
Ого, какое простое и изящное решение! Из файла проекта через заранее объявленную функцию передать значение счётчика в конструктор класса... Не думал, что такое вообще возможно. Однако же, всё работает!

Спасибо тебе огромное!
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33369 / 21495 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
21.12.2015, 19:36
Цитата Сообщение от Enzi Посмотреть сообщение
передать значение счётчика в конструктор класса
Это неправильно. Это не конструктор класса, это всего лишь метод класса. Вот как раз с конструктором такое было бы нерешаемо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.12.2015, 19:36
Помогаю со студенческими работами здесь

Переключение между элементами формы клавишей Enter
Всем здравствуйте. Есть форма , на которой расположены textbox’ы и combobox’в , как сделать так , чтобы при нажатии на первый текстбокс и...

Переход курсора между Edit по нажатию Enter
Как сделать что при заполнение поля Edit1 и нажатием клавиши Enter курсор переходил на Edit2

Tab Control на WPF, переключение между вкладками по нажатию кнопки
Здравствуйте форумчане, есть вопрос связанный с Tab Control на WPF. Задача стоит следующая есть Tab Control с 5 вкладками. На каждой...

Смена фокуса ввода между двумя компонентами по нажатию Enter
доброго времени суток. теперь к вопросу у меня есть программа которая состоит из listbox и edit. и мне нужно чтоб по нажатию на ентер...

Передать фокус на TStringGrid по нажатию кнопки
Добрый день, подскажите как реализовать данную задумку ... мне нужно чтобы по нажатии кнопки фокус перемещался на StringGrid и выполнял...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru