发信人: lofe ()感激生活(), 信区: BorlandDev
标  题: 用C++ Builder3 制作NotePad(记事本)续篇
发信站: 哈工大紫丁香 (Sun Sep  3 07:51:36 2000), 转信

上回说到“我的记事本”小功告成,copy给朋友一份,咦,不能用,说是缺文件?噢,
像VB的VBRUN???
.dll一样,C++ Builder3编译的程序也需要运行库的支持的。找到并打开它看看我们还
有些什么没有做?首先是关于菜单的快捷键问题。如果你是使用我上次所给的资源脚本
导人的菜单,你会发现带有快捷键的菜单项的文字都像“撒消(U)\tCtrl+Z”一样。以前
用BC的资源编辑器做过菜单的朋友都知道,“\t”表示右对齐,而在C++ Builder3中也
作为菜单的文字了。另外C++ Builder3中的快捷键的建立也简单的多,快捷键已经作为
菜单的ShortCut属性了。这里,仅改动“编辑(E)”中的“撒消(U)Ctrl+Z”项来示众,
其余皆可依样而画葫芦之。
   先双击MainMenu1菜单组件,进入菜单编辑器,选中“编辑(E)”中的“撤消(U)Ctrl
+Z”项。接着将Caption属性改为“撤消(U)”(即把“\tCtrl+Z”删去),并在shortC
ut瞩性中选择Ctrl+Z。这样,该项的快捷键就设完了。接着是编辑菜单里的各个项。首
先是“撤消(&U)Ctrl+Z”到“全部选定(&A)”六项(必须先将他们的Enabled属性都设为
true),C++ Builder3为这些功能提供了现成的方法(Method)。比如“撤消(&U)Ctral
+Z”菜单,可以使用Undo方法,即在该菜单的OnClick事件处理函数中输入“Memo1->Un
do();”。同理有:
    “剪切(&T)\tCtrl+X”项,输入:“Memo1->CutToClipboard();”
    “复制(&C)\tCtrl+C”项,输入:“Memo1->CopyToClipboard();”
    “粘贴(&P)\tCtrl+V”项,输入:“Memo1->PasteFromClipboard();”
    “删除(&L)\tDel”项,输入:“Memo1->ClearSelection();”
    “全部选定(&A)”项,输入:“Memo1->SelectAll();”
   下面是“时间/日期(&D)F5”项,我们必须先取得当前的日期和时间。有两种方法,
一种是用getdate和
gettime函数,一种是用C++ Builder3中的TDateTime类。这里选择后一种,但有时使用
getdate和gettime函数会更简便。下面给出该菜单项的处理代码:
TDateTime * Current_DateTime =newTDateTime; //生成TDateTime对象
* Current_DateTime=Current_DateTime->CurrentDateTime(); //获取当前日期和时间

Memo1->SetselTextBuf(Current_DateTime->DateTimeString().c_str());//将当前日期
和时间转换成字符串,并用SetSelTextBuf方法插入当前光标位置
   接着是处理‘自动换行(&W)”的代码:
//W1是“自动换行(&W)”菜单项的名字(Name)属性,如果你不是W1,请做相应的改动
if(W1->Checked) //该菜单已经检取(Checked)
{W1->Checked=false; //取消检取
Memo1->ScrollBars=ssBoth; //Memo1两根滚动条都要
} else
{ W1->Checked=true; //设置检取
Memo1->ScrollBars = ssVertical; //Memo1只设垂直滚动条,效果就是自动换行
}
   接下来处理“设置字体(&F)...”菜单,我们首先需要一个设置字体的公用对话框。
从Dialogs组件条中选FontDialog组件放入表单中。下面是处理“设置字体(&F)...”的
代码:
if(FontDialog1->Execute())Memo1->Font=FontDialog1->Font;
   至此,“编辑(E)”菜单的功能都处理完了,下面将是处理“搜索(S)”菜单的工作。
其中,我们又将用到两个公用对话框。C++ Builder3只提供了用来获取用户欲查我的字
符串的对话框,并未提供具体查找的函数,所以我们得自己写处理函数。下面我给出修
改的Win32 SDK的范例代码,你需要将这些代码插在程序的首部,即定义全局变量的地方

typedef enum {
    frtFind
    frtReplace,
    frtRepAll
} FRT
#define GETSEL(ichS,ichE) \ SendMessage(MainForm - > Memo1 - > Handle,
EM_GETSEL,(WPARAM) & ichs, (LPARAM) & ichE)
#define SETSEL(ichS,ichE) \SendMessage(MainForm - > Memo1 - > Handle,
EM_SETSEL, (WPARAM) ichS, (LPARAAM) ichE)
BOOL FWholeWord(char * sz, char * szStart, char * szEnd,
int cch) {
    if ( sz! = szStart & &
        * (sz - 1 ) ! = ' ' & &
        * (sz - 1 ) ! = '\t' & &
        * (sz - 1 ) ! = ',' & &
        * (sz - 1 ) ! = '.' & &
        * (sz - 1 ) ! = '\r'
    ) { return FALSE;
    }
    if ( sz + cch! = szEnd & &
        * (sz + cch) ! = ' ' & &
        * (sz +cch) ! = '\t' & &
        * (sz + cch) ! = ',' & &
        * (sz + cch) ! = '.' & &
        * (sz + cch) ! = '\r'
    ) { return FALSE;
    }
    return TRUE;
}
BOOL Find(char * szFind, BOOL fDown, BOOL fMatchCase, BOOL fWholeWord, BOOL 
fNoScroll)
{ char * szText;
    UINT ichStart;
    UINT ichEnd;
    UINT cch;
    int dch;
    int dchComp;
    char * szTerm;
    char * sz;
    UINT cchFind;
    BOOL fFound = FALSE;
    int dcbOnFind;
    szText = MainForm - > Memo1 - > Lines - > GetText();
    cchFind = strlen (szFind);
    GETSEL(ichStart, ichEnd);
    cch = strlen(szText);
    if (
        ichEnd - ichStart = = cchFind & &
        !strnicmp(szText + ichStart, szFind, cchFind)
        )
        dchOnFind = 1;
    else
        dchOnFind = 0;
    if (fDown)
        { dch = 1;
        dchComp = 0;
        sz = szText + ichStart + dchOnFind;
        szTerm = szText + cch;
        }
    else
        { dch = -1;
        dchComp = 1;
        sz = szText + ichStart - dchOnFind;
        szTerm = szText;
    }
    for (; sz + dchComp! = szTerm; sz + = dch)
    {
      if (
        tolower(* sz) = = tolower( * szFind) & &
        (fMatchCase ?
            !strncmp(sz, szFind, cchFind) :
            !strnicmp (sz, szFind, cchFind)
        ) & &
        ( !fWholeWord || FWholeWord(sz, szText, szTerm,cchFind)))
        { SendMessage(MainForm -> Memo1 -> Handle,EM_SETSEL, sz-szText, sz-s
zText + cchFind);
        if (!fNoScroll)
            SendMessage(MainForm - > Memo1 - > Handle,EM_SCROLLCARET, 0, 0L)
;
        fFound = TRUE;
        break;
      }
    }
    if ( !fNoScroll & & !fFound)
        MessageBox(NULL, szFind, "字 符 串 没 有 找 到",MB_OK);
    return fFound;
    }
    VOID Replace(char * szReplace) {SendMessage(MainForm - > Memo1 - > Handl
e,
    EM_REPLACESEL, 0, (LPARAM) (LPSTR) szReplace);
    }
    VOID ReplaceAll(char * szFind, char * szReplace, BOOLfMatchCase, BOOL fW
holeWord)
    { UINT ichStart;
      UINT ichEnd;
      GETSEL(ichStart, ichEnd);
      SETSEL(0, 0);
      while(Find(szFind, TRUE, fMatchCase, fWholeWord,TRUE)) {
      Replace (szReplace);
      }
      SETSEL(ichStart, ichEnd);
    }
    VOID FindReplace(
        char * szFind, char * szReplace,
        FRT frt,
        BOOL fDown, BOOL fMatchCase, BOOL fWholeWord)
    { switch (frt)
      { case frtFind:
        Find(szFind, fDown, fMatchCase, fWholeWord,FALSE);
        break;
      case frtReplace:
        Find(szFind, fDown, fMatchCase, fWholeWord,FALSE);
        Replace (szReplace);
        break;
      case frtRepAll:
        ReplaceAll(szFind, szReplace, fMatchCase, fWholeWord);
    }
}
   这些代码本来并不是给C++ Builder用的,但我们只要稍加改动就能使用了,这也为
我们移植以前的代码提供了新思路,即一般只要将过去程序中的窗口或控制的句柄(HW
ND)用C++Builder中表单或组件的Handle属性来代替,将过去程序中的程序事例句柄用
HInstance代替,就能方便的完成移植。回到程序中来,上面有5个函数和2个宏,其实我
们直接使用的只有FindReplace函数。先在表单上放上FindDialog和ReplaceDialog两个
对话框,随后写“查找(F)...”菜单项的处理代码:
FindDialog1->Execute();
   你可能会很奇怪,这么简单,那查找的过程在哪里呢?当用户按了查找对话框的[查
找下一个(F)]按钮后,会产生FindDialog的OnFind事件,在该事件的处理函数中进行查
找工作。如何编写组件的事件函数?
(1)在表单编辑区选中该组件(这里是FindDialog1);
(2)在对象观察器(如果没有显示,按F11调出)中选择Event(事件),系统将列出事
件;
(3)双击事件后面的编辑框(这里是OnFind),系统将切换入代码编辑区;
(4)输入事件处理代码。
下面给出OnFind的处理代码:
MainForm - > SerFocus();
FindReplace(FindDialog1 - > FindText.c_str(), "", frtFind,
    FindDialog1 - > Options. Contains(frDown),
    FindDiaiog1 - > Options.Contains(frMatchCase),
    FindDialog1 - > Options.Contains(frWholeWord));
同样的,“替换(&R)”菜单项处理代码是:
ReplaceDialog1 - > Execute();
ReplaceDialog1的onFind 事件的处理代码:
MainForm - > SetFocus();
if(ReplaceDialog1 - > Options.Contains(frFindNext))
FindReplace(ReplaceDialog1 - > FindText.c_str(),"", frtFind,
    ReplaceDialog1 - > Options. Contains(frDown),
    ReplaceDialog1 - > Options. Contains(frMatchCase),
    ReplaceDialog1 - > Options. Contains(frWholeWord));
ReplaceDialog1的onReplace 事件(用户按了[替换(R)]按钮)的处理代码:
MainForm - > SetFocus ();
if(ReplaceDialog1 - > Options. Contains (frReplace))
FindReplace(ReplaceDialog1 - > FindText. c_str(),
    ReplaceDiaiog1 - > ReplaceText. c_str(), frtReplace,
    ReplaceDialog1 - > Options. Contains(frDown),
    ReplaceDialog1 - > Options. Contains(frMatchCase),
    ReplaceDialog1 - > Options. Contains(frWholeWord));
else if(ReplaceDialog1 - > Options. Contains (frReplaceAll))//全部替换
FindReplace(ReplaceDialog1 - > FindText.c_str(),
    ReplaceDialog1 - > ReplaceText, c_str(), frtRepAll,
    ReplaceDialog1 - > Options. Contains(frDown),
    ReplaceDialog1 - > Options. Contains(frMatchCase),
    ReplaceDialog1 - > Options. Contains(frWholeWord));
当然,还有“查找下一个(N)”菜单项,处理的方法几乎和OnFind一样:
FindReplace(FindDialog1 - > FindText. c_str(),"", frtFind,
    FindDialog1 - > Options. Contains (frDown),
    FindDialog1 - > Options. Contains (frMatchCase),
    FindDialog1 - > Options. Contains(frWholeWord));
    至此为止,终于真的“大”功告成了。至于“帮助(H)”菜单处理,你可以用WinHe
lp来显示一个帮助文
件,用MessageBox来显示“关于XXX”的对话框,这些都不怎么和C++ Builder有关,我
就不赘述了。
    最后还有些收尾工作,选择Project菜单Options,将显示一个程序设置的对话框。

    1.选择Application页面,这里Title是程序在任务栏上的标题,默认的是程序文件
名。我们将它设为
“我的记事本V1.00”。接着,单击[Load Icon...]按钮来为你的软件选择一个图标。
    2.选择Compiler页面,单击[Release]按钮,这样就不会向程序中插入调试代码而
加快执行速度。
    3.选择Linker页面,取消对Use Dynamic RTL的选择,不使用动态链接库。
    4.选择Packages页面,取消对Build with runtime packages的选择,不使用运行
时包。
    按OK退出后,选Project菜单中的Build NotePad来编译一下,你的第一个用C++ Bu
ilder3制作的称得上“软件”的程序终于诞生了。

--
※ 修改:.haojs 于 Sep  3 07:49:12 修改本文.[FROM: bbs.hit.edu.cn]
--
※ 转寄:.武汉白云黄鹤站 bbs.whnet.edu.cn.[FROM: bbs.hit.edu.cn]

--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: haojs.bbs@bbs.whnet.]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.546毫秒