Posts tagged ‘wxwidgets’

现象

使用 DialogBlocks 建立自定义窗口类,使用 wxFlexGridSizer 布局控件。主窗口类使用这个自定义的窗口类作为子控件。因为这个子控件在程序开始运行隐藏,只在执行某项任务完成后才显示,结果在显示时位置和尺寸都不对,几乎不可见,使用鼠标调整主窗口尺寸后这个子控件的布局和尺寸才随之变化达到设计意图。

Continue reading ‘wxWidgets 怎样重新计算窗口布局’ »

现象

HAT 程序在处理 TESTING_THREAD_DONE 事件时,出现非法操作引起程序退出。疑为转换指针类型时发生错误。

Continue reading ‘wxWidgets 控件 ID 冲突’ »

现象

在编译手工编码的 MpiProdave.cpp/MpiProdave.h 时,使用 DialogBlocks MinGW Debug (Non-Unicode)标准编译器设置发生编译错误如下。这种错误在其他 DialogBlocks 生成的某些 c++ 文件编译时也会出现。而使用 MinGW Unicode Debug 标准编译设置时则没有编译错误发生。

g++.exe -c -o MinGWDebug/MpiProdave.o -fno-pcc-struct-return -fstrict-aliasing -Wall -Wno-write-strings -D__WXMSW__ -D__GNUWIN32__ -D__WIN95__  -D__WXDEBUG__ -ggdb -O0 -Wall -Wno-write-strings -I"C:/wx/include" -I"C:/wx/contrib/include" -I"C:/wx/lib/gcc_lib/mswd" src\MpiProdave.cpp
*** In file included from C:/wx/include/wx/toplevel.h:317,
***                  from C:/wx/include/wx/dialog.h:17,
***                  from C:/wx/include/wx/msw/msgdlg.h:16,
***                  from C:/wx/include/wx/msgdlg.h:49,
***                  from src\MpiProdave.cpp:17:
*** C:/wx/include/wx/msw/toplevel.h:122: error: expected identifier before numeric constant
*** C:/wx/include/wx/msw/toplevel.h:122: error: expected `,' or `...' before numeric constant
*** C:/wx/include/wx/msw/toplevel.h:122: error: ISO C++ forbids declaration of `parameter' with no type
*** mingw32-make.exe: *** [MinGWDebug/MpiProdave.o] Error 1

Continue reading ‘MinGW 宏定义与 wxWidgets 头文件冲突’ »

现象

wxWidgets 与 IBPP 一同使用(连接 wxWidgets 库)时,

  • 如果使用 Unicode,则 IBPP 无法编译,错误信息:
    make -f makefile.gcc all
    g++.exe -c -o MinGWUnicodeDebug/all_in_one.o -fno-rtti -fno-pcc-struct-return -fstrict-aliasing -Wall -Wno-write-strings -D__WXMSW__ -D__GNUWIN32__ -D__WIN95__ -DUNICODE  -D__WXDEBUG__ -ggdb -O0 -Wall -Wno-write-strings -I"C:/wx/include" -I"C:/wx/contrib/include" -I"C:/wx/lib/gcc_lib/mswud" ibpp\core\all_in_one.cpp
    In file included from ibpp\core\all_in_one.cpp:35:
    ibpp\core\_ibpp.cpp: In member function `ibpp_internals::GDS* ibpp_internals::GDS::Call()':
    ibpp\core\_ibpp.cpp:142: error: cannot convert `const char*' to `const WCHAR*' for argument `1' to `HINSTANCE__* LoadLibraryW(const WCHAR*)'
    ibpp\core\_ibpp.cpp:162: error: cannot convert `char*' to `WCHAR*' for argument `2' to `DWORD GetModuleFileNameW(HINSTANCE__*, WCHAR*, DWORD)'
    ibpp\core\_ibpp.cpp:170: error: cannot convert `char*' to `WCHAR*' for argument `1' to `WCHAR* lstrcatW(WCHAR*, const WCHAR*)'
    ... ...
  • 如果不使用 Unicode,编译通过,但运行时发生异常退出。

解决方案

针对第二种情况,不使用 wxWidgets 的编译选项 -fno-rtti,重新编译 IBPP(all_in_one.cpp)。

即在 Makefile 里把下面一行:

CPPFLAGS= -fno-rtti -fno-pcc-struct-return -fstrict-aliasing -Wall -Wno-write-strings -D__WXMSW__ -D__GNUWIN32__ -D__WIN95__

改为

CPPFLAGS=-fno-pcc-struct-return -fstrict-aliasing -Wall -Wno-write-strings -D__WXMSW__ -D__GNUWIN32__ -D__WIN95__

故障消除。

(参考使用 wxWidgets 编写国际化程序

  1. 目标系统上安装 NJStar Communicator,并运行 NJStar。
  2. 在 Application 类 头文件变量声明部分内插入如下代码:
    private:
        wxLocale _locale;
  3. 在 Application 类 cpp 文件的 OnInit() 函数开始插入如下代码:
    if (_locale.Init(wxLANGUAGE_FRENCH, 0)) {
    	wxLocale::AddCatalogLookupPathPrefix(wxT("resources"));
    	_locale.AddCatalog(_T("default"));
    }

    这里重要的是行1:不能设置为 wxLANGUAGE_CHINESE_SIMPLIFIED,否则系统报错“不能设置为指定语言”。而 Windows 2000 操作默认支持法语,这里实际上绕过了系统的检查。

  4. 使用 poEdit 建立分类条目,将字符串翻译为中文,并生成 .mo 文件(在这里为 default.mo)。
  5. 在程序运行根目录下建立目录 resources\fr,复制上一步生成的 .mo 文件到这个目录。

注意:使用这个方法,菜单(菜单条和弹出式菜单)无法汉化,其余用户界面控件显示正常。有时会有字符宽度问题。

窗口关系如下:

wxScrolledWindow > wxBoxSizer > wxPanel derived

从 wxPanel derived 函数内部调用如下代码:

// ajust chart window size
SetSizeHints(w, h);
// ask containing sizer to request scroll window for resizing
GetParent()->GetSizer()->FitInside(GetParent());

现象

在 wxFrame 窗口中嵌入 wxSplitWindow,程序初始运行时隐藏,待载入数据后显示,但显示时未铺满 wxFrame 的用户区域,手动 resize 后,尺寸调整至正常。

解决方法

给父窗口(此处是 wxFrame)发送 wxSizeEvent,代码如下(代码片段在 wxFrame 派生类的一个函数中):

_contentwnd->Show();
// send resize event to frame to make split window fit into content area
wxSizeEvent sizeEvent(GetSize());
wxPostEvent(this, sizeEvent);

现象

从 wxPanel 派生一个新类,使用 OnPaint() 画背景(灰色边线的矩形),父窗口 resize 时新类的窗口中画出的背景发生重叠。

解决办法

在包含新类的父窗口 style 属性页中选中 wx_FULL_REPAINT_ON_RESIZE

现象

frame 窗口关闭时(似乎)已经强行关闭了所有线程,因此使用线程指针 Delete() 将出现内存错误。

解决方案

拦截程序菜单中的退出事件和主Frame的 wxEVT_CLOSE_WINDOW 事件(called when the user closes the frame via the window decorations),删除线程。参见 hats/MainFrame.cpp

更好的解决方案:有无一个统一的节点,所有导致应用程序关闭(主窗口关闭)的过程都在关闭主窗口之前调用这个节点,而这个节点又可以重载(虚拟)?

操作GUI

wxMutexGuiEnter();
// 进行 GUI 操作
// ...
wxMutexGuiLeave();

在非主线程(非GUI线程)中如果要对GUI进行直接操作就必须使用这种方法,否则会出现同步错误,引起程序非正常终止。

注意这种方法的局限性:多个线程对于GUI的操作严格互锁,交替进行。例如在非GUI线程中有下列代码:

wxMutexGuiEnter();
wxLogDebug(_T("%d..."), i);
wxMutexGuiLeave();

如果下拉主菜单,则Log窗口的输出暂时停止,待菜单回卷后才继续进行。

最安全的方法还是使用自定义命令事件传递,例如在非GUI线程中可以这样:

// send done event to give hint
wxCommandEvent doneEvent(wxEVT_COMMAND_MENU_SELECTED, TESTING_THREAD_DONE);
wxPostEvent(_frame, doneEvent);

TestDestroy() & Delete()

用来停止 work thread。

Continue reading ‘使用 wxWidgets 进行 Multi-threading 编程’ »