none
Vista新增API在XP中无法定位 RRS feed

  • 问题

  • 我希望我的MFC程序在vista以上系统运行时 使用Vista新增的API  ChangeWindowMessageFilter 但是这样导致我的程序在XP中直接报错无法定位ChangeWindowMessageFilter在USER32.DLL

    	OSVERSIONINFO osver;
    	osver.dwOSVersionInfoSize = sizeof(osver);
    	GetVersionEx(&osver);
    	CString out;
    	out.Format("%d", osver.dwMajorVersion);
    	AfxMessageBox(out);
    	if(osver.dwMajorVersion >= 6){
    		ChangeWindowMessageFilter(WM_USER + 3, MSGFLT_ADD);
    		ChangeWindowMessageFilter(WM_USER + 4, MSGFLT_ADD);
    	}
    我写了上面的代码 但是程序在XP中运行时似乎没有做判断而是直接报出无法定位ChangeWindowMessageFilter在USER32.DLL  是什么原因 如何解决?
    2010年3月23日 7:28

答案

  • 比较简单的方法是把Vista独有的代码放到一个DLL里面去,判断操作系统是Vista之后再把这个DLL载入。

    你的问题估计是编译的时候就选择了Vista支持,不然编译都通不过的。

     

    不想分DLL的话也可以用LoadLibrary/GetProceAddress来调用函数。



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    • 已标记为答案 李砚超 2010年3月24日 6:01
    2010年3月23日 22:34
    版主
  • 链接的时候要知道跳转到哪里,所以编译器要知道ChangeWindowMessageFilter才行,换一个更高版本的编译器,或者把更高版本编译器的头文件和lib文件拷贝过来试试。

    也可以试一下换一种方式调用它,例如先LoadLibaray()然后GetProcAddress(),这样编译器不知道ChangeWindowMessageFilter的地址也可以编译成功。

     

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

     

    大家好,我刚来到这里,初学者,希望大家多多指教,谢谢。

    • 已标记为答案 李砚超 2010年3月24日 6:01
    2010年3月23日 11:47

全部回复

  • 这个……  你Vista 才支持的API Windows XP 当然不支持了。

     

    你要么可以在运行时进行动态判断,比如通过GetVersion() 函数获取OS的主版本号,XP的是5 Vista 是6.

    if(6 <= dwMajorVersion)

    {

    ChangeWindowMessageFilter

    }

    else

    {

    // XP 下的处理

    }

     

    另外,你使用Visual Studio 创建工程,在工程中会有一个targetver.h 的头文件, 里面有 WINVER _WIN32_WINNT  _WIN32_WINDOWS 几个版本宏,若你的程序需要支持XP,就将WINVER _WIN32_WINNT 的值改为0x0500

    这样,当你的代码中使用了只有Vista 才支持的API 时,编译器在编译代码时就会报错了。可以提示你。

     

    总之,你别指望在XP 上调用一个Vista 才有的API。 而且这也不是把vista 上的user32.dll 拷贝到XP 上就能解决的。

     

    2010年3月23日 7:48
    版主
  • 额 我写了判断的代码 我是希望它只在Vista以上执行ChangeWindowMessageFilter XP中不执行

    	OSVERSIONINFO osver;
    	osver.dwOSVersionInfoSize = sizeof(osver);
    	GetVersionEx(&osver);
    	if(osver.dwMajorVersion >= 6){
    		ChangeWindowMessageFilter(WM_USER + 3, MSGFLT_ADD);
    		ChangeWindowMessageFilter(WM_USER + 4, MSGFLT_ADD);
    	}
    这样的话应该在XP上不执行ChangeWindowMessageFilter才对 但是实际情况是在XP中运行时直接报错 说无法定位ChangeWindowMessageFilter在USER32.DLL
    2010年3月23日 7:56
  • 对不起,我看题目不仔细。 你有没有尝试使用static link 方式编译程序呢?
    2010年3月23日 8:11
    版主
  • 不懂 程序是从VC6升级上来的 /MT 静态MFC
    2010年3月23日 8:45
  • 现在的问题是我的程序似乎在执行if(osver.dwMajorVersion >= 6)之前就试图从USER32.DLL找到ChangeWindowMessageFilter
    2010年3月23日 8:51
  • 链接的时候要知道跳转到哪里,所以编译器要知道ChangeWindowMessageFilter才行,换一个更高版本的编译器,或者把更高版本编译器的头文件和lib文件拷贝过来试试。

    也可以试一下换一种方式调用它,例如先LoadLibaray()然后GetProcAddress(),这样编译器不知道ChangeWindowMessageFilter的地址也可以编译成功。

     

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

     

    大家好,我刚来到这里,初学者,希望大家多多指教,谢谢。

    • 已标记为答案 李砚超 2010年3月24日 6:01
    2010年3月23日 11:47
  • 你这样写肯定是要报错地,因为你的链接器仍然会去查找ChangeWindowMessageFilter这个函数,而XP的DLL里面是没有它的。

    正确的做法是使用宏

    #ifndef WINVER    // Allow use of features specific to Windows XP or later.
    #define WINVER 0x0501  // Change this to the appropriate value to target other versions of Windows.
    #endif

    #ifndef _WIN32_WINNT  // Allow use of features specific to Windows XP or later.                  
    #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
    #endif      

    #ifndef _WIN32_WINDOWS  // Allow use of features specific to Windows 98 or later.
    #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
    #endif
    这是MFC中的定义,在任何用到Win32 API的地方都可以使用,是编译器预定义的。

     

    你可以这样写

    #if _WIN32_WINNT > 0x0501

    ChangeWindowMessageFilter(WM_USER + 3, MSGFLT_ADD);
    ChangeWindowMessageFilter(WM_USER + 4, MSGFLT_ADD);

    #endif


    0xBAADF00D
    • 已建议为答案 xiilin 2010年3月23日 14:35
    2010年3月23日 13:26
    版主
  • 比较简单的方法是把Vista独有的代码放到一个DLL里面去,判断操作系统是Vista之后再把这个DLL载入。

    你的问题估计是编译的时候就选择了Vista支持,不然编译都通不过的。

     

    不想分DLL的话也可以用LoadLibrary/GetProceAddress来调用函数。



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    • 已标记为答案 李砚超 2010年3月24日 6:01
    2010年3月23日 22:34
    版主
  • 比较简单的方法是把Vista独有的代码放到一个DLL里面去,判断操作系统是Vista之后再把这个DLL载入。

    你的问题估计是编译的时候就选择了Vista支持,不然编译都通不过的。

     

    不想分DLL的话也可以用LoadLibrary/GetProceAddress来调用函数。



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    用独立 DLL 大概是最好的办法了, 靠宏切换还是编译前的事情, 不能做到一个程序文件通吃所有系统, 通过主程序 GetVersionEx 然后选择性装入 DLL 或者采用 DLL 延迟加载是针对这类问题比较灵活的解决办法.
    2010年3月26日 11:49