在开发过程中,经常会遇到程序在某些操作系统上无法正常运行的情况。特别是当程序依赖于某些特定库文件时,这个问题尤为突出。例如,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的依赖,并确保程序在目标平台上能够正常运行。
首先,需要从项目中移除对oleacc.lib的依赖。这可以通过以下步骤完成:
接下来,需要编写自己的代理函数来动态加载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"));
}
}