转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
讲述如何开发一个控件,很有价值(六)         ★★★★

讲述如何开发一个控件,很有价值(六)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:2565 更新时间:2009/4/23 18:44:03
ow,BeginSelStart,EndSelStart: Integer;
MyRe : TRichEdit;
MyPBuff: array[0..255] of char;
MyTokenStr:string;
MyTokenState:TTokenState;
MyRun:PChar;
MySelStart: Integer;

begin

MyRe := TRichEdit(Sender);

WasSelStart    := MyRE.SelStart;
WasRow         := MyRE.Perform(EM_LINEFROMCHAR, MyRE.SelStart, 0);
Row            := WasRow;
BeginSelStart  := MyRe.Perform(EM_LINEINDEX, Row, 0);
EndSelStart    := BeginSelStart + Length(MyRE.Lines.Strings[Row]);

StrPCopy(MyPBuff,MyRE.Lines.Strings[Row]);
MyPBuff[Length(MyRE.Lines.Strings[Row])] := #0; 

MySelStart   := BeginSelStart;
MyRun        := MyPBuff;

while(MyRun^ <> #0) do
begin

MyRun          := PasCon.GetToken(MyRun,MyTokenState,MyTokenStr);
MyRe.SelStart   := MySelStart;
MyRe.SelLength  := Length(MyTokenStr);

MyRe.SelAttributes.Assign(PasCon.FParseFont[MyTokenState]);

MySelStart := MySelStart + Length(MyTokenStr);

end;

MyRE.SelStart    := WasSelStart;
MyRE.SelLength   := 0;

end;

Now: put the Debugging code on, do [Build All] and then [Run], and set a breakpoint on the first line of this Event. Open up the testinput.pas. When the debugger stops in the OnChange event, Press <F9> to continue on, and press <F9> again, and again - Do you see? We keep going back into the Event again and again (and again). What’s happening?

Somehow in our event we are triggering off another [OnChange] event. This call to the [OnChange] event code is stored in the message queue. When the event were currently in is finished, a new one is just waiting on the Event queue, which executes and creates more events... a re-entrant loop.

This behaviour is not surprising - after all we are actually changing the control in the process of our code, so no wonder another [OnChange] event is being triggered.

The way to fix such things is to ensure our actions do not trigger of the Event. We can do this by "temporarily" storing the RichEdits.OnChange property (which contains a reference to call our procedure TForm1.RichEdit1Change) in our own internal variable, and then setting the OnChange property to nil.

We then do all the processing we want to do - if it happens to trigger an [OnChange] event - there is nothing to call as OnChange is nil, and so the Event doesn''''t go onto the Message queue. When we''''re finished however we must return the OnChange property to it original value, otherwise the reprocessing want happen next time around.

If we look at the Delphi Helpfile we see that the OnChange property is of a certain type, the same type we have to make our SaveOnChangeIn variable:

var

SaveOnChangeIn: TNotifyEvent;

~~~~~rest of code

begin

MyRe                     := TRichEdit(Sender);
SaveOnChangeIn  := MyRe.OnChange;
MyRe.OnChange  := nil;

~~~~~rest of code

MyRe.OnChange := SaveOnChangeIn;

end;

Try it out!!!

  • Compile and Run
  • Open up Unit1.pas in the "editor" we have written
  • Click in the RichEdit in the center of the first lines, in the middle of "unit".
  • Press the [space bar]
  • Press the [backspace key]
  • Arrow to the end of the line
  • Press [Enter]
  • Press [BackSpace]
  • [BackSpace] away the entire line
  • Re-type the entire line

Result:  "functionally" the Control should look that same as it did before we clicked in it. The line "unit Unit1;" should highlighted properly as per your Delphi 3.0 Editor (save the background colour). However its slow and flickers a great deal. Try opening up a new line and just type a long phrase - e.g "if (RichEdit = Santa) then GetPresents(''''box of choclate''''); " and you''''ll agree with me that:

  1. GOOD - It is highlighting properly
  2. BAD - There is flickering
  3. BAD - The longer the line gets, the longer it takes to do the re-highlighting
  4. BAD - you get the "someone is chasing me effect"

The flickering is due to a number of components. We''''ll have to deal with each seperately.

The most obvious is the "selecting" of each Token. Visually the control is just repeating what we were able to do manually - when a piece of text is selected it becomes highlighted by the black stripe. We need to stop this from happening. Back to the helpfile(s) again. Have a search around, and come back after a snack break with some ideas... I''''m hungry :-)
 
 

Death to the black stripe
 
 

Marks: 5/10

Most of you would have found the HideSelection property of the RichEdit control. When it is set to TRUE and the RichEdit looses the focus (the user clicks onto another control) the selection bar (the black stripe) is hidden. In fact if you try it out by selecting some text in the RichEdit1 then clicking in the Edit1 control at the top of the "editor" you''''ll see the selection disappears! [Tab] back into the RichEdit control and it reappears. Lets do this programmatically:

begin

Edit1.SetFocus;

~~~~~

MyRe.SetFocus;

end;

Take my word for it, but if you look closely, the black strip is gone. Pity we got stuck with a new one in the Edit1 control :-(

If your programmed in Delphi you may know a little trick:

    Delphi Rule #4:  you can''''t SetFocus on a disabled Control.

The converse however is also true:

    Delphi Rule #4b: a disabled Control is not "Focused"

So try instead we can just Disable (then Enable) the RichEdit control like this:

begin

MyRe := TRichEdit(Sender);
MyRe.Enabled := False;

~~~~~~

MyRe.Enabled := True;

end;

Oops. I should have known. After all I said it: a disabled Control is not "Focused" - barely ten lines ago! When the RichEdit is enabled again, we also have to SetFocus back to it. Shees.. :-)

begin

MyRe := TRichEdit(Sender);

MyRe.Enabled := False;

~~~~~~

MyRe.Enabled := True;

MyRe.SetFocus;

end;

Try it again. This time things are working better, and we''''re leaving poor old Edit1 Control alone. Thats good practice, as it may have had an [OnFocus] event that does wierder things than what we''''re trying to do. Maybe not now, but it could in the future!
 

Marks: 10/10
 

On the other kind, some of you may have found instead the EM_HIDESELECTION message in the Win32.HLP. If you had delved in, you would have found something very interesting. The Delphi HideSelection property only implements half the capabilities of this message. You can also, by calling it direct, tell it to Temporarily hide the black stripe even when the control has the focus. So instead you could use the following lines of code:

begin

MyRe := TRichEdit(Sender);

MyRe.Perform(EM_HIDESELECTION,1,0);

~~~~~~

MyRe.Perform(EM_HIDESELECTION,0,0);

end

Yummy. Nice clean coding:
 
 

Death to the FLICKER
 
 

The next major problem is this bloody flicker. You should pop back into Delphi for a second, and ty

上一页  [1] [2] [3]  下一页


[Delphi程序]讲述如何开发一个控件,很有价值(七)  [Delphi程序]讲述如何开发一个控件,很有价值(五)
[Delphi程序]讲述如何开发一个控件,很有价值(四)  [Delphi程序]讲述如何开发一个控件,很有价值(三)
[Delphi程序]讲述如何开发一个控件,很有价值(二)  [Delphi程序]讲述如何开发一个控件,很有价值
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台