dEEp |
Отправлено: 27.02.2005, 19:44 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Здраствуйте. Подскажите мне...
На форме расположено Memo в котором есть текст.
А также кнопка.
Имеется массив слов...
Например,
CODE | AnsiString w0rds[3]={"help", "your", "send"}; |
Необходимо, чтобы при клике по кнопке в строке выделилось слово, а именно w0rds[1]. Кликаешь ещё раз и уже в следующей строке (или в этой же) выделяется слово w0rds[2].
Это необходимо для того, чтобы пользователь обратил внимание на выделенное слово.
Вот пример...
Дан текст (английским владею плохо):
Hi! My name is Alexander. You can help me?
What your name?
Please, send me...
User кликает по кнопке и выделяется слово "help", затем кликает ещё раз и выделяется "your", затем ещё раз и уже слово "send". Маленький дополнение Кникаешь ещё раз и опять выделяется первое слово — "help". То есть цикл получается. Понятно? Дело в том, что я пишу программу по изучению английского языка (переводчик (человек) имеется, а то я его плохо знаю). Кто может — помогите. Как всё это реализовать?
|
|
Aptem |
Отправлено: 28.02.2005, 06:26 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
Поиск делается очень просто, у класса AnsiString есть методы: Pos и SubString. Вот их и используй!
|
|
dEEp |
Отправлено: 28.02.2005, 08:26 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
В принципе я разобрался.
Слово нахожу, а вот выделить его проблемно.
Вот кусок кода...
CODE |
AnsiString w0rds[6]={"gets up", "go to home", "hi", "oh", "very", "work"};
AnsiString Str;
int c0unt=Memo1->Lines->Count;
int Positi0n;
for (int i=0; i<=c0unt; i++)
{
if (Memo1->Lines->Text.AnsiPos(w0rds[1]))
{
Str=Memo1->Lines->Strings[i];
int temp=w0rds[0].Length();
Positi0n=Str.Pos(w0rds[0]);
if (Positi0n>0)
{
Memo1->SelStart=Positi0n;
Memo1->SelLength=temp;
// Memo2->Text=Positi0n; - нужно было для проверки
}
}
}
|
Естественно код не доделан. Пока что он ищет только одно слово. А вот что с выделением? Я не знаю как выделить найденное слово. Есть ли простой способ? Хотя давайте любой...
Кстати, Aptem, ты уже не первый раз помогаешь! Выражаю благодарность!
Жду ответов...
Приеду с учёбы (после 19:00) посмотрю. Надеюсь на помощь...
|
|
Konstantine |
Отправлено: 28.02.2005, 09:21 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
Выделяет... просто по default у Memo свойство HideSelection установлено в true, а оно означает — скрывать выделение при неактивном контроле, поэтому чтоб увидеть выделение нужно:
1) сделать Memo1 активным, т.е. после назначения выделения вставить CODE | ActiveControl=Memo1; |
2) установить HideSelection в false, это можно сделать и через инспектора обьектов;
а ещё лучше — сделать и то и другое, т.к. при неактивном контроле выделение другое по цвету (у меня станд.схема XP — в активном — тёмно-синее, а при неактивном — серое)
|
|
dEEp |
Отправлено: 28.02.2005, 12:39 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Костя, чего-то я плохо понял. Подробнее можешь?
|
|
Konstantine |
Отправлено: 28.02.2005, 15:30 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
в инспекторе обьектов для обьекта Memo1 установи HideSelection в false... для этого:
1) не запуская программу выдели на форме Memo1;
2) обычно справа от формы имеется инспектор обьектов (Object Inspector) если нету — то включи отображение через меню View;
3) в этом инспекторе открыть вкладку Properties;
4) найти св-во HideSelection и установи его в false;
в коде после строк CODE | Memo1->SelStart=Positi0n;
Memo1->SelLength=temp; | добавь строку CODE | ActiveControl=Memo1; |
если чего-то неясно — уточни где именно...
|
|
dEEp |
Отправлено: 28.02.2005, 19:38 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Я не понял, что мне это даёт.
Он итак выделяет. Проблема со строкой. То есть в какой строке что
выделить...
|
|
Bond |
Отправлено: 28.02.2005, 19:54 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
идешь по мемо, ищешь абсолютную позицию нужного слова, задаешь
Memo1->SelStart = AbsOffset;
Memo1->SelLength = WordLength;
|
|
dEEp |
Отправлено: 01.03.2005, 02:34 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
QUOTE (Bond @ 28/02/2005, 19:54) | идешь по мемо, ищешь абсолютную позицию нужного слова, задаешь
Memo1->SelStart = AbsOffset;
Memo1->SelLength = WordLength; |
Ничего не понял...
|
|
Bond |
Отправлено: 01.03.2005, 11:01 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Свойства класса TMemo SelStart и SelLength — это переменные, которые задают первый символ отмеченного текста и длину отмеченного текста в символах соответственно.
Эти свойства не работают со строками, они работают со всем текстовым буфером класса TMemo. Например в TMemo есть следующие строки:
------------------------------------
1
234
567890
------------------------------------
и нам необходимо выделить 89.
Подсчитаем абсолютное смещение относительно буфера (не забываем что нужно учитывать символ переноса строки "\n"):
CODE | Memo1->SelStart =
strlen( "1 " ) + 1 +
strlen( "234" ) + 1 +
strlen( "567") = 9 | и считаем длину отмеченного текста:CODE | Memo1->SelLength = strlen( "89" ) = 2 |
|
|
Bond |
Отправлено: 01.03.2005, 11:03 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Извини, тут нужно к длине каждой строки прибавлять не единицу, 2
|
|
dEEp |
Отправлено: 01.03.2005, 16:35 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Большое спасибо. В принципе я понял. Сегодня вечером попробую, а ночью напишу ответ. Так что ждите. Уверен, что ваша помощь мне ещё понадобится.
|
|
dEEp |
Отправлено: 05.03.2005, 14:15 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Всё получилось! Сделал! Работает! Спасибо всем!
*.exe я присоединить не смог — ругается сервер.
Протестируйте пожалуйста. Увидете глюки — пишите
Вот исходник. В библиотеке объявлен int flag.
CODE |
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int flag2=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
Application->Terminate();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{
int c0unt=Memo1->Lines->Count;
if (flag2>0)
{
flag++;
}
if (flag>7)
{
flag=0;
}
flag2=1;
Memo2->Text=flag;
for (int i=0; i<=c0unt; i++)
{
switch (flag)
{
case (0): {
Memo1->SelStart=68;
Memo1->SelLength=strlen("gets up");
Edit1->Text="gets up — вставать";
} break;
case (1): {
Memo1->SelStart=183;
Memo1->SelLength=strlen("gets the breakfast ready");
Edit1->Text="gets the breakfast ready — завтракать";
} break;
case (2): {
Memo1->SelStart=219;
Memo1->SelLength=strlen("gets washed");
Edit1->Text="gets washed — умываться";
} break;
case (3): {
Memo1->SelStart=244;
Memo1->SelLength=strlen("gets dressed");
Edit1->Text="gets dressed — одеваться";
} break;
case (4): {
Memo1->SelStart=461;
Memo1->SelLength=strlen("gets ready");
Edit1->Text="gets ready — готовиться";
} break;
case (5): {
Memo1->SelStart=695;
Memo1->SelLength=strlen("In the evening");
Edit1->Text="In the evening — вечером";
} break;
case (6): {
Memo1->SelStart=980;
Memo1->SelLength=strlen("newspaper");
Edit1->Text="newspaper — газета";
} break;
case (7): {
Memo1->SelStart=1323;
Memo1->SelLength=strlen("get undressed");
Edit1->Text="get undressed — раздеваться";
flag=0; // f0r go to begin text...
flag2=0;
} break;
}
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
int c0unt=Memo1->Lines->Count;
if (flag2>0)
{
flag--;
}
if (flag<0)
{
flag=7;
}
flag2=1;
Memo2->Text=flag;
for (int i=0; i<=c0unt; i++)
{
switch (flag)
{
case (0): {
Memo1->SelStart=68;
Memo1->SelLength=strlen("gets up");
Edit1->Text="gets up — вставать";
flag=7;
flag2=0;
} break;
case (1): {
Memo1->SelStart=183;
Memo1->SelLength=strlen("gets the breakfast ready");
Edit1->Text="gets the breakfast ready — завтракать";
} break;
case (2): {
Memo1->SelStart=219;
Memo1->SelLength=strlen("gets washed");
Edit1->Text="gets washed — умываться";
} break;
case (3): {
Memo1->SelStart=244;
Memo1->SelLength=strlen("gets dressed");
Edit1->Text="gets dressed — одеваться";
} break;
case (4): {
Memo1->SelStart=461;
Memo1->SelLength=strlen("gets ready");
Edit1->Text="gets ready — готовиться";
} break;
case (5): {
Memo1->SelStart=695;
Memo1->SelLength=strlen("In the evening");
Edit1->Text="In the evening — вечером";
} break;
case (6): {
Memo1->SelStart=980;
Memo1->SelLength=strlen("newspaper");
Edit1->Text="newspaper — газета";
} break;
case (7): {
Memo1->SelStart=1323;
Memo1->SelLength=strlen("get undressed");
Edit1->Text="get undressed — раздеваться";
} break;
}
break;
}
}
//---------------------------------------------------------------------------
|
Вот такой вод код. Теперь объясняю...
1. flag — это, по сути дела, индекс слова.
2. flag2 — с помощью его проверяем нажатие кнопок.
Остальное всё должно быть понятно. Вот только проблемка...
В моей программе выделение слова происходит путём назначения номера символа с которого нужно выделять. Так вот теперь мне нужно переписать эту программу так, чтобы поиск по словам происходил. Т.е. так, как я описывал раньше.
Мысли есть? Пишите... ночью посмотрю....
|
|
dEEp |
Отправлено: 05.03.2005, 14:29 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
ScreenShot
Присоединить изображение
|
|
Bond |
Отправлено: 05.03.2005, 15:25 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
в Unit1.cppCODE | //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ComboBox1->ItemIndex = 0;
LastFind = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString text = Memo1->Lines->Text;
AnsiString subString = text.SubString( LastFind+1, text.Length() );
int result = subString.Pos( ComboBox1->Text );
if( result > 0 )
{
Memo1->SelStart = LastFind + result — 1; Memo1->SelLength = ComboBox1->Text.Length();
LastFind += result;
}
else
{
LastFind = 0;
Memo1->SelLength = 0;
result =
MessageBox(NULL,"Слово не найдено. Начать с начала текста?","Поиск",MB_YESNOCANCEL);
switch( result )
{
case IDNO:
if( ComboBox1->ItemIndex < ComboBox1->Items->Count-1 ) ComboBox1->ItemIndex++;
else ComboBox1->ItemIndex = 0;
Button1Click(Sender);
break;
case IDYES:
Button1Click(Sender);
break;
}
}
} |
в Unit1.h
|
|
dEEp |
Отправлено: 05.03.2005, 20:17 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Не могли бы Вы вкратце раъяснить?
|
|
dEEp |
Отправлено: 05.03.2005, 20:49 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
До меня "дошло". Попытаюсь внедрить в свой код...
|
|
dEEp |
Отправлено: 06.03.2005, 10:47 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Каким образом можно добавить слово в массив искомых слов.
Т.е. есть массив слов, которые мы ищем в Memo, а вдруг приспичило добавить туда ещё
одно или несколько слов. Что тогда? Как лдобавить в массив. Было бы хорошо, чтобы при следующем запуске
был уже новый массив (с добавленным словом). Я предполагаю, что можно сделать
файл, в котором будут храниться искомые слова. А если приспичит, то тогда открываем файл
и дописываем туда слово (всё это делать не в ручную, а с помощью Edit'ов и Button'ов). Так?
Или есть способ получше?
Присоединить изображение
|
|
GIZMO |
Отправлено: 09.03.2005, 10:27 |
|
Машинист паровоза
Группа: Участник
Сообщений: 174
|
QUOTE (dEEp @ 06/03/2005, 10:47) | Каким образом можно добавить слово в массив искомых слов.
Т.е. есть массив слов, которые мы ищем в Memo, а вдруг приспичило добавить туда ещё
одно или несколько слов. Что тогда? Как лдобавить в массив. Было бы хорошо, чтобы при следующем запуске
был уже новый массив (с добавленным словом). Я предполагаю, что можно сделать
файл, в котором будут храниться искомые слова. А если приспичит, то тогда открываем файл
и дописываем туда слово (всё это делать не в ручную, а с помощью Edit'ов и Button'ов). Так?
Или есть способ получше? |
TStringList — 4 your...
CODE |
//in hp
private:
TStringList* sl
//in cpp
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
sl = new TStringList();
sl->LoadFromFile("filename.txt");
}
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
if(sl->IndexOf(Ediit1->Text) == -1)
sl->Add(Edit1->Text);
}
__fastcall TForm1::~TForm1()
: TForm(Owner)
{
sl->SaveToFile("filename.txt");
delete sl;
}
|
|
|
Bond |
Отправлено: 09.03.2005, 11:37 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Можешь добавить кнопочку "Back". Для этого необходимо:
- при нахождении слова добавлять в список а) искомое слово; б) позицию слова в тексте и BackButton->Enabled = false;
- [B]при редактировании текста список обнулять, BackButton->Enabled = false;
|
|
Bond |
Отправлено: 09.03.2005, 11:40 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Извините, допустил ошибки .
Можешь добавить кнопочку "Back". Для этого необходимо:
- при нахождении слова добавлять в список а) искомое слово; б) позицию слова в тексте и BackButton->Enabled = true;
- при редактировании текста список обнулять, BackButton->Enabled = false;
|
|
Bond |
Отправлено: 09.03.2005, 12:51 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
P.S.
- при нажатии клавиши "Back" контролировать начало списка: если уже некуда "Бэкать" — BackButton->Enabled = false;
|
|
dEEp |
Отправлено: 10.03.2005, 17:28 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 69
|
Это я уже реализовал.
|
|
telepath |
Отправлено: 10.03.2005, 17:38 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 132
|
Странная конструкция...
CODE | switch(/*----*/)
{
case 0:
{
/*---------*/
} break;
} |
не будет ли тут ошибочки?
Отредактировано telepath — 10/03/2005, 17:39 |
|
Bond |
Отправлено: 10.03.2005, 18:04 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 142
|
Это простые операторные скобки, которые объединяют несколько операторов. Никакой ошибки не будет
|
|