//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
::SendMessage (rich->Handle, EM_SETEVENTMASK, 0 , ENM_LINK|ENM_PROTECTED);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnNotify(TMessage &Message)
{
NMHDR *pNMHDR;
pNMHDR = (NMHDR *)Message.LParam;
switch (pNMHDR->code)
{
case EN_LINK :
OnLink (pNMHDR, (LRESULT *)&Message.Result);
break;
case EN_PROTECTED :
OnProtected (pNMHDR, (LRESULT *)&Message.Result);
break;
default :
TForm::Dispatch(&Message);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
DWORD dwStart;
//get insert position
if (::SendMessage (rich->Handle, EM_GETSEL, (WPARAM)&dwStart, NULL) == -1)
return;
InsertLink (rich->Handle, dwStart, "Go to Tek-Tips", "[URL unfurl="true"]www.tek-tips.com");[/URL]
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::InsertLink(HWND hRich, int nPos, const char *pszTitle, const char *pszURL)
{
Richedit::CHARFORMAT2 cf2;;
int nTitleLen, nURLen;
char *pszLinkBuf = NULL;
//check if ptrs are valid and pszTitle has 2 chars at least
if (!pszURL || !pszTitle || !pszTitle[0] || !pszTitle[1])
return FALSE; //title too short
//get lengths of title & URL
nTitleLen = strlen (pszTitle);
nURLen = strlen (pszURL) + URL_HDR_LEN;
//alloc suff. buf for sprintf, you can manage it some other way;
//to have constant buf, or use EM_SETSEL&EM_REPLACESEL inserting
//text piece by piece to avoid new/delete for each link
pszLinkBuf = new char [nTitleLen + nURLen];
if (!pszLinkBuf)
return FALSE; //alloc failed
//reset cf2
memset (&cf2, 0, sizeof(cf2));
cf2.cbSize = sizeof(cf2);
//1st letter+url len+url text+rest of the title
// "G[0018www.experts-exchange.com]o to Experts-Exchange"
sprintf (pszLinkBuf, "%c%04X%s%s", *pszTitle, nURLen, pszURL, pszTitle + 1);
//set title text
::SendMessage (hRich, EM_SETSEL, nPos, nPos);
::SendMessage (hRich, EM_REPLACESEL, 0, (LPARAM)pszLinkBuf);
//now we don't need the buf anymore, so delete it
delete[] pszLinkBuf;
//apply link style on'G'
::SendMessage (hRich, EM_SETSEL, nPos, nPos+1);
cf2.dwMask = CFE_LINK|CFE_PROTECTED;
cf2.dwEffects = CFM_LINK|CFM_PROTECTED;
::SendMessage (hRich, EM_SETCHARFORMAT, SCF_SELECTION , (LPARAM)&cf2);
//hide URL text
nPos++;
::SendMessage (hRich, EM_SETSEL, nPos, nPos+nURLen);
cf2.dwMask = CFE_LINK|CFE_PROTECTED|CFE_HIDDEN;
cf2.dwEffects = CFM_LINK|CFM_PROTECTED|CFM_HIDDEN;
::SendMessage (hRich, EM_SETCHARFORMAT, SCF_SELECTION , (LPARAM)&cf2);
//apply link&protected style on the rest of the title
nPos += nURLen;
::SendMessage (hRich, EM_SETSEL, nPos, nPos+nTitleLen-1);
cf2.dwMask = CFE_LINK|CFE_PROTECTED;
cf2.dwEffects = CFM_LINK|CFM_PROTECTED;
::SendMessage (hRich, EM_SETCHARFORMAT, SCF_SELECTION , (LPARAM)&cf2);
return TRUE;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnLink(NMHDR* pNMHDR, LRESULT* pResult)
{
ENLINK *pEnLink = (ENLINK *)pNMHDR;
if (pEnLink->msg == WM_LBUTTONDOWN)
{
Richedit::TEXTRANGE tr;
int nURLen, nRange;
//prepare TEXTRANGE and aloc suff. buf for clicked link text
tr.chrg = pEnLink->chrg;
tr.lpstrText = new TCHAR[tr.chrg.cpMax-tr.chrg.cpMin + 1];
if (!tr.lpstrText)
return; //alloc failed
//get the link text
nRange = ::SendMessage (rich->Handle, EM_GETTEXTRANGE, 0 , (LPARAM)&tr);
//get URL length
if (!sscanf (tr.lpstrText + 1, "%04X", &nURLen) ||
nRange < nURLen + 1)
return;
//place zero at the URL's end
tr.lpstrText[nURLen + 1] = 0;
//here is your URL
ShellExecute (NULL, "open", (tr.lpstrText + 1 + URL_HDR_LEN), NULL, NULL, SW_SHOW);
delete[] tr.lpstrText;
}
*pResult = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
{
ENPROTECTED *pEnProtected = (ENPROTECTED *)pNMHDR;
//return 0 to allow modification, 1 otherwise
//allow copy, but deny link modification
*pResult = pEnProtected->msg != WM_COPY;
}