一个困扰了我大学两年的问题,关于richedit,请教高手了,谢谢了

chenxidu 2008-03-31 05:12:51


或许这个图片,你们看不到,
我把思路先说一下,困扰了我很久的一个问题。我是个学生,希望大家指教我一下!!!

问题:
我在richedit书写内容的时候,
想让richedit,随着richedit内容行数的增加,richedit自动换行(这个知道怎么做)和加长,

困扰的地方:
但是这个richedit每多一行后,因为字体大小不一样的话,
,当书写的人改变字体的时候,两行之间的间距也不一样,
那么这个加长的数值,很难确定,谁能给个思路了?


谁能给我一个思路,把心中的疙瘩解开了,

下面是我以前的笨办法:
int icnt = SendMessage(rie_edit->Handle,EM_GETLINECOUNT,0,0);
if(icnt!= i_line_count)
{
i_line_count = icnt;
if(rie_edit->Font->Size == 12)
{
rie_edit->Height = (-rie_edit->Font->Height+4)*i_line_count;
}
if(rie_edit->Font->Size>12 && rie_edit->Font->Size<=14)
{
rie_edit->Height = (-rie_edit->Font->Height+4)*i_line_count;
}
if(rie_edit->Font->Size>14 && rie_edit->Font->Size>16)
{
rie_edit->Height = (-rie_edit->Font->Height+5)*i_line_count;
}

SendMessage(rie_edit->Handle,WM_VSCROLL, SB_TOP,0);
this->Height = rie_edit->Height + 30;
}

这样做,太不准确了,不是我吝啬,我只有40分!
...全文
460 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenxidu 2008-04-02
  • 打赏
  • 举报
回复
谢谢楼上,我好好的看看你的代码!很感激!
wenyongjie 2008-04-02
  • 打赏
  • 举报
回复
MARK
Waiting4you 2008-04-02
  • 打赏
  • 举报
回复
经过偶一个多小时的“研究”,终于找到一个比较“官方”的方法,利用EN_REQUESTRESIZE通知。在BCB里有个反射机制让WM_NOTIFY发到父窗口后给回给自己一个CN_NOTIFY,下面代码就是使用的这个CN_NOTIFY:

class TAutoSizeRichEdit
: public TComponent // 继承TComponent是为了能自动删除
{
TCustomRichEdit *m_pRichEdit;
TWndMethod OldProc;
void __fastcall NewProc(Messages::TMessage &Message)
{
OldProc(Message);
if(Message.Msg == CN_NOTIFY)
{
REQRESIZE *prqs = (REQRESIZE *)Message.LParam;
if(prqs->nmhdr.code == EN_REQUESTRESIZE)
{
m_pRichEdit->Height = prqs->rc.bottom - prqs->rc.top; // 如果是CN_NOTIFY + EN_REQUESTRESIZE,则调整大小
}
}
}

public:
__fastcall TAutoSizeRichEdit( TCustomRichEdit *pRichEdit )
:TComponent(pRichEdit),m_pRichEdit(pRichEdit)
{
OldProc = m_pRichEdit->WindowProc; // 子类化RichEdit,用NewProc代替它原来的消息处理
m_pRichEdit->WindowProc = NewProc;

m_pRichEdit->Perform(EM_SETEVENTMASK,0,ENM_REQUESTRESIZE); // 允许EN_REQUESTRESIZE消息
m_pRichEdit->Perform(EM_REQUESTRESIZE,0,0); // 强制发送一个EN_REQUESTRESIZE消息,用于立即调整大小
}

__fastcall ~TAutoSizeRichEdit()
{
m_pRichEdit->WindowProc = OldProc;
}
};


void __fastcall TForm1::FormCreate(TObject *Sender)
{
new TAutoSizeRichEdit(RichEdit1); // 子类化RichEdit1,不必担心内存泄漏,它会随着RichEdit1的删除一起删除的
}
//---------------------------------------------------------------------------
小笨象 2008-04-02
  • 打赏
  • 举报
回复
毛毛最强!
收藏!
truelove7283159 2008-04-01
  • 打赏
  • 举报
回复
void CEditMELFA::CalcTextMetric(void)
{
CClientDC dc(this);

是新函数的开始,
不相关的你都可以删除掉看,不过最好去看tms那个下面的一个edit控件,好像已经做到你那些功能的。
truelove7283159 2008-04-01
  • 打赏
  • 举报
回复
void CEditMELFA::OnChange()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CRichEditCtrl::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.

// TODO: Add your control notification handler code here
if(0 ==GetTextLength())
{
SetLineSpace(m_CurSysConfig.mSysTextEditor.mLineSpace);
}


{






LONG CEditMELFA::SetLineSpace(LONG nSpace)
{
if (NULL == m_pMainWnd)
{
return ROBOTCONTROL_ERROR_NOTPARENTWND;
}

if(nSpace<1)
{
return ROBOTCONTROL_ERROR_PARAMETER;
}

LONG ret = ROBOTCONTROL_ERROR_OK;

if (ret == ROBOTCONTROL_ERROR_OK)
{
//if (m_CurSysConfig.mSysTextEditor.mLineSpace != nSpace)
{

m_CurSysConfig.mSysTextEditor.mLineSpace = nSpace;

CHARFORMAT cf;
memset(&cf, 0, sizeof(cf));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_SIZE;
SendMessage(EM_GETCHARFORMAT, (WPARAM)(UINT)SCF_DEFAULT, (LPARAM) &cf);

CHARRANGE tmpCr, oldCr;
GetSel(oldCr);

tmpCr.cpMin = 0;
tmpCr.cpMax = -1;
SetSel(tmpCr);

PARAFORMAT2 pf2;
memset(&pf2, 0, sizeof(pf2));
pf2.cbSize = sizeof(PARAFORMAT2);
pf2.dwMask = PFM_LINESPACING;
pf2.bLineSpacingRule = 4;
pf2.dyLineSpacing = cf.yHeight+m_CurSysConfig.mSysTextEditor.mLineSpace*20 + 20; //TWIPS (20 * Points)
SendMessage(EM_SETPARAFORMAT, (WPARAM)(UINT)SCF_SELECTION, (LPARAM)&pf2);

SetSel(oldCr);

SendMessage(EM_SETCHARFORMAT, (WPARAM)(UINT)SCF_DEFAULT, (LPARAM)&cf);
SendMessage(EM_SETPARAFORMAT, (WPARAM)(UINT)SCF_DEFAULT, (LPARAM)&pf2);
EmptyUndoBuffer();

CalcTextMetric();
UpdateLeftAreas();
UpdateTopAndBottom();
}
}

return ret;
}

LONG CEditMELFA::SetTextFont(CString strFont,LONG nSize)
{

if (strFont.IsEmpty() || nSize<0)
{
return ROBOTCONTROL_ERROR_NOTPARENTWND;
}


LONG ret = ROBOTCONTROL_ERROR_OK;

if (m_pMainWnd == NULL)
{
ret = ROBOTCONTROL_ERROR_NOTPARENTWND;
}

if (ret == ROBOTCONTROL_ERROR_OK)
{
m_CurSysConfig.mSysTextEditor.FontName = strFont;
m_CurSysConfig.mSysTextEditor.FontSize = nSize;
CHARRANGE tmpCr, oldCr;
GetSel(oldCr);

tmpCr.cpMin = 0;
tmpCr.cpMax = -1;
SetSel(tmpCr);
CHARFORMAT cf;
memset(&cf, 0, sizeof(cf));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwEffects = CFE_PROTECTED;
cf.dwMask = CFM_BOLD | CFM_FACE | CFM_SIZE | CFM_CHARSET | CFM_PROTECTED;//cf.dwMask = CFM_FACE|CFM_SIZE|CFM_PROTECTED;
cf.yHeight = nSize*20; //TWIPS (20 * Points)
lstrcpy(cf.szFaceName, strFont);
SendMessage(EM_SETCHARFORMAT, (WPARAM)(UINT)SCF_SELECTION, (LPARAM) &cf);//SetDefaultCharFormat(cf);

PARAFORMAT2 pf2;
memset(&pf2, 0, sizeof(pf2));
pf2.cbSize = sizeof(PARAFORMAT2);
pf2.dwMask = PFM_LINESPACING;
pf2.bLineSpacingRule = 4;
pf2.dyLineSpacing = nSize*20+m_CurSysConfig.mSysTextEditor.mLineSpace*20 + 40; //TWIPS (20 * Points)


SendMessage(EM_SETPARAFORMAT, (WPARAM)(UINT)SCF_SELECTION, (LPARAM)&pf2);

SetSel(oldCr);

SendMessage(EM_SETCHARFORMAT, (WPARAM)(UINT)SCF_DEFAULT, (LPARAM)&cf);
SendMessage(EM_SETPARAFORMAT, (WPARAM)(UINT)SCF_DEFAULT, (LPARAM)&pf2);

//todo lijiwu
PARAFORMAT pf;
pf.cbSize = sizeof(PARAFORMAT);
pf.dwMask = PFM_TABSTOPS ;
pf.cTabCount = MAX_TAB_STOPS;

for( int itab = 0 ; itab < pf.cTabCount ; itab++ )
pf.rgxTabs[itab] = (itab + 1) * 1440/5 ;
SetParaFormat( pf );

EmptyUndoBuffer();

CalcTextMetric();

}

return ret;
}

{
CClientDC dc(this);

CHARFORMAT cf;
LOGFONT lf;
memset(&cf, 0, sizeof(cf));
memset(&lf, 0, sizeof(lf));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_ALL;
SendMessage(EM_GETCHARFORMAT, (WPARAM)(UINT) SCF_DEFAULT, (LPARAM) &cf);

int logPixelsY = dc.GetDeviceCaps(LOGPIXELSY);
// cf.yHeight is in TWIPS (20 * Points)
int lfcfHeight = cf.yHeight/20; // In Points
lf.lfHeight = -MulDiv(lfcfHeight, logPixelsY, 72);
lstrcpy(lf.lfFaceName, cf.szFaceName);
lf.lfPitchAndFamily = cf.bPitchAndFamily;
lf.lfUnderline = (cf.dwEffects & CFM_UNDERLINE) ? TRUE : FALSE;
lf.lfStrikeOut = (cf.dwEffects & CFM_STRIKEOUT) ? TRUE : FALSE;
lf.lfItalic = (cf.dwEffects & CFM_ITALIC) ? TRUE : FALSE;
lf.lfWeight = (cf.dwEffects & CFM_BOLD) ? 700 : 400;
lf.lfCharSet = cf.bCharSet;

PARAFORMAT2 pf2;
memset(&pf2, 0, sizeof(pf2));
pf2.cbSize = sizeof(PARAFORMAT2);
pf2.dwMask = PFM_LINESPACING;
SendMessage(EM_GETPARAFORMAT, (WPARAM)(UINT)SCF_DEFAULT, (LPARAM)&pf2);

//m_lf = lf;
//m_lLineHgt = MulDiv(pf2.dyLineSpacing/20, logPixelsY, 72);
SetTextLogFont(lf);
SetLineHeight(MulDiv(pf2.dyLineSpacing/20, logPixelsY, 72));
m_lFontHeight = -lf.lfHeight;
}


我使用的,是vc的相关代码,
当然bcb的操作简单,大部分还是有参考价值的。
truelove7283159 2008-04-01
  • 打赏
  • 举报
回复
有2个东东 你可以参考 richedit
1 vc有很多很多的richedit控件的例子,
里面的消息循环 字体控制等等,都可以。
但毕竟不是咱BCB的。

2 下面说一个自家门的吧
好像有个tms的第三方控件的,里面就有可以参考的,当时我要做语法分析时候看到过,名字忘记了,
改天再帮你确认。
http://www.ccrun.com/view.asp?id=169
Waiting4you 2008-04-01
  • 打赏
  • 举报
回复
对了,你的软件看上去不错,能给偶用用吗?
提个改进意思,背景色是否可以用渐变色?用API: GradientFill
Waiting4you 2008-04-01
  • 打赏
  • 举报
回复
帮你试了一种方法,貌似可用,你拿去多测试啊

void AdjustEditRect(TCustomEdit *pEdit)
{
pEdit->Perform(WM_VSCROLL,SB_BOTTOM,0); // 移到末尾

TPoint pt;
pEdit->Perform(EM_GETSCROLLPOS,0,(LPARAM)&pt);// 得到当前偏移量
pEdit->Height += pt.y; // 加上垂直偏移量就应该就是总高度了

pEdit->Perform(WM_VSCROLL,SB_TOP,0); // 移到开头就能显示整个内容了
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
AdjustEditRect(RichEdit1);
}
chenxidu 2008-04-01
  • 打赏
  • 举报
回复
SendMessage(rie_client_edit->Handle,WM_VSCROLL, SB_BOTTOM,0);
上面错了一行
chenxidu 2008-04-01
  • 打赏
  • 举报
回复
我后来是这样做的
当字体大小变小时(字体变大没有这个问题)


你字体改变事件里:
向主窗体发送一个消息
PostMessage(this->Handle,WM_USER + 1000,0,0);

主窗体接管后处理:

case WM_USER + 1000 :
{
SendMessage(rie_client_edit->Handle,WM_VSCROLL, SB_ENDSCROLL,0);
break ;
}

还是没有缩短,不知道为什么
chenxidu 2008-04-01
  • 打赏
  • 举报
回复
我思考你的代码很久,想在你的基础上再改变一下,因为我发现:

例如:输入几行字体大小为20的内容后,这个时候你改变字体的大小,比如
设成12大小,这个时候richedit下面会空出很长的一段高度,我想
让richedit自动也缩短,就是保持richedit底部总在最后一行的
紧跟着的下面!



再次请教你了!!!
chenxidu 2008-04-01
  • 打赏
  • 举报
回复
谢谢你
chenxidu 2008-03-31
  • 打赏
  • 举报
回复
谁能帮我看看我的问题吗?

604

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder VCL组件使用和开发
社区管理员
  • VCL组件使用和开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧