解决MFC程序在旧版Windows上的兼容性问题

在开发过程中,经常会遇到程序在某些操作系统上无法正常运行的情况。特别是当程序依赖于某些特定库文件时,这个问题尤为突出。例如,Microsoft Active Accessibility (MSAA) 库文件 oleacc.dll 在1997年发布后,一些旧的操作系统如Windows 95、Windows NT和未安装Active Accessibility Options的Windows 98就无法正常支持它。这导致依赖于此库的程序在这些平台上运行失败,给开发者带来了不小的困扰。

MFC7.0中,类CWnd的某些成员函数会调用oleacc.dll中的三个过程:

AccessibleObjectFromWindow(HWND hwnd, DWORD dwId, REFIID riid, void **ppvObject); CreateStdAccessibleObject(HWND hwnd, LONG idObject, REFIID riid, void** ppvObject); LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN punk);

为了解决这个问题,可以通过以下步骤来移除对oleacc.dll的依赖,并确保程序在目标平台上能够正常运行。

步骤1:移除项目对oleacc.lib的依赖

首先,需要从项目中移除对oleacc.lib的依赖。这可以通过以下步骤完成:

  1. 在Visual Studio中,选择“项目”菜单中的“属性...”选项。
  2. 在配置树中选择“链接器”目录,然后点击“输入”。
  3. 点击“忽略特定库”,并输入“oleacc.lib”。

步骤2:编写自己的代理函数

接下来,需要编写自己的代理函数来动态加载oleacc.dll,并在加载成功后调用其中的相应过程。这些函数的名称与MSAA API相对应。将这些函数封装到两个文件中:oleaccproxy.h和oleaccproxy.cpp,并将它们添加到项目中。以下是代理函数的源代码:

// oleaccproxy.h #pragma once typedef LRESULT (_stdcall *pfnAccessibleObjectFromWindow)(HWND hwnd, DWORD dwId, REFIID riid, void **ppvObject); typedef LRESULT (_stdcall *pfnCreateStdAccessibleObject)(HWND hwnd, LONG idObject, REFIID riid, void** ppvObject); typedef LRESULT (_stdcall *pfnLresultFromObject)(REFIID riid, WPARAM wParam, LPUNKNOWN punk); class COleaccProxy { public: COleaccProxy(void); virtual ~COleaccProxy(void); private: static HMODULE m_hModule; static BOOL m_bFailed; public: static void Init(void); static pfnAccessibleObjectFromWindow m_pfnAccessibleObjectFromWindow; static pfnCreateStdAccessibleObject m_pfnCreateStdAccessibleObject; static pfnLresultFromObject m_pfnLresultFromObject; }; // oleaccproxy.cpp #include "StdAfx.h" #include "oleaccproxy.h" extern "C" LRESULT _stdcall AccessibleObjectFromWindow(HWND hwnd, DWORD dwId, REFIID riid, void **ppvObject) { COleaccProxy::Init(); return COleaccProxy::m_pfnAccessibleObjectFromWindow ? COleaccProxy::m_pfnAccessibleObjectFromWindow(hwnd, dwId, riid, ppvObject) : 0; } extern "C" LRESULT _stdcall CreateStdAccessibleObject(HWND hwnd, LONG idObject, REFIID riid, void** ppvObject) { COleaccProxy::Init(); return COleaccProxy::m_pfnCreateStdAccessibleObject ? COleaccProxy::m_pfnCreateStdAccessibleObject(hwnd, idObject, riid, ppvObject) : 0; } extern "C" LRESULT _stdcall LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN punk) { COleaccProxy::Init(); return COleaccProxy::m_pfnLresultFromObject ? COleaccProxy::m_pfnLresultFromObject(riid, wParam, punk) : 0; } HMODULE COleaccProxy::m_hModule = NULL; BOOL COleaccProxy::m_bFailed = FALSE; pfnAccessibleObjectFromWindow COleaccProxy::m_pfnAccessibleObjectFromWindow = NULL; pfnCreateStdAccessibleObject COleaccProxy::m_pfnCreateStdAccessibleObject = NULL; pfnLresultFromObject COleaccProxy::m_pfnLresultFromObject = NULL; COleaccProxy::COleaccProxy(void) { } COleaccProxy::~COleaccProxy(void) { } void COleaccProxy::Init(void) { if (!m_hModule && !m_bFailed) { m_hModule = ::LoadLibrary(_T("oleacc.dll")); if (!m_hModule) { m_bFailed = TRUE; return; } m_pfnAccessibleObjectFromWindow = (pfnAccessibleObjectFromWindow)::GetProcAddress(m_hModule, _T("AccessibleObjectFromWindow")); m_pfnCreateStdAccessibleObject = (pfnCreateStdAccessibleObject)::GetProcAddress(m_hModule, _T("CreateStdAccessibleObject")); m_pfnLresultFromObject = (pfnLresultFromObject)::GetProcAddress(m_hModule, _T("LresultFromObject")); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485