本人目前的wx环境是Win7下Code::Blocks nightlybuild 7040+MinGW4.5.1+wx2.9.2 SVN 2011-03-12,编译wx的各选项如下:
mingw32-make -f makefile.gcc BUILD=release SHARED=0 MONOLITHIC=1 UNICODE=1 2>errlog.txt
如未经说明,所有有关wx的随笔都是在些环境下。
突然提到这个是因为在本人过去的经历中,也就是在C::B nightly 7040之前,用wxSmith制作界面(如下讨论)后,在wxTextCtrl与wxFileDialog互操作时,很郁闷的发现:
1.界面菜单里的中文以及状态栏里的中文
2.读入到wxTextCtrl里的中文
3.把wxTextCtrl内容写回到文本文件里的中文
三者总有一个或两个出现乱码,不管我如何地刻苦努力,也无济于事。为此曾着实郁闷了一阵子,学习wx的兴趣也因之剧减。但因对wx的“此情不渝”,wx每有一个新的nightly build放出,我都要编译下来试一下。终于,这一个环境下,该问题不再出现。因此,在未发现有新的问题出现之前,本人会在相当长的时间内,一直使用这个环境,不再尝试跟着新的版本跑了。
好了,言归正题。下面的例子主要解决以下几个问题:
1.利用wxSmith生成中文菜单及要注意的问题
2.wxFileDialog的使用
3.在wxTextCtrl与wxFileDialog之间进行读写文件操作,该文件一定要中英文混合,本例中所用到的文件正是本例程源码之一,即wxSmith生成的xxxMain.cpp。
在C::B里wx项目向导下,为工程起名为testcnread,名字很不好,原因是易懂的名字都被我在前些版本下测试上述问题时用完了,创建这个工程时也没指望这个版本下上述问题会消失,所以很随意地起了这样一个名(TestCnRead),将就着点吧~
工程生成后,项目下总共有如下几个文件
testcnreadApp.h testcnreadMain.h testcnreadApp.cpp testcnreadMain.cpp resource.rc testcnreadframe.wxs
其中testcnreadframe.wxs是wxSimth界面文件,而testcnreadMain.cpp会在程序运行时被用来测试。
下图是程序运行时的主菜单打开后,鼠标点在"(&X)退出"菜单上时的截图,注意状态栏提示信息。
下面是点击"(&O)打开",然后在弹出的打开文件对话框下选择了上述的testcnreadMain.cpp文件后,wxTextCtrl将该文件内容读入后所显示的截图。
而下图则是点击"(&S)保存"后,将文本框里的内容保存至文件dummy.cpp里:
而下图则是打开保存的文件dummy.cpp看看数据显示是否正确无乱码:
下面一一来说明。
一.wxSmith生成中文界面
利用wxSimth设计器制作中文界面当然很简单,只需记着两点就够了:
1.所有有中文的地方,都需在源代码中(如,本例为testcnreadMain.cpp)将默认的_("blabla")改为wxT("中文的东东"),不然程序编译时会导致断言失败,运行后的界面会乱码;
2.wxSimth界面设计器每更新一次,默认生成的代码部分都会重置,如上面的例子,虽然你已将_("blabla")改为wxT("中文的东东")了。假设后来你又想起什么,或是新添加了一个子菜单或是一个新的按钮等等,保存后wxSmith又会将你已改好的wxT("中文的东东")改为_("中文的东东"),从而又一次导致前面所讲的问题。所以结论是:
1).一开始你只需测试一个中文菜单或按钮项什么的,只要确定是OK,建议用英文菜单就行了;
2).如果你和我一样固执,以为给中国人写的程序就一定得是中文菜单,那么,好好构思你的界面吧,一次完成;
3).如果你是上述2)里的人,同时也和我一样经常改来改去,那么,就不要嫌烦,哪里被wxSmith改回去了,你就再把它改回来。弄多几次自然就知道怎么弄了。
二.wxTextCtrl类的两个重要方法LoadFile和SaveFile
wxTextCtrl::LoadFile是从文件中获取内容:
bool wxTextCtrl::LoadFile ( const wxString & filename, int fileType = wxTEXT_TYPE_ANY )
如果文件filename存在,则将文件内容加载到wxTextCtrl里。
参数:
filename 要加载的文件名.
fileType 要加载文件的文件类型,目前该参数被wxTextCtrl所忽略.
返回值: 操作成功返回true ,失败返回 false.
也就是说,要将testcnreadMain.cpp里的内容一字不漏地读入到变量名为text1 (wxTextCtrl* text1)的wxTextCtrl里,你只需要下面一行代码:
text1->LoadFile(wxT("testcnreadMain.cpp"));
而SaveFile则是把wxTextCtrl里的内容写入到一文件里:
bool wxTextCtrl::SaveFile ( const wxString & filename = wxEmptyString, int fileType = wxTEXT_TYPE_ANY )
把wxTextCtrl里的内容保存到文件filename里
参数: filename 要保存到的文件名. fileType 要保存文件的文件类型,目前该参数被wxTextCtrl所忽略. 返回值: 操作成功返回true ,失败返回 false.
同样的,要将text1里的内容保存到名为dummy.cpp的文件里,你唯一需要的代码就是
text1->SaveFile(wxT("dummy.cpp"));
三.wxFileDialog
使用wxFileDialog类时首先要包含头文件<wx/filedlg.h>
wxFileDialog::wxFileDialog ( wxWindow * parent,
const wxString & message = wxFileSelectorPromptStr,
const wxString & defaultDir = wxEmptyString,
const wxString & defaultFile = wxEmptyString,
const wxString & wildcard = wxFileSelectorDefaultWildcardStr,
long style = wxFD_DEFAULT_STYLE,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
const wxString & name = wxFileDialogNameStr )
构选函数。
用ShowModal() 显示对话框
参数:
parent 父窗口
message 要显示的提示信息
defaultDir 默认要打开的目录,或为空字符串
defaultFile 要打开的默认文件名,或为空字符串
wildcard 文件扩展名通配符,比如 "*.*" 或 "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif"
style 对话框式样. 比如wxFD_OPEN为打开文件对话框,wxFD_FILE_MUST_EXIST则为打开文件对话框时文件必须存在
wxFD_SAVE为保存文件对话框,wxFD_OVERWRITE_PROMPT则为保存文件时如给定的文件已存在,则提示是否要覆盖已存在文件
pos 对话框位置,未实现
size 对话框大小,未实现
name 对话框名称,未实现
wxFileDialog::ShowModal() 用户点击了OK按钮则返回wxID_OK,不然的话则返回wxID_CANCEL
wxFileDialog::GetPath()、GetPaths()、wxFileDialog::GetFilename()、GetFilenames()其义自明。
下面是本例中通过打开文件对话框,选择源文件(testcnreadMain.cpp)并读入到wxTextCtrl (text1)里的全部代码:
1 #include <wx/filedlg.h>
2
3 void testcnreadFrame::OnOpenFileClick(wxCommandEvent& event)
4 {
5 wxFileDialog dlg(this,wxT("打开C++源程序"),wxT(""),wxT(""),
6 wxT("C++源程序(*.cpp)|*.cpp"),
7 wxFD_OPEN|wxFD_FILE_MUST_EXIST);
8 if(dlg.ShowModal()==wxID_CANCEL)
9 return;
10 text1->LoadFile(dlg.GetPath());
11
12 }
而下面则是打开保存文件对话框,选择要保存的文件名(dummy.cpp),然后将wxTextCtrl里的内容保存到该文件里的全部代码:
1 void testcnreadFrame::OnSaveFileClick(wxCommandEvent& event)
2 {
3 wxFileDialog* dlg=new wxFileDialog(this,wxT("保存C++源文件"),wxT(""),wxT(""),
4 wxT("C++源程序(*.cpp)|*.cpp|文本文件(*.txt)|*.txt"),
5 wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
6 if(dlg->ShowModal()==wxID_CANCEL)
7 return;
8 text1->SaveFile(dlg->GetPath());
9 dlg->Destroy();
10
11 }
注意两次分别演示了在堆上和栈上实例化wxFileDialog的方法。
全部源代码: http://cid-cc918acb2883534f.office.live.com/self.aspx/.Public/testcnread.7z