C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Гиперссылка в строке Мемо
** kea
Отправлено: 24.12.2005, 17:15


Не зарегистрирован







Здравствуйте! Как сделать гиперссылку (на свой почтовый) ящик в строке Memo, чтобы при нажати на нее открывался outlook экспресс?
AVC
Отправлено: 26.12.2005, 09:24


Ветеран

Группа: Модератор
Сообщений: 1583



Дешевле воспользоваться Label'ом (обсуждалось пару тем назад). По клику (или другому событию) вызывать
ShellExecute(Handle,"open","mailto:нужный@адрес?subject=тема&body=текст",0,0,SW_SHOWDEFAULT);
Guest
Отправлено: 27.12.2005, 20:21


Не зарегистрирован







QUOTE (AVC @ 26/12/2005, 09:24)
Дешевле воспользоваться Label'ом (обсуждалось пару тем назад). По клику (или другому событию) вызывать
ShellExecute(Handle,"open","mailto:нужный@адрес?subject=тема&body=текст",0,0,SW_SHOWDEFAULT);

Здравствуйте! А как все же сделать гиперссылку в строке Memo? Помогите, пожалуйста.
AVC
Отправлено: 28.12.2005, 09:28


Ветеран

Группа: Модератор
Сообщений: 1583



В строке мемо вы не сможете её показать как ссылку (другим стилем) а так все очень просто. По, допустим, одному нажатию мыша анализируете местоположение курсора или текст под курсором и вызываете ShellExecute.

PS. Была симпатичная статейка как это сделать в richedite, но, к сожалению, форум где она была размещена временно не действует. Как мне помнится принцип такой же. Поищу у себя, может осталась реализация.
kea
Отправлено: 29.12.2005, 11:32


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (AVC @ 28/12/2005, 09:28)
PS. Была симпатичная статейка как это сделать в richedite, но, к сожалению, форум где она была размещена временно не действует.

Здравствуйте!
Был на bcbdev, видел заголовок статьи, но саму стаью не читал.
Что случилось с bcbdev?
Он будет работать?
avc*
Отправлено: 29.12.2005, 11:39


Не зарегистрирован







>Что случилось с bcbdev?
Хозяин форума начал менять провайдера и в процессе переезда сменил работу. Заняться форумом пока у него времени нет.

>Он будет работать?
Очень надеюсь. Я к нему уже как-то привык.
** Admin
Отправлено: 29.12.2005, 16:10


Не зарегистрирован







Воспользуйтесь RxRichEdit — пример к нему есть (см. Demo)
kea
Отправлено: 05.01.2006, 14:22


Станционный диспетчер

Группа: Участник
Сообщений: 80



QUOTE (** Admin @ 29/12/2005, 16:10)
Воспользуйтесь RxRichEdit — пример к нему есть (см. Demo)

Здравствуйте!
А в RzRichEdit — такое есть?
Grigoriy
Отправлено: 15.01.2006, 05:57


Мастер участка

Группа: Участник
Сообщений: 381



Вообще есть компонент TControlScrollBar, в котором хранятся данные о ползунке, но для компонента TMemo скорее всего этот компонент скрыт каким то образом от использования вне методов TMemo.
Для TRichEdit я тоже не нашел свойства типа TControlScrollBar.
SmAlex
Отправлено: 18.01.2006, 13:30


Станционный диспетчер

Группа: Участник
Сообщений: 91



QUOTE (AVC @ 26/12/2005, 09:24)
Дешевле воспользоваться Label'ом (обсуждалось пару тем назад). По клику (или другому событию) вызывать
ShellExecute(Handle,"open","mailto:нужный@адрес?subject=тема&body=текст",0,0,SW_SHOWDEFAULT);

А как прицепить файл в аттачмент?
Guest
Отправлено: 18.01.2006, 13:35


Не зарегистрирован







QUOTE

А как прицепить файл в аттачмент?

Через параметры ShellExecute я не смог найти решения.
Grigoriy
Отправлено: 01.03.2006, 18:41


Мастер участка

Группа: Участник
Сообщений: 381



АГААА !

А я составил код, который исполняет эту мечту !

QUOTE

В строке мемо вы не сможете её показать как ссылку (другим стилем)


Именно в редакторе TMemo
и даже ссылка выделяется цветом при наведении мыши... и подчеркивается желанным цветом. А потом как отпустите кнопку — ссылка на некоторое время станет другим желанным цветом и откроется браузер или почта.
И все это в TMemo.

QUOTE

По, допустим, одному нажатию мыша анализируете местоположение курсора или текст под курсором и вызываете ShellExecute.


И не только. Указатель мыши становится "рукой".

QUOTE

Вообще есть компонент TControlScrollBar, в котором хранятся данные о ползунке, но для компонента TMemo скорее всего этот компонент скрыт каким то образом от использования вне методов TMemo.
Для TRichEdit я тоже не нашел свойства типа TControlScrollBar.


Не, функции API намного лучше всяких там навороченных средств.
API-функции  — свобода программирования под WINDOWS !
С помощью них можно обдурить компоненты.

Вы знаете, что все редакторы, включая TMemo, TEdit и другие компоненты в своем большинстве — это по настоящему дочерние окна того окна, в котором они находятся ?
Так вот я вам могу объяснить, что TMemo — это дочернее окно формы, только система программирования от вас это скрывает biggrin.gif .

Хотите нарисовать что-нибудь в Memo ?

Вот пример кода рисования в Memo1

CODE

//..........
HDC d;
tagPOINT* fr=new tagPOINT;
d=GetDC(Memo1->Handle);
MoveToEx(d,10,10,fr);
LineTo(d,60,60);
//..........


Попробуйте даже прокрутить Memo и изображение будет перемещаться. Но если изображение выйдет за границу отображаемой области, оно конечно сотрется. нужно будет постоянно перерисовывать его.

А насчет узнать положение полос прокрутки...
есть вот такие API-функции

function GetScrollPos(Wnd: HWnd; Bar:Integer): Integer;

Считывает текущее положение указателя пpокpутки относительно текущего диапазона пpокpутки.

Паpаметpы:
Wnd: Окно, содеpжащее полосу пpокpутки.
Bar: Одна из констант SB_CTL, SB_HORZ, SB_VERT.

Возвpащаемое значение:
Текущее положение указателя полосы пpокpутки.

Функция GetScrollRange

Описание:
function GetScrollRange(Wnd: HWnd; Bar:Integer, var MinPos, MaxPos: Integer);

Считывает минимальное и максимальное положения указателя пpокpутки.

Паpаметpы:
Wnd: Окно, содеpжащее полосу пpокpутки.
Bar: Одна из констант SB_CTL, SB_HORZ, SB_VERT.
MinPos: Целое для пpиема минимального положения.
MaxPos: Целое для пpиема максимального положения.

А Wnd=Memo1->Handle.

Ну и наконец мой код

Эта функция возвращает строку со ссылкой, которая находится в Memo по координатам точки. Если точке не принадлежит ссылка — возвращается пустая строка.
Кроме того обеспечиваются дополнительные эффекты.
Если ссылка на адрес электронной почты, то в возвращаемом значении уже будет "mailto:".

CODE

AnsiString GetandActivateLinkfromMemo(TMemo* Memol,int X, int Y, TColor colorlink)
{
TControlCanvas* canv;
HWND gt;
TColor color1, color2;
TFontStyles temp1;
int jg,jg1,posv,pos1,pos2,w1,bor,h,n1,typeaddr,t;
AnsiString Smemo;
AnsiString LinkMemo;
static int pr1;
unsigned int Xstrv, Ystrv;
static unsigned int Xstrv1, Ystrv1;
gt=Memol->Handle;
jg=GetScrollPos(gt,SB_VERT);
jg1=GetScrollPos(gt,SB_HORZ);
canv = new TControlCanvas;
canv->Handle=GetDC(Memol->Handle);
canv->Font=Memol->Font;
h=canv->TextExtent(" ").cy;
posv=jg+Y/h;
Smemo=Memol->Lines->Strings[posv];
if (Memol->BorderStyle==bsSingle) {bor=1;} else {bor=0;};
n1=1;
while (canv->TextExtent(Smemo.SubString(1,n1)).cx<(X+jg1))
{n1++;
if (n1>Smemo.Length()) break;};
if (n1<=Smemo.Length()) {
pos1=n1;
while (Smemo[pos1]!=' ')
{
pos1--;
if (!pos1) break;
};
pos1++;
pos2=n1;
while (Smemo[pos2]!=' ')
{
pos2++;
if (pos2>Smemo.Length()) break;
};
pos2--;
if (pos1<=pos2){
LinkMemo=Smemo.SubString(pos1,pos2-pos1+1);
if (!((LinkMemo.SubString(1,7).LowerCase()=="http://")||(LinkMemo.SubString(1,4).LowerCase()=="www.")))
{
if (LinkMemo.Pos("@")){
typeaddr=2;}
else typeaddr=0;
}
else typeaddr=1;
}
else typeaddr=0;
}
else typeaddr=0;
if (typeaddr)
{
w1=canv->TextExtent(Smemo.SubString(1,pos1-1)).cx;
color1=canv->Font->Color;
canv->Font->Color=colorlink;
temp1=canv->Font->Style;
canv->Font->Style=canv->Font->Style << fsUnderline;
Xstrv=w1-jg1+bor;
Ystrv=h*(posv-jg)+bor;
if ((Xstrv!=Xstrv1)||(Ystrv!=Ystrv1))
{Xstrv1=Xstrv;Ystrv1=Ystrv;
Memol->Repaint();};
canv->TextOut(Xstrv,Ystrv,LinkMemo);
pr1=1;
canv->Font->Color=color1;
canv->Font->Style=temp1;
Memol->Cursor=crHandPoint;
}
else {Memol->Cursor=crArrow;
if (pr1) {pr1=0;Memol->Repaint();
}
LinkMemo="";
};
delete canv;
if (typeaddr==2) LinkMemo="mailto:"+LinkMemo;
return LinkMemo;
};


А это обработчики соответствующих событий от мыши

CODE

void __fastcall TForm1::Memo1MouseMove(TObject *Sender, TShiftState Shift,
     int X, int Y)
{
GetandActivateLinkfromMemo(Form1->Memo1,X,Y,0xff00);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Memo1MouseUp(TObject *Sender, TMouseButton Button,
     TShiftState Shift, int X, int Y)
{
AnsiString t;
t=GetandActivateLinkfromMemo(Form1->Memo1,X,Y,0xff);
if (t.Length())
ShellExecute(Form1->Handle,0,t.c_str(),0,0, SW_SHOWNORMAL);
}
Smart
Отправлено: 01.03.2006, 21:56


Дежурный стрелочник

Группа: Участник
Сообщений: 35



Афигеть, работает!
Автору — орден Сутулова!

Жаль, криво работает с RichEdit: пока скроллинг на нуле, все нормально, но стоит чуть прокрутить — подсветка не робить... sad.gif(
Grigoriy
Отправлено: 02.03.2006, 02:06


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE (Smart @ 01/03/2006, 21:56)
Жаль, криво работает с RichEdit: пока скроллинг на нуле, все нормально, но стоит чуть прокрутить — подсветка не робить... sad.gif(

ЭЭЙ !
До RichEdit Я ещё не дошёл.
Grigoriy
Отправлено: 02.03.2006, 03:47


Мастер участка

Группа: Участник
Сообщений: 381



А как мне узнать данные об отображении всего текста в компоненте RichEdit ?
Сейчас пока разгадать структуру данных компонента RichEdit для меня не представляется возможным.
В Delphi дан пример работы с компонентом.
Но работа в том примере осуществляется пользовательски.
То есть компонент преобразует текст используя текущее положение курсора и текущую выделенную часть.

Вопрос в том, как мне например изменить параметры той строки текста, на которой вовсе не стоит курсор и нет выделенных символов ?

Вот интересно, ответить может на это вопрос кто-то ?
Grigoriy
Отправлено: 02.03.2006, 04:38


Мастер участка

Группа: Участник
Сообщений: 381



Интересно, почему когда я просто читаю одну какую-нибудь строчку из
RichEdit1->Lines
и пишу её в Edit1 то строчка записывается без тегов.
А если я сохраняю набор строк в файл, то строки сохраняются с тегами

???
Smart
Отправлено: 02.03.2006, 13:20


Дежурный стрелочник

Группа: Участник
Сообщений: 35



Было бы интересно, если было бы не так! smile.gif
--
С нетерпением (и благоговением) жду варианта для RichEdit, очень нада!
Alex1000
Отправлено: 02.03.2006, 14:14


Ученик-кочегар

Группа: Участник
Сообщений: 13



У TRichEdit есть свойство PlainText. Ставишь его в true и текст будет сохраняться и читаться без тегов.
AVC
Отправлено: 02.03.2006, 16:44


Ветеран

Группа: Модератор
Сообщений: 1583



Раз тема все еще интересна — статью у себя найти не смог, был свободный час — набросал макет кода. На работоспособность проверил, но код еще сырой.
CODE

в .h
private:
 TShiftState FREOldShift;

в .cpp

//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
TRichEdit  *re = RichEdit1;
re->Text = "";
re->PlainText = false;

 re->Lines->LoadFromFile(ExtractFilePath(Application->ExeName) + "link.rtf");
//re->Lines->LoadFromFile(ExtractFilePath(Application->ExeName) + "link1.rtf");
}

//---------------------------------------------------------------------------

void __fastcall TForm1::RichEdit1MouseDown(TObject *Sender,
     TMouseButton Button, TShiftState Shift, int X, int Y)
{
FREOldShift = Shift;    // запомнить состояние нажатия
}

//---------------------------------------------------------------------------


void __fastcall TForm1::RichEdit1MouseUp(TObject *Sender,
    TMouseButton Button, TShiftState Shift, int X, int Y)
{
LabelS1->Caption = "";  // отладка для контроля

TRichEdit *re = dynamic_cast<TRichEdit*>(Sender);
if (!re)  return;

if (re->SelLength > 0)             return; // пропустить выделение
if (!FREOldShift.Contains(ssLeft)) return; // была нажата левая кнопка

TTextAttributes* att = re->SelAttributes;  // что под курсором

// Знаю, что у меня в тексте гиперссылки выделены синим цветом с подчеркиванием
if (!(att->Color == clBlue && att->Style.Contains(fsUnderline))) return;

// Выделить область текста имеющие атрибуты гиперссылки
int oldss = re->SelStart;
int linkstart;
for (linkstart = oldss; linkstart > 0; linkstart--)
{  re->SelStart = linkstart;
   if (!(att->Color == clBlue && att->Style.Contains(fsUnderline)))   break;
}

int linkstop;
int tlen = re->Text.Length();
for (linkstop = oldss + 1; linkstop < tlen; linkstop++)
{  re->SelStart = linkstop;
   if (!(att->Color == clBlue && att->Style.Contains(fsUnderline)))   break;
}
linkstop --;
re->SelStart = oldss;

AnsiString linktext = re->Text.SubString(linkstart+1, linkstop-linkstart).Trim();

// Осталось только по найденому тексту через ассоциированный массив найти
// и выполнить переход по ссылке

LabelS1->Caption = "<" + linktext + ">";
}
//---------------------------------------------------------------------------

Примеры rtf на которых тестировал
CODE

link.rtf
{\rtf1\ansi\ansicpg1251\deff0
{\fonttbl
{\f0\fnil Arial;
 \f1\fnil Courier New;
}
}
{\colortbl
;
\red000\green000\blue255;
\red128\green000\blue000;
\red255\green255\blue255;
}
\cf1\ul\b\i link1 sample \cf0\ulnone\b0\i0
}



link1.rtf
{\rtf1\ansi\ansicpg1251\deff0
{\fonttbl
{\f0\fnil Arial;
 \f1\fnil Courier New;
}
}
{\colortbl
;
\red000\green000\blue255;
\red128\green000\blue000;
\red255\green255\blue255;
}
\lang1049\viewkind4\uc1
\pard\qc
\f1\fs48\cf3\highlight2\b\~A\~s\~d\~\b0\highlight0
\par
\pard\ql
\f0\fs24\cf0
Some text
\cf1\ul\b\i link1 sample \cf0\ulnone\b0\i0
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Other text\par
Some text \cf1\ul\b\i link2 sample \cf0\ulnone\b0\i0
Other text\par
Other text text text text text text text text text text text \cf1\ul\b\i link3 sample \cf0\ulnone\b0\i0
 text text text text text text text text text text text text text
\par
Other text\par
Other text\par
}


Вернуться в Вопросы программирования в C++Builder