在Visual Studio上构建C++的GUI框架wxWidgets的开发环境
本文使用的unicode+dll+debug的方式,因为不想最后生成的exe文件太大。
环境搭建步骤如下:
1、下载wxwidgets包:
登录wxwidgets的下载页面:http://www.wxwidgets.org/downloads
下载最新的stable release稳定版,我这里用旧的2.8.12版作演示。
2、将wxmsw-2.8.12.zip解压到d盘根目录下。
转到d:\wxmsw-2.8.12\build\msw目录,用vs2005打开wx.dsw,会有提示转换项目:
选择“全是”。
3、进入到vs2005的界面,在下图所示区域选择dll unicode debug:
4、按f7生成解决方案,这个操作会在d:\wxmsw-2.8.12\lib下生成一个“vc_dll”文件夹,里面是我们需要的dll和lib。
不过第一次执行会提示有一些失败的。因为有一些生成项依赖于其他的生成项。此时继续按f7,直到提示有1个失败。此时,再按f7也是没用的,看看错误提示:
1>link : fatal error lnk1104: 无法打开文件“..\..\lib\vc_dll\wxbase28ud_odbc.lib”
这个wxbase28ud_odbc.lib在d:\wxmsw-2.8.12\lib\vc_dll下并不存在。此时可以在上图中选择unicode debug,之后在左边选择odbc,右击,选择生成,会在d:\wxmsw-2.8.12\lib\vc_lib目录下生成wxbase28ud_odbc.lib,将这个文件拷到d:\wxmsw-2.8.12\lib\vc_dll目录下,在上图中将选项选回dll unicode debug,再按f7,这样所有的文件都生成了。
这样,在生成了14个dll文件和18个lib文件。
5、在菜单栏依次选择 工具——选项,在打开的窗口依次选择 项目和解决方案——vc++目录。
5.1 在“包含文件”中添加:
d:\wxmsw-2.8.12\include d:\wxmsw-2.8.12\include\msvc
5.2 在“库文件”中添加:
d:\wxmsw-2.8.12\lib\vc_dll d:\wxmsw-2.8.12\lib\vc_dll\mswud
如下图:
6、关闭原来的工程,新建一个空的win32项目,名称为wxtest。注意,要是空的项目。
为这个项目添加一个c++文件test.cpp,内容为d:\wxmsw-2.8.12\samples\minimal\minimal.cpp的内容。
7、配置项目:
选中这个项目,在菜单栏依次选择 项目——wxtest属性,在打开的窗口配置属性:
7.1 在“配置属性 —— c/c++ —— 预处理器”中的“预处理器定义”添加:
_unicode;wxusingdll
7.2 在“配置属性 —— c/c++ —— 运行时库”中的“运行时库”选择:
多线程调试 dll (/mdd)
7.3 在“配置属性 —— 链接器 —— 输入”中的“附加依赖库”添加:
wxbase28ud.lib wxbase28ud_net.lib wxbase28ud_odbc.lib wxbase28ud_xml.lib wxexpatd.lib wxjpegd.lib wxmsw28ud_adv.lib wxmsw28ud_aui.lib wxmsw28ud_core.lib wxmsw28ud_html.lib wxmsw28ud_media.lib wxmsw28ud_qa.lib wxmsw28ud_richtext.lib wxmsw28ud_xrc.lib wxpngd.lib wxregexud.lib wxtiffd.lib wxzlibd.lib
这里是一股脑全加上了。
8、生成解决方案,是成功的。按f5运行这个程序,会提示计算机中丢失wxmsw28ud_core_vc_custom.dll,从d:\wxmsw-2.8.12\lib\vc_dll中把这个文件拷到生成的exe文件所在的目录下。再次运行,会提示丢失wxbase28ud_vc_custom.dll,再把这个文件拷到生成的exe文件所在的目录下。此时再运行就可以正确执行了:
关于wxwidgets控件出现乱码问题的解决
这两天在用wxwidgets做一个小程序,突然遇到了一个控件显示出现乱码的问题。
首先声明:我用的编译器是visual studio 2005,wxwidgets版本是2.8.12,下面的解决方法不一定对所有的平台都有效。
我们知道,wxwidgets中控件显示字符串一般都是用wxstring,例如下面的一小段代码创建并显示一个按钮:
// 创建一个按钮,显示名称就是“按钮” wxbutton* onebutton = new wxbutton( itemframe1, id_button, wxt("按钮"), wxdefaultposition, wxdefaultsize, 0); // 把这个按钮放在一个boxsizer中 itemboxsizer->add(onebutton, 1, wxalign_center_vertical|wxall, 5);
上面的代码没有错误,显示截图如下:
但是,很多情况下,我们想要显示的控件的标签是先放在char *中的,我们当然要先转换成wxstring,转换的方法有很多,比如用wxstring::fromutf8(),或者可以定义一个wxstring对象,调用printf方法。然而,两种方法都不行。
如下代码:
char *label = "按钮"; wxstring wxlabel; wxlabel.printf(wxt("%s"), label); wxbutton* onebutton = new wxbutton( itemframe1, id_button, wxlabel, wxdefaultposition, wxdefaultsize, 0); itemboxsizer->add(onebutton, 1, wxalign_center_vertical|wxall, 5);
得到的结果是
而如果使用wxstring::fromutf8(),则控件中根本没有显示的标签。
谷歌了很久都没找到解决办法,后来突然想到,以前做一个gtk项目的时候遇到过中文出现乱码的问题,当时峰哥给我发了一个将字符串转换编码的函数,当然,gtk有自带的函数可以进行转换,是g_locale_to_utf8。而wxwidgets貌似没有这样的函数。峰哥给我的函数正好派上用场。
峰哥给我的函数是ansi与utf8相互转换,为什么有用,是因为vs默认的编码是ansi。我今天在谷歌的时候,见到有人说将源代码的编码格式改成utf8,在vs的 文件——高级保存选项中,我试过了,没用。但是用了峰哥给我的函数,效果就不一样了。
峰哥的代码是:
bool ansi_to_utf8(char * lpcszstr, char** lpwszstr) { wchar* stra; int i= multibytetowidechar(cp_acp, 0, (char*)lpcszstr, -1, null, 0); stra = (wchar *)malloc(sizeof(wchar) * i); multibytetowidechar(cp_acp, 0, (char* )lpcszstr, -1, stra, i*2); i= widechartomultibyte(cp_utf8, 0, stra, -1, null, 0, null, null); *lpwszstr = (char *)malloc(i); widechartomultibyte(cp_utf8, 0, stra, -1, *lpwszstr, i, null, null); return true; }
可以把这段代码放在程序的某个头文件中,作为一个成员函数。别忘了包含windows.h头文件。
再修改上面的第二段代码如下:
char *label = "按钮2"; char *label_utf8; this->ansi_to_utf8(label, &label_utf8); wxbutton* onebutton = new wxbutton( itemframe1, id_button, wxstring::fromutf8(label_utf8), wxdefaultposition, wxdefaultsize, 0); free(label_utf8); itemboxsizer->add(onebutton, 1, wxalign_center_vertical|wxall, 5);
这样就可以正常显示了: