CnPack Forum


 
Subject: 实现Delphi输入法,帮助懒人
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-10-2 11:46  Profile | Site | Blog | P.M. 
实现Delphi输入法,帮助懒人

前段时间看到有个叫Delphi输入法的程序,很有创意,但使用不方便。
所以我想实现类似的在IDE实现代码输入助手。 下面为前期无IDE的测试程序:
http://www.internetoa.com/uploadfiles/DelphiPut_Test.rar  (需要D7运行包)
效果: http://www.internetoa.com/uploadfiles/DelphiPut.png


问题:怎样捕捉EditWindow的OnKeyDown事件?


我尝试用下面方式:
找到EditWindow,然后挂接OnKeydown或WindowProc,但WM_KEYDOWN都不发生。挂接在EditControl上情况也一样。

但如果挂接事件WM_KEYUP是正常发生的,因为我在发送IDE前要修改按下的键,所以才要捕获KeyDown。


下面是挂接KeyUp代码,正常的:

   for i := 0 to Screen.CustomFormCount - 1 do
    if IsIdeEditorForm(Screen.CustomForms) then
    begin
      EditorForm := Screen.CustomForms;
      EditControl := EditorForm.FindComponent(EditControlName) as TWinControl;
      Assert(Assigned(EditControl));
      Assert(EditControl.ClassNameIs(EditControlClassName));

      EditorForm.KeyPreview:= True;

      OldKeyUpEvent:= EditorForm.OnKeyUp;
      EditorForm.OnKeyUp:= EditWindowKeyUp;

//           OldEditControlWndProc:= EditorForm.WindowProc;
//      EditorForm.WindowProc:= EditControlWndProc;

。。。

procedure TfrmMain.EditWindowKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
    MessageBeep(MB_ICONSTOP);
    if Assigned(OldKeyUpEvent) then
        OldKeyUpEvent(Sender, Key, Shift);
end;

完成后,我会将把源代码公开到此,我对IDE缺少经验,那位高手指点条明路?

[ 本贴由 internetzs 于 2004-10-2 11:52 最后编辑 ]




Yeah, this is johnson. Johnson is a programmer.
Top
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-10-4 17:21  Profile | Site | Blog | P.M. 
差不多完成了,下面是测试版

本人只是在WinXP + SP1 + Delphi7测试通过

效果:http://www.internetoa.com/uploadfiles/DelphPut.gif
下载:http://www.internetoa.com/uploadfiles/DelphiPut.rar




Yeah, this is johnson. Johnson is a programmer.
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-10-7 20:43  Profile | Site | Blog | P.M. 
效果看起来还不错:)

不知输入法里的词汇是否支持从即时编译中获得?在 GExperts 中提供了一个代码纠错功能,里面有个方法可以从 IDE 中取得当前项目即时语法分析后的有效符号表,可以参考一下。

CnPack 最近开发工作不少,如果你这个工具完善后愿意加到 CnWizards 中来,无限欢迎!!




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-10-21 16:10  Profile | Site | Blog | P.M. 
源代码: http://www.internetoa.com/uploadfiles/DelphiPut.rar
知道的问题:在Delphi编辑时,在某些特殊区别会报Code completion错误,
我暂时找不到解决的办法。只能重启IDE.
Top
leeon
新警察
Rank: 1



UID 259
Digest Posts 0
Credits 22
Posts 22
点点分 22
Reading Access 10
Registered 2003-12-9
Status Offline
Post at 2004-10-26 09:47  Profile | Blog | P.M. 
我想Hook会帮你解决这个问题。如果你的汇编能看懂一些,

可以从看雪这里下载ApiList:

http://www.pediy.com/tools/Compilers.htm

ApiList这个软件,运行之后不管在哪个编辑框都可以。
Top
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-10-26 11:37  Profile | Site | Blog | P.M. 
* 修正了list out of index bonus(1)的错误
* 修正了AV非法访问内存错误

http://www.internetoa.com/uploadfiles/DelphiPut.rar




Yeah, this is johnson. Johnson is a programmer.
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-10-26 22:58  Profile | Site | Blog | P.M. 
试用了一下,感觉不错,做得很细致!

分析其源码,建议以下地方可以再改进一下:
1、键盘事件挂接可以改用 SetWindowsHookEx 建一个键盘钩子,当前的挂接方式有时候不起作用。
2、Delphi自己的自动完成窗口弹出时,键盘焦点还在 EditWindow 上,而输入助手窗口弹出时自己获得了焦点。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
felixsun
普通灌水员
Rank: 2



UID 231
Digest Posts 0
Credits 51
Posts 44
点点分 51
Reading Access 10
Registered 2003-11-25
Status Offline
Post at 2004-11-5 10:29  Profile | Blog | P.M. 
如果支持D6就好了
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-11-6 09:07  Profile | Site | Blog | P.M. 
我已经把这个工具移植到 CnWizards 中了,改动部分如下:
1、移植到 CnWizards 专家框架中。
2、EditWindow 的 OnKeyUp 替换改成用 SetWindowsHookEx 注册一个全局的键盘钩子来实现(实现于公共的 CnWizNotifier 单元。
3、通过在 InvokeCodeCompletion 前用 TCnMethodHook 替换掉 MessageDlgPosHelp 函数,来避免失败时 IDE 弹出错误对话框的问题。
4、对程序结构的一些调整及代码整理。
5、把图片资源直接加到 ImageList 中。

单元列表:
cnpackSourceWizardIdeEnhancementsCnInputHelper.pas
cnpackSourceWizardUtilsCnWizSymbolList.pas

后续工作:
1、改进提示窗口显示,使焦点保持在代码编辑器中,象 Code Insignt 窗口一样。
2、使用 GExpoerts 提供的方法,移植到不支持 IOTACodeInsightManager 的 D5/D6 中。
3、增加设置窗口。
4、完善对列表按类型排序功能,增加类型过滤功能。

相关任务单:
http://www.cnvcl.org:8008/cnpack/tktview?tn=115,0

非常感谢 internetzs 的工作及移植授权!您的名字已经作为该专家的第一作者出现,现在使用的是 Johnson Zhong,如果觉得不合适,请与我联系。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-11-7 11:49  Profile | Site | Blog | P.M. 
移植到cnpack是个令人振奋的好消息。我现在每天都离不开这个东东了。

关于提示焦点问题:
我发现以前的旧版的delphi输入法(DelphiInput)的焦点是保持在delphi中的,我问过原作者是怎么实现的,他回答:

是用栏截Delphi中键盘的消息,而不是用SetWindowsHookEx
在Delphi7的Demo中用一个“Editor Keybinding”例子,可以参考一下!
目录是“Delphi7DemosToolsAPIEditor Keybinding”

我对Keybinding不太了解,移植的时候或许可参考。
毕竟用SetWindowsHookEx方法要外加dll不太好。




Yeah, this is johnson. Johnson is a programmer.
Top
iceman
新警察
Rank: 1



UID 558
Digest Posts 0
Credits 10
Posts 10
点点分 10
Reading Access 10
Registered 2004-11-10
Status Offline
Post at 2004-11-10 10:26  Profile | Blog | P.M. 
请问新版本的CnPack什么时候发布???带DelphiInput的
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-11-10 11:45  Profile | Site | Blog | P.M. 
呵呵,新版本还要一段时间才发完善发布,不过您现在可以先下载一个刚刚发布的内部测试版:
http://ftp.cnvcl.org/temp/CnWizards_0.7.0.alpha.exe

这个版本对 DelphiPut 进行了大量的改进和增强,已经可以支持 D567 了。
希望大家喜欢,有什么问题欢迎给我们反馈。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-11-10 11:54  Profile | Site | Blog | P.M. 
移植后的输入助手增强了如下功能:
1、全面支持 D567,功能一致。
2、可以显示在标识符中间匹配的项。
3、在 uses 中使用时自动列出所有可用的单元名。
4、根据不同的代码位置,自动过滤列表内容。
5、支持多种排序方式,调整了一些优先级算法。
6、大量的结构改进和性能优化,更多智能判断。
7、支持延时弹出,默认为250ms。

目前设置界面还没有完成,请关注新版本的发布。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-11-10 12:05  Profile | Site | Blog | P.M. 
正在开发中的功能及未解决的问题:
1、如果IDE的AutoComplete显示时,不弹出列表,当前会替换。
2、列表弹出时,光标保留在编辑区,象AutoComplete窗口一样。
3、增加设置界面。
4、支持代码模板功能,可以用缩写输入代码块,如用 be 输入 begin end 对。

大家有什么好的建议,欢迎与我们联系!




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-11-10 18:12  Profile | Site | Blog | P.M. 
呵,动作真快,下面一些建议提供参考:

1. 行号和Symbol的字体可以设置,还有颜色。默认的“宋体”不好看
2. 行号的代码的TCnEditorGutter.Width可根据行号宽度进行动态调整
3. 单击TCnEditorGutter可以设置或取消书签
4. SymbolList过滤还是只过滤以输入的单词打头好些,太多眼花

以下是我的前段时间写的的一些代码片段:


// 画行号
procedure TGutterPanel.DrawLineNumber;
var
    i: Integer;
    Number: string;
    R: TRect;
    EditView: IOTAEditView;
    TopRow: Integer;
    BottomRow: Integer;
    CurrentRow: Integer;
begin
    EditView := CnOtaGetTopMostEditView;
    if not Assigned(EditView) then Exit;

    TopRow:= EditView.TopRow;
    BottomRow:= EditView.BottomRow;
    CurrentRow:= EditView.CursorPos.Line;

    with FLineControl do
    begin
        Refresh;
        Canvas.Brush.Style:= bsClear;
        Canvas.Font:= Self.Font;
        
        // 根据字串的宽度动态调整Gutter的宽度
        Self.Width:= FLineControl.Canvas.TextWidth(IntToStr(BottomRow))+3;

        for i:= TopRow to BottomRow do
        begin
            if (i=CurrentRow) and Assigned(FEditCursor) then
            begin
                // 画一个当前行的图标代替
                Canvas.Draw((Width - FEditCursor.Width) div 2 ,
                    (i-TopRow)* FLineHeight, FEditCursor);
            end
            else
            begin
                Number:= IntToStr(i);
                R:= Rect(0, (i-TopRow)* FLineHeight, Width-3, (i-TopRow)* FLineHeight+FLineHeight);
                DrawText(Canvas.Handle, PChar(Number), Length(Number), R, DT_RIGHT);
            end;
        end;

        // 画一条垂直线
        Canvas.Pen.Color:= VLineColor;
        Canvas.MoveTo(Width-1, 0);
        Canvas.LineTo(Width-1, Height);
    end;
end;

// 单击Gutter Panel设置或取消书签
procedure TGutterPanel.LineControltMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
    Row: Integer;
    EditView: IOTAEditView;
    ID: Integer;
    EditPos, SavePos: TOTAEditPos;

    function GetBlankBookmarkID: Integer;
    var
      i: Integer;
    begin
        Result:= 0;
        for i:=0 to 9 do
        if EditView.BookmarkPos[i ].Line = 0  then
        begin
            Result:= i;
            Exit;
        end;
    end;
    function FindBookmark(Row: Integer): Integer;
    var
      i: Integer;
    begin
        Result:= -1;
        for i:=0 to 9 do
        if EditView.BookmarkPos[i ].Line=Row then
        begin
            Result:= i;
            Exit;
        end;
    end;
begin
   
    if Button = mbLeft then
    begin
        EditView := CnOtaGetTopMostEditView;
        if Assigned(EditView) then
        begin
            Row:= EditView.TopRow + Y div FLineHeight;
            SavePos:= EditView.CursorPos;
            EditPos:= EditView.CursorPos;
            EditPos.Line:= Row;
            EditView.CursorPos:= EditPos;
            ID:= FindBookmark(Row);
            if ID=-1 then ID:= GetBlankBookmarkID;
            EditView.BookmarkToggle(ID);
            EditView.CursorPos:= SavePos;
            EditView.Paint;
        end;
    end;
end;




Yeah, this is johnson. Johnson is a programmer.
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-11-10 18:29  Profile | Site | Blog | P.M. 
呵呵,internetzs 做的东西不少嘛!

行号是 Passion 移植 Dragon PC 的专家,我让他过来这里看看。

符号过滤支持中间匹配是考虑到有时候我们只记得一些标识符中间的部分,或者不知道用什么函数合适,用一些关键词来尝试的功能,比如输入 Process 可以显示所有与进程相关的函数。默认的排序方法会将匹配开头的放到最前面,而且只有回车可以选择,应该没什么影响。
这个功能可以关掉,只是设置界面还没有做,注册表项:
HKEY_CURRENT_USERSoftwareCnPackCnWizardsCnInputHelper




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
internetzs
新警察
Rank: 1



UID 529
Digest Posts 0
Credits 31
Posts 31
点点分 31
Reading Access 10
Registered 2004-9-29
Status Offline
Post at 2004-11-10 18:52  Profile | Site | Blog | P.M. 
你的那个问题:
1、如果IDE的AutoComplete显示时,不弹出列表,当前会替换。

可以用下面方法解决(未验证):

Delphi的Code completion窗口的信息,

WindowText: KibitzWindow
WindowClass: TCodeCompleteListView

如果你用FindWindow函数能找到此窗口,则证明Code completion窗口已经存在。
否则此时SymbolList的窗口才可以弹出。

还有个问题就是中文输入法存在时不要弹出




Yeah, this is johnson. Johnson is a programmer.
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2004-11-10 19:10  Profile | Site | Blog | P.M. 
多谢提供,省去不少功能,否则我得自己去找了。

输入法问题是因为我平时都开着输入法,只是用shift把它禁用,如果开输入法就关自动完成的话,来回切换输入法太麻烦,所以把这个功能禁用了。我加个选项由用户决定吧。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6756
Posts 3554
点点分 6756
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2004-11-10 19:56  Profile | Blog | P.M. 
行号显示功能还没完善……

……就被匆忙地拿出来见世面,不好意思,我赶紧接着完善它。
Top
iceman
新警察
Rank: 1



UID 558
Digest Posts 0
Credits 10
Posts 10
点点分 10
Reading Access 10
Registered 2004-11-10
Status Offline
Post at 2004-11-13 13:49  Profile | Blog | P.M. 
输入法总体感觉比vs.net2005好,但如下图(我在输入点的时候){图1}

[ Last edited by iceman on 2004-11-13 at 15:25 ]


Image Attachment: 输入点的时候.JPG (2004-11-13 13:49, 110.39 K)

Top
 




All times are GMT++8, the time now is 2024-4-19 17:19

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.011056 second(s), 8 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP