• 主页
  • Windows SDK/API
  • 基础类
  • ActiveX
  • 数据库及相关技术
  • 网络及通讯开发
  • VCL组件使用和开发

好久没发问,问个关于双字节的问题

rainfall19831109 2007-07-18 05:59:38
软件中使用了TMS的AdvMemo控件,目前我只能用这个控件了,不能用别的Memo控件代替了
问题是AdvMemo可以正确显示中文字,但当我按下退格键准备删除中文字的时候,只能删除该中文字的一半,另外一半还存在,造成乱码
而VCL带的Memo能根据当前的字符决定究竟是退2格还是1格
有没有什么方法入手修改这问题?
控件有源码的。。。
...全文
633 点赞 收藏 16
写回复
16 条回复
rainfall19831109 2007年07月25日
不好意思。。。这阵比较忙忘记结帖了。。。
再次写cczlp(不惑)
回复 点赞
cczlp 2007年07月20日
有时间改BUG还不如自己写了, AdvMemo居然从TWinControl继承, 画图是方便了, 但Memo标准的Windows消息 EM_XXXX 都不响应了.
回复 点赞
jacknes009 2007年07月20日
void __fastcall TForm1::AdvMemo1KeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{

}
中判断AdvMemo1有没有选中,判断位置,
按字节判断,字节大于0x80的应该是双字节,也就是
for(int i = 1; i <= AdvMemo1->Text.Length(); i++)
{
Byte ch = Memo1->Text.operator [](i);
if(ch > 0x80)
{
i++;
}
}
回复 点赞
TurboCIU 2007年07月19日
学习了,谢谢。
回复 点赞
cczlp 2007年07月19日
void __fastcall TForm1::AdvMemo1SelectionChange(TObject *Sender)
{
BOOL bLeadByte;
BOOL bTrailByte;
BOOL bLeadEnd;
BOOL bTrailEnd;

CheckText(AdvMemo1, AdvMemo1->SelStart, &bLeadByte, &bTrailByte);
CheckText(AdvMemo1, AdvMemo1->SelStart + AdvMemo1->SelLength, &bLeadEnd, &bTrailEnd);

if (bTrailByte)
{
AdvMemo1->SelStart--;
AdvMemo1->SelLength++;
}
else if (bTrailEnd)
{
AdvMemo1->SelLength++;
}
}
只能从左到右选择, 从右到左不行, 应该是AdvMemo的BUG .
回复 点赞
mimong_lin 2007年07月19日
mark学习。
回复 点赞
MEFULEU 2007年07月19日
板凳~
回复 点赞
hagic 2007年07月19日
学习
回复 点赞
rainfall19831109 2007年07月19日
这个Memo的Bug的确不少
昨晚我几乎通宵在修改这个Memo的源码
现在几乎改好了。。。各个按键都正常了。。。
但另外又有问题出现了,就是这个Memo它本身有提供Undo跟Redo的功能,可是效果很差(或者说根本就是Undo和Redo的结果不对!)
我现在还在修改当中。。。

不过无论如果,虽然没使用不惑的代码,还是感谢你的热心解答!
回复 点赞
cczlp 2007年07月18日
void CheckText(TAdvMemo *memo, int Index, BOOL *bLead, BOOL *bTrail)
{
int MultiStart = 0;
*bLead = false;
*bTrail = false;

for (int i = Index; i > 0; i--)
{
if ((BYTE)memo->Lines->Text[i] < 0xa0)
{
MultiStart = i;
break;
}
}

if ((BYTE)memo->Lines->Text[Index + 1] >= 0xa0)
{
*bLead = (Index - MultiStart) % 2 == 0;
*bTrail = !*bLead;
}
}


void __fastcall TForm1::AdvMemo1KeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
BOOL bLeadByte = false;//IsDBCSLeadByte(AdvMemo1->Lines->Text[AdvMemo1->SelStart + 1]);
BOOL bTrailByte = false;//AdvMemo1->Lines->Text.IsTrailByte(AdvMemo1->SelStart);
BOOL bHalf = FALSE;

CheckText(AdvMemo1, AdvMemo1->SelStart, &bLeadByte, &bTrailByte);

if ((Key == VK_DELETE && bLeadByte) || (Key == VK_BACK && bTrailByte))
{
bHalf = TRUE;
}
else if (Key == VK_LEFT)
{
if (!bTrailByte && AdvMemo1->SelStart > 1)
{
if ((BYTE)AdvMemo1->Lines->Text[AdvMemo1->SelStart] >= 0xa0)
{
bHalf = TRUE;
}
}
}
else if (Key == VK_RIGHT)
{
if (bLeadByte)
{
bHalf = TRUE;
}
}

if (bHalf)
{
AdvMemo1->OnKeyDown = NULL;
SendMessage(AdvMemo1->Handle, WM_KEYDOWN, Key, 0);
AdvMemo1->OnKeyDown = AdvMemo1KeyDown;
}
}
回复 点赞
rainfall19831109 2007年07月18日
感谢 cczlp(不惑)的代码。。
是挺有效。。。

不过我想从根本上改变这个问题,不知还有办法没。。。
现在情况是,如果我不是删除,只是选择里面文本的话
假如里面文本是“我a”,那么当我选择a和我的后半个字节的话,被选择的部分advMemo会显示一个另外的乱码字,就是把我的后半字节与a合并了
回复 点赞
cczlp 2007年07月18日
void __fastcall TForm1::AdvMemo1KeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
BOOL bLeadByte = IsDBCSLeadByte(AdvMemo1->Lines->Text[AdvMemo1->SelStart + 1]);
BOOL bTrailByte = AdvMemo1->Lines->Text.IsTrailByte(AdvMemo1->SelStart);
if ((Key == VK_DELETE && bLeadByte) || (Key == VK_BACK && bTrailByte))
{
AdvMemo1->OnKeyDown = NULL;
SendMessage(AdvMemo1->Handle, WM_KEYDOWN, Key, 0);
AdvMemo1->OnKeyDown = AdvMemo1KeyDown;
}
}
回复 点赞
rainfall19831109 2007年07月18日
KeyDown里根本就处理不了
本来控件已经存在对按键的处理
我再处理Lines属性的话会乱掉。。。因为情况是有时候是英文,有时候是中文
回复 点赞
LuoGD 2007年07月18日
那在它的ONKEYDOWN里处理,每按一下把它存储的内容删除一个(既然是TStrings),不过这样不一定很好,
回复 点赞
rainfall19831109 2007年07月18日
根本就不是这个问题
我看过控件的代码
里面用来储存文本的是一个自定义类,该类是从TStrings继承
回复 点赞
LuoGD 2007年07月18日
说明你的AdvMemo操作的是char*,而VCL的是AnsiString
回复 点赞
发动态
发帖子
C++ Builder
创建于2007-08-02

2563

社区成员

10.2w+

社区内容

C++ Builder相关内容讨论区
社区公告
暂无公告