wxpython skin bug(弹出菜单,内存错误)
来源:互联网 发布:mysql大于符号 编辑:程序博客网 时间:2024/06/04 21:06
前面说到了 wxpython skin的问题(使用皮肤后弹出目录,程序崩溃)
http://blog.csdn.net/xugangjava/article/details/7763212
使用OllyDbg 调试 发现在wxwindow中的 handlermenuchar 报错了,非法的地址访问,
一下也看不出来是为什么,还好wxpython是开源的,网上下载源码。
我下载的是2.9.4 最新版,我建议下载这个版本,官方的说法是development 版本的并非bug更多,只是文档跟API未能跟上而已,
wxpython2.9编译非常简单,在vc 2008命令提示符 下运行 wxpython目录中的 build_wxpython.py 就 OK了
详细可以参考http://wxpython.org/BUILD.html
打开源码查看 core 工程目录下的 MSW Sources
打开windows.cpp 5805行
#if wxUSE_MENUSint wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), WXLPARAM WXUNUSED_IN_WINCE(lParam)){ // FIXME: implement GetMenuItemCount for WinCE, possibly // in terms of GetMenuItemInfo#ifndef __WXWINCE__ const HMENU hmenu = (HMENU)lParam; WinStruct<MENUITEMINFO> mii; // we could use MIIM_FTYPE here as we only need to know if the item is // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but // MIIM_FTYPE is not supported under Win95 mii.fMask = MIIM_TYPE | MIIM_DATA; // find if we have this letter in any owner drawn item const int count = ::GetMenuItemCount(hmenu); for ( int i = 0; i < count; i++ ) { // previous loop iteration could modify it, reset it back before // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData mii.cch = 0; if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) ) { if ( mii.fType == MFT_OWNERDRAW ) { // dwItemData member of the MENUITEMINFO is a // pointer to the associated wxMenuItem -- see the // menu creation code wxMenuItem *item = (wxMenuItem*)mii.dwItemData; const wxString label(item->GetItemLabel()); const wxChar *p = wxStrchr(label.t_str(), wxT('&')); while ( p++ ) { if ( *p == wxT('&') ) { // this is not the accel char, find the real one p = wxStrchr(p + 1, wxT('&')); } else // got the accel char { // FIXME-UNICODE: this comparison doesn't risk to work // for non ASCII accelerator characters I'm afraid, but // what can we do? if ( (wchar_t)wxToupper(*p) == (wchar_t)chAccel ) { return i; } else { // this one doesn't match break; } } } } } else // failed to get the menu text? { // it's not fatal, so don't show error, but still log it wxLogLastError(wxT("GetMenuItemInfo")); } }#endif return wxNOT_FOUND;}
const wxString label(item->GetItemLabel()); 这里报错,内存冲突
看来mii.dwItemData强转成wxMenuItem 调用GetItemLabel时造成了无效的内存访问。
重新实现这一段代码,使用GetMenuString来得到,Menu的 Text 然后跟用户按键比较。
#if wxUSE_MENUSint wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), WXLPARAM WXUNUSED_IN_WINCE(lParam)){ // FIXME: implement GetMenuItemCount for WinCE, possibly // in terms of GetMenuItemInfo#ifndef __WXWINCE__ const HMENU hmenu = (HMENU)lParam;//xugangjava fixedWinStruct<MENUITEMINFO> mii;mii.fMask = MIIM_TYPE | MIIM_DATA;const int count=::GetMenuItemCount(hmenu);wchar_t itemText[255];for(int itemIdx=0;itemIdx<count;itemIdx++){if ( ::GetMenuItemInfo(hmenu, itemIdx, TRUE, &mii) ){ if ( mii.fType == MFT_OWNERDRAW ) { int textLen =::GetMenuStringW(hmenu,itemIdx,itemText,255,MF_BYPOSITION); if(!textLen)continue; for(int strIdx=0;strIdx<textLen;strIdx++) {if(itemText[strIdx]==L'&')continue;else if (itemText[strIdx] == (wchar_t)chAccel)return itemIdx;elsebreak; } }}else // failed to get the menu text?{// it's not fatal, so don't show error, but still log itwxLogLastError(wxT("GetMenuItemInfo"));}}/* bug // we could use MIIM_FTYPE here as we only need to know if the item is // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but // MIIM_FTYPE is not supported under Win95 mii.fMask = MIIM_TYPE | MIIM_DATA; // find if we have this letter in any owner drawn item const int count = ::GetMenuItemCount(hmenu); for ( int i = 0; i < count; i++ ) { // previous loop iteration could modify it, reset it back before // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData mii.cch = 0; if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) ) { if ( mii.fType == MFT_OWNERDRAW ) { // dwItemData member of the MENUITEMINFO is a // pointer to the associated wxMenuItem -- see the // menu creation code wxMenuItem *item = (wxMenuItem*)mii.dwItemData; const wxString label(item->GetItemLabel()); const wxChar *p = wxStrchr(label.t_str(), wxT('&')); while ( p++ ) { if ( *p == wxT('&') ) { // this is not the accel char, find the real one p = wxStrchr(p + 1, wxT('&')); } else // got the accel char { // FIXME-UNICODE: this comparison doesn't risk to work // for non ASCII accelerator characters I'm afraid, but // what can we do? if ( (wchar_t)wxToupper(*p) == (wchar_t)chAccel ) { return i; } else { // this one doesn't match break; } } } } } else // failed to get the menu text? { // it's not fatal, so don't show error, but still log it wxLogLastError(wxT("GetMenuItemInfo")); } }*/#endif return wxNOT_FOUND;}
Ok 经过测试后 皮肤可以用了,没有内存崩溃,
现在 Wxpython 也可以做出QQ 的效果了,虽然有些地方没有渲染到位,不过整体还是可以的
(我用的是SkinSharp,向大家推荐一下)
- wxpython skin bug(弹出菜单,内存错误)
- wxpython skin bug(staticbox背景绘制)
- wxpython禁止弹出错误框
- wxpython skin sharp的问题
- android 7.0 popuwindow 位置弹出错误bug
- wxPython菜单与工具栏
- wxPython:菜单介绍
- wxpython 创建窗口菜单
- wxPython菜单与工具栏
- wxPython添加菜单
- wxPython中的菜单
- IE7 自动弹出下拉菜单错误
- webView第一次长按不弹出菜单的bug
- 弹出菜单(有弹出过程)
- wxPython 实现右下角弹出框
- 右键弹出菜单(oncontextmenu)
- 一个菜单示例分析(wxPython)
- wxPython:工具栏、状态栏、菜单实现
- Classification
- Connected Components Labeling
- jffs2_scan_inode_node(): Data CRC failed on node at ... Read ... calculated ...
- Windows 8关键里程碑
- 告诉你一个真实的中国互联网:精英与草根
- wxpython skin bug(弹出菜单,内存错误)
- C# 延时函数 非Sleep
- Hough Transform
- wince U盘驱动的增加
- Thickening
- WINCE下内核模式和用户模式的区别
- java基本的名字术语:java源文件,java字节码文件,JDK,JRE,JVM
- Hit-and-Miss Transform
- Adaptive Thresholding