scintilla 中的代码折叠功能的使用收藏

来源:互联网 发布:阿里云服务器cname 编辑:程序博客网 时间:2024/06/06 00:32
 scintilla 中的代码折叠功能的使用收藏

 | 旧一篇:  如何在 Windows 环境下使用 Scintilla 编辑控件?

本文翻译自http://sphere.sourceforge.net/flik/docs/scintilla-folding.html

使用 scintilla 中的代码折叠功能
scintilla 是一个脚本编辑组件,您可以到 
http://www.scintilla.org 这个网站上看看。

--------------------------------------------------------------------------------
下面介绍如何使用 scintilla 的代码折叠功能

--------------------------------------------------------------------------------

首先咋们来创建一些我们稍后会用到的一些常量。
static const int MARGIN_SCRIPT_FOLD_INDEX = 1;

为窗口注册 margin Event (即用户执行折叠和展开代码时,触发的事件)事件(仅用于 windows 环境)

static const int WINDOW_ID = 900;

BEGIN_MESSAGE_MAP(CDocumentWindowCDocumentWindowsBaseClass)
  ON_NOTIFY(SCN_MARGINCLICK, WINDOW_ID, OnMarginClicked)
END_MESSAGE_MAP()


(这里的 WINDOW_ID 就是我们调用 CreateWindow 创建窗口时经常用到的)

设置我们需要的 lexer(词法识别器,用于识别代码格式)...
(可以直接使用已有的常量,也可以自己手动创建...)

  SendEditor(SCI_SETLEXERSCLEX_CPP);
  SendEditor(SCI_SETSTYLEBITS, 5);


设置我们用到的 lexer 的一些属性

  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold", (LPARAM)"1");
  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold.compact", (LPARAM)"0");


(这里的 fold.compact 选项就是折叠必要的代码行;我不太喜欢这个特性,但是这个属性缺省值就是"1")
下面这样也不错:

  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold.comment", (LPARAM)"1");
  SendEditor(SCI_SETPROPERTY, (WPARAM)"fold.preprocessor", (LPARAM)"1");


现在让我们将所有的 margins 重置
(可以通过 RecalcLineMargin 函数处理...)


  SendEditor(SCI_SETMARGINWIDTHNMARGIN_SCRIPT_FOLD_INDEX, 0);

接着,设置 margin 类型和 margin 掩码(mask),并重置...

  SendEditor(SCI_SETMARGINTYPEN,  MARGIN_SCRIPT_FOLD_INDEXSC_MARGIN_SYMBOL);
  SendEditor(SCI_SETMARGINMASKNMARGIN_SCRIPT_FOLD_INDEXSC_MASK_FOLDERS);
  SendEditor(SCI_SETMARGINWIDTHNMARGIN_SCRIPT_FOLD_INDEX, 20);


设置一些其他的选项

  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDERSC_MARK_PLUS);
  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDEROPENSC_MARK_MINUS);
  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDERENDSC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDERMIDTAILSC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDEROPENMIDSC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDERSUBSC_MARK_EMPTY);
  SendEditor(SCI_MARKERDEFINESC_MARKNUM_FOLDERTAILSC_MARK_EMPTY);

  SendEditor(SCI_SETFOLDFLAGS, 16, 0); // 16   如果没有展开就在折叠行的下面划一条横线


我们注册一下通知事件,这样当用户点击 margin 时,scintilla 就会通知我们。

  SendEditor(SCI_SETMARGINSENSITIVENMARGIN_SCRIPT_FOLD_INDEX, 1);


响应 SCN_MARGINCLICK 事件...(请注意函数原型)

afx_msg void
CDocumentWindow::OnMarginClick(NMHDRnmhdrLRESULTresult)
{
  SCNotificationnotify = (SCNotification*)nmhdr;

  const int modifiers = notify->modifiers;
  const int position = notify->position;
  const int margin = notify->margin;
  const int line_number = SendEditor(SCI_LINEFROMPOSITIONposition, 0);

  switch (margin)
  {
    case MARGIN_SCRIPT_FOLD_INDEX:
    {
      SendEditor(SCI_TOGGLEFOLDline_number, 0);
    }break;
  }
}


有了上面这些应该能够工作了。
You'll want to play around with it until you're happy with the way the folding works,
scintilla seems to use a much more complicated MarginClick...
Luckily harvesting the MarginClick code from scintilla is easy:

首先修改一下 OnMarginClick:

      SendEditor(SCI_TOGGLEFOLDline_number, 0);

修改为: 
      MarginClick(positionmodifiers);


接着在你的头文件中...
Then in your header file...

  bool MarginClick(int positionint modifiers);
  void Expand(int &linebool doExpand,
              bool force = falseint visLevels = 0, int level = -1);
  void FoldAll();

接着到 SciTEBase.cxx 中找一些你需要的代码,直接粘贴到你自己的文件中(译者注:没想到作者要我这样写代码:))

对了,你最好赶快更新一下你的 Goto Line 函数...(译者:跳转到某一行功能,可能是这里比较容易出错)

 SendEditor(SCI_ENSUREVISIBLEENFORCEPOLICYline_number);
 SendEditor(SCI_GOTOLINEline_number);


就这些了,enjoy.

如果对此有什么问题或者建议你可以发邮件到 vascy@hotmail.com

 libbyliugang translate to chinese.

 

发表于 @ 2007年12月17日 17:59:00|评论(0)|编辑

 | 旧一篇:  如何在 Windows 环境下使用 Scintilla 编辑控件?


http://blog.csdn.net/libbyliugang/archive/2007/12/17/1944046.aspx

原创粉丝点击