21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663

Реализация через PopupMenu функций copy and paste в DrawGrid

14.03.2016, 13:06. Показов 3262. Ответов 42
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго дня! Встала задача реализовать данный сабж в пределах одного DrawGrid. При выделение одной, а еще лучше диапазона ячеек. В голову приходит некий еще один, временный DrawGrid (промежуточный хранитель). Как это правильно реализовать вообще? Может есть пример где - не найти. Спасибо.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.03.2016, 13:06
Ответы с готовыми решениями:

Реализация Copy/Paste
Добрый день!!!!! уважаемые форумчане подскажите кто как реализует copy/paste?????? Есть грид, в нем можно выделять несколько...

Copy >> Paste
Тянет ли копи паст под низкочастотники? Не в ту категорию пост запихал ( Как исправить?

Copy/Paste
доброго! вот у меня тут возник такой вопрос: 1.Сopy 2.Paste итак вот вопросы 1.Как сделать так что бы в виндовс приложении из...

42
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
14.03.2016, 23:37  [ТС]
Студворк — интернет-сервис помощи студентам
Огромное спасибо. Все получилось! GridData у меня уже был оказываетя, только в другой переменной) Оставалось заносить в него изменения(заполнять новые данныев соотв. члены массива) и перерисовывать. Спасибо!

Добавлено через 12 минут
Одна только осталась проблема - у меня изначально свойство goRangeSelect стоит false и все это не работало.
Поставив его в true все заработало, но перестало выделять по коду некоторые вещи(желтым по периметру например выделенные ячейки)
Как то можно побороть?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 00:32
Для того, чтобы сделать тот функционал, который у тебя был - нужно как минимум видеть, что именно было. В частности, никто не мешает по OnMouseUp грида (после того, как выбор ячеек закончен) отрисовать это самое выделение выбранных ячеек по периметру:
C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall TForm1::DrawGrid1MouseUp(TObject *Sender, TMouseButton Button,
    TShiftState Shift, int X, int Y)
{
    TDrawGrid *dg = static_cast<TDrawGrid*>(Sender);
    TGridRect sel = DrawGrid1->Selection;
 
    dg->Canvas->Pen->Color = clRed;
    dg->Canvas->Brush->Style = bsClear;
    dg->Canvas->Rectangle(Rect(dg->CellRect(sel.Left, sel.Top).TopLeft(),
                               dg->CellRect(sel.Right, sel.Bottom).BottomRight()));
}
, и получить:
Миниатюры
Реализация через PopupMenu функций copy and paste в DrawGrid  
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 10:06  [ТС]
Там проблема есть в том, что DrawGrid1->Selection , я так понял, позволяет выделить прямоугольную область и с ней работать.
У меня выделение работает таким образом, что можно выделить например всю нулевую строку и например 5 ячеек первой строки.Есть переменная int Grid1SelectCell[20][10]; (DrawGrid1 20 на 10)
В DrawGrid1SelectCell
C++
1
Grid1SelectCell[ACol][ARow]=1;
В DrawGrid1DrawCell
C++
1
2
if(Grid1SelectCell[ACol][ARow] != 0)
       {//желтым красим периметр ячейки
Я упростил, но примерно таким образом выделение происходит.

Добавлено через 7 минут
Пробую в циклах проходить copy paste меняя DrawGrid1->Selection на пложение ячейки, если Grid1SelectCell[i][j] != 0 , но пока как то не то.

Добавлено через 7 часов 12 минут
вот так написал - вроде работает.
в DrawGrid1DrawCell
C++
1
2
if(State.Contains(gdSelected))
{//....красим
Добавлено через 1 час 34 минуты
но мне это не совсем подходит(
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 10:17
Каким образом у тебя происходило выделение ячеек, расскажи? То есть, дословно: вот нужно тебе выбрать ячейки от предпоследней в нулевой строке до третьей в первой строке, что ты делал для этого? Просто поодиночке щелкал по ячейкам с каким-нибудь Ctrl-ом зажатым?

Сам понимаешь, чтобы копировать ячейки, они должны быть выбраны либо подряд (построчно, дошел до конца строки - начинаешь следующую с начала), либо прямоугольником. Все остальные варианты (выбрать несколько ячеек в первом ряду, потом еще несколько в третьем, и еще в седьмом ряду парочку) довольно сложны для реализации, да и не представляю, зачем это может понадобиться. Поэтому могу предложить вариант: при клике и протягивании мыши с зажатым Shift-ом выбирать последовательно клетки от той, на которой был изначальный клик до той, над которой мышь отпустили, при клике и протягивании с зажатым Ctrl-ом выбирать ячейки так же, как они выбираются при goRangeSelect = true, то есть, в виде прямоугольника. А потом, когда выбран пункт меню Paste, вставлять так, как я показал выше, начиная от выбранной ячейки и сколько было запомнено. Если тебя такой вариант устроит - чуть позже набросаю проект, как это реализовать (не очень хочется делать, если оно тебе изначально не подходит)
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 10:48  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Все остальные варианты (выбрать несколько ячеек в первом ряду, потом еще несколько в третьем
Это не нужно.Устраивают как раз прямоугольные области.
Единственный вопрос - возможно ли сделать copy paste не через DrawGrid1->Selection
У меня при нажатой левой кнопки мыши и елозанью мышью по гриду в DrawGrid1SelectCell заполняется массив интовый 20 на 10
Grid1SelectCell[ACol][ARow]=1 при выборе ячеек. Далее он используется много где, в том числе и для подсветки выделенных ячеек.
Теперь задача определить(задать) TGridRect sel
Я пробую делать для copy вместо TGridRect sel = DrawGrid1->Selection; что то типа
C++
1
2
3
4
5
6
7
8
9
10
for(int i=0;i<20;i++)
          {
             for(int j=0;j<10;j++)
              {
                  if (Grid1SelectCell[i][j] != 0 )
                    {
                      /*TRect sel= что то, что его определяет*/
                    }
              }
          }
для paste не придумать, пока copy не понятно..
смысл всего этого - оставить goRangeSelect = 0
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 11:04
Сделал вот так:
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
    TPoint topleft, bottomright;
    bool stop = false;
    for (int i = 0; i < 20 && !stop; i++)
        for (int j = 0; j < 10 && !stop; j++)
        {
            if (Grid1SelectCell[i][j] != 0)
            {
                topleft = Classes::Point(i, j);
                stop = true;
            }
        }
 
    if (stop) // верхний угол был найден
    {
        stop = false;
        for (int i = 19; i > -1 && !stop; i--)
            for (int j = 9; j > -1 && !stop; j--)
            {
                if (Grid1SelectCell[i][j] != 0)
                {
                    bottomright = Classes::Point(i, j);
                    stop = true;
                }
            }
    }
. для тестового массива оно мне прекрасно нашло координаты ненулевого прямоугольника:



Потом из этих двух TPoint-ов запросто собирается TRect, если нужно.
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 11:21  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Потом из этих двух TPoint-ов запросто собирается TRect
Спасибо, все подходит. Только как это наложить в copy и paste..
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 11:24
А чего там кидать-то? Все уже сделано, осталось только подставить нужную TRect вместо Selection
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
void __fastcall TForm1::Copy1Click(TObject *Sender)
{
    // тут находишь эти самые topleft и bottomright, создаешь из них TRect:
    TRect sel = Classes::Rect(topleft, bottomright);
    // дальше все без изменений
    CopySize = Point(sel.Right - sel.Left + 1, sel.Bottom - sel.Top + 1);
 
    CopyData->Clear();
    for (int i = sel.Left; i <= sel.Right; i++)
        for (int j = sel.Top; j <= sel.Bottom; j++)
        {
            CopyData->Add(GridData[i][j]);
        }
}
 
void __fastcall TForm1::Paste1Click(TObject *Sender)
{
    // достаточно найти только topleft и работать с ним
    // (я правильно понимаю, что ты выбираешь ячейку, начиная с которой будет вставка,
    // или делается как-то по другому, и при правом клике на ячейку перед выбором Paste
    // нужно запомнить, куда именно кликнули?)
    int k = 0;
    for (int i = 0; i < CopySize.x; i++)
        for (int j = 0; j < CopySize.y; j++)
            GridData[(topleft.Left + i) % 12]
                    [(topleft.Left + i) / 12 + topleft.Top + j] = CopyData->Strings[k++];
    DrawGrid1->Invalidate();
}
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 11:41  [ТС]
да, все пашет.поставил уже
C++
1
TRect sel(topleft, bottomright);
спасибо!
а чем отличается
C++
1
TRect sel = Classes::Rect(topleft, bottomright);
от
C++
1
TRect sel(topleft, bottomright);
или можно и так и эдак?

Добавлено через 11 минут
Цитата Сообщение от volvo Посмотреть сообщение
я правильно понимаю, что ты выбираешь ячейку, начиная с которой будет вставка
да, именно так, но если реализация запоминания может быть - было бы не плохо - может пригодится.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 11:48
Цитата Сообщение от Sergey_03 Посмотреть сообщение
а чем отличается
В этом случае одно и то же, иногда предпочтительней делать вторым способом, если может случиться так, что Top > Bottom или Right < Left, потому что вызов конструктора с двумя параметрами типа TPoint кроме всего прочего еще и нормализует запись (приводит к виду, когда Top < Bottom и Left < Right), функция Classes::Rect этого не делает.
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 11:52  [ТС]
чегото не понятно..не узнает в paste переменной
C++
1
[BCC32 Error] Unit1.cpp(11962): E2451 Undefined symbol 'topleft'
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 12:03
Цитата Сообщение от Sergey_03 Посмотреть сообщение
если реализация запоминания может быть
Еще раз: нет ничего невозможного. Например, обрабатывать OnContextPopup:
C++
1
2
3
4
5
6
void __fastcall TForm1::DrawGrid1ContextPopup(TObject *Sender, TPoint &MousePos, bool &Handled)
{
    // int APopupCol, APopupRow; // где-то снаружи, чтобы можно было потом использовать
    DrawGrid1->MouseToCell(MousePos.x, MousePos.y, APopupCol, APopupRow);
    Handled = false; // Показывать-таки меню, если будет true - то popup-меню не покажется
}
, и заменить в обработчике Paint-а строку заполнения грида на вот эту:
C++
1
2
            GridData[(APopupCol + i) % 12]
                    [(APopupCol + i) / 12 + APopupRow + j] = CopyData->Strings[k++];
не узнает в paste переменной
Так она должна быть либо описана локально, и первый цикл поиска - тоже, либо должна быть описана где-то в классе формы или глобально, где есть доступ и в тот момент, когда ты ищешь в матрице выбранный прямоугольник, и когда делаешь paste. Я ж тебе 1000 раз говорил: приводи тестовые проекты, у тебя там не пойми что накручено, будут ошибка за ошибкой сыпаться.
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 12:10  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Например, обрабатывать OnContextPopup:
отлично. работает!
Цитата Сообщение от volvo Посмотреть сообщение
Так она должна быть либо описана локально
это я понимаю-
код на paste
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TPoint topleft;
    bool stop = false;
    for (int i = 0; i < 20 && !stop; i++)
        for (int j = 0; j < 10 && !stop; j++)
        {
            if (Grid1SelectCell[i][j] != 0)
            {
                topleft = Classes::Point(i, j);
                stop = true;
            }
        }
   int k = 0;
    for (int i = 0; i < CopySize.x; i++)
        for (int j = 0; j < CopySize.y; j++)
            CurrDevImageFllename[(topleft.Left + i) % 20]
                    [(topleft.Left + i) / 20 + topleft.Top + j] = CopyData->Strings[k++];
    DrawGrid1->Invalidate();
почемуто приводит к ошибке
[BCC32 Error] Unit1.cpp(11971): E2316 'Left' is not a member of 'TPoint'
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 12:55
Ну да. Вот что значит создавать код прямо тут, в редакторе форума. Поправь:
C++
1
2
            CurrDevImageFllename[(topleft.x + i) % 20]
                    [(topleft.x + i) / 20 + topleft.y + j] = CopyData->Strings[k++];
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
15.03.2016, 13:00  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
Ну да
я уже новый Rect определил. Теперь понятно все.Спасибо.
А можно при paste присваивать нужным Grid1SelectCell единицы, начиная с места вставки?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
15.03.2016, 13:04
Ну, так там же, где заполняешь CurrDevImageFllename, по тем же координатам выставляй единицы в Grid1SelectCell

C++
1
2
3
4
5
6
{
            CurrDevImageFllename[(topleft.x + i) % 20]
                    [(topleft.x + i) / 20 + topleft.y + j] = CopyData->Strings[k++];
            Grid1SelectCell[(topleft.x + i) % 20]
                    [(topleft.x + i) / 20 + topleft.y + j] = 1;
}
, по-моему, должно работать
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
16.03.2016, 13:33  [ТС]
Спасибо, все работает.

Добавлено через 23 часа 0 минут
Еще такой вопросик - а можно сделать, что бы если попадало на выделенную ячейку (Grid1SelectCell[A][B] == 1), снимался признак, то есть становилось Grid1SelectCell[A][B] = 0 ?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
16.03.2016, 13:38
Если что попадало?
1
21 / 9 / 4
Регистрация: 15.12.2014
Сообщений: 663
16.03.2016, 13:43  [ТС]
выделении ячеек. я веду по гриду мышью - например в нулевой строке - с 0 по 10 ячейку выделил, потом передумал и на две влево сдвинул мышь. По типу, как при Selection чтобы работало. Если это конечно реально.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33480 / 21578 / 8250
Регистрация: 22.10.2011
Сообщений: 37,041
Записей в блоге: 12
16.03.2016, 13:56
Проблема вся в том, что ты вообще не рассказал, как у тебя тот массив Grid1SelectCell заполняется 1-цами, вот когда расскажешь, где именно (в каком событии, при каких условиях) происходит его заполнение - тогда можно будет что-то советовать.

Не верю, что просто по OnMouseMove проверяется признак "кнопка мыши зажата", и если да, то для ячейки, над которой находится мышь, выставляется 1 в Grid1SelectCell.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.03.2016, 13:56

Copy-Paste VIM
Как выделить и сделать копи-пейст?

RichTextBox и Copy/Paste
В общем столкнулся с проблемой копирования и вставки данных из буфера обмена в поле RichTextBox. Во-первых, горячие клавиши (Ctrl +...

Запрет на copy/paste
как сделать так чтоб при открытии ексель запускалась прога которая блокирует копирование и вставку ?

Не работает Copy\paste
Доброго времени суток. Не ожидал что увижу такое... в базе не работает Copy\Paste Посмотрел другие базы, там все норм. Сравнил...

Copy/Paste текста в Word
Уважаемые! Не сочтите за труд, подскажите - что не так делаю? Нужно: - открыть в фоновом режиме источник (путь - FileSource); -...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

Новые блоги и статьи
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru