如何禁用 MFC Feature Pack 应用程序中 MenuBar 项目中文本的恢复?
How to disable the restoration of text in MenuBar items in an MFC Feature Pack application?
我的应用程序是使用 MFC 功能包 (VS2012) 编写的。它可以通过从资源 dll 加载数据来切换 UI 本地化。但是 CMFCMenuBar
菜单会在应用程序重新加载时恢复菜单项的原始文本。
如果我使用 GetDockingManager()->DisableRestoreDockState(TRUE);
,它会阻止恢复所有布局数据,而不仅仅是文本数据。
我知道 MFC Feature Pack 序列化了许多 UI 元素。如果可能,如何禁用文本数据序列化来实现此目的?
我找到了很好的解决方案。主要思想是将 LANGID 与菜单按钮数据一起存储。当菜单栏执行加载过程时,我们需要检查存储的 LANGID 和当前进程的 LANGID,如果它们不相等,则重置栏。
代码:
class CLocalyMenuBar
: public CMFCMenuBar
{
DECLARE_SERIAL(CLocalyMenuBar)
public:
typedef CMFCMenuBar TBase;
public:
CLocalyMenuBar();
virtual ~CLocalyMenuBar();
virtual void Serialize(CArchive& ar);
};
IMPLEMENT_SERIAL(CLocalyMenuBar, CLocalyMenuBar::TBase, VERSIONABLE_SCHEMA | 1)
CLocalyMenuBar::CLocalyMenuBar()
{}
CLocalyMenuBar::~CLocalyMenuBar()
{}
void CLocalyMenuBar::Serialize(CArchive& ar)
{
TBase::Serialize(ar);
if (ar.IsLoading()) {
LANGID nID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
ar >> nID;
if ((nID != Locality::GetCurResourceLANGID()) && CanBeRestored()) {
RestoreOriginalState();
}
}
else {
ar << Locality::GetCurResourceLANGID();
}
}
namespace Locality {
LANGID GetCurResourceLANGID()
{
// You should return current resource LANGID for your app process!
return MY_PROCESS_CURRENT_LANGID;
}
}
P.S.:
为了获得更好的结果,您应该将此类序列化代码添加到所有工具栏和可停靠栏 类.
仅删除文本并仍然保存菜单的 positions/customization...
您将不得不超越 CMFCToolbarButton class 并在您不想保存的地方使用该按钮。在 CMFCMenuBar 中,可能有一种方法可以传递用于按钮的 class 类型。那么你的按钮 class 可以有一个 BOOL 来打开或关闭保存文本。
如果无法在菜单中传递按钮 class 类型,那么您将不得不覆盖创建这些按钮的人。
与所有序列化代码一样,一个对象序列化另一个对象。
CMFCMenuBar 最终序列化 CBCGPToolbarButton::Serialize 的项目。如果您查看此代码,您会发现文本已存储并重新加载到那里...
因此,您唯一的机会就是将工具栏中的所有控件更改为您的 class。而这几乎是不可能的。更改序列化中的行为不是可行的方法。
所以从我的角度来看,除了选择不同的方法外,没有很好的答案来解决你的问题。
我的应用程序是使用 MFC 功能包 (VS2012) 编写的。它可以通过从资源 dll 加载数据来切换 UI 本地化。但是 CMFCMenuBar
菜单会在应用程序重新加载时恢复菜单项的原始文本。
如果我使用 GetDockingManager()->DisableRestoreDockState(TRUE);
,它会阻止恢复所有布局数据,而不仅仅是文本数据。
我知道 MFC Feature Pack 序列化了许多 UI 元素。如果可能,如何禁用文本数据序列化来实现此目的?
我找到了很好的解决方案。主要思想是将 LANGID 与菜单按钮数据一起存储。当菜单栏执行加载过程时,我们需要检查存储的 LANGID 和当前进程的 LANGID,如果它们不相等,则重置栏。
代码:
class CLocalyMenuBar
: public CMFCMenuBar
{
DECLARE_SERIAL(CLocalyMenuBar)
public:
typedef CMFCMenuBar TBase;
public:
CLocalyMenuBar();
virtual ~CLocalyMenuBar();
virtual void Serialize(CArchive& ar);
};
IMPLEMENT_SERIAL(CLocalyMenuBar, CLocalyMenuBar::TBase, VERSIONABLE_SCHEMA | 1)
CLocalyMenuBar::CLocalyMenuBar()
{}
CLocalyMenuBar::~CLocalyMenuBar()
{}
void CLocalyMenuBar::Serialize(CArchive& ar)
{
TBase::Serialize(ar);
if (ar.IsLoading()) {
LANGID nID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
ar >> nID;
if ((nID != Locality::GetCurResourceLANGID()) && CanBeRestored()) {
RestoreOriginalState();
}
}
else {
ar << Locality::GetCurResourceLANGID();
}
}
namespace Locality {
LANGID GetCurResourceLANGID()
{
// You should return current resource LANGID for your app process!
return MY_PROCESS_CURRENT_LANGID;
}
}
P.S.: 为了获得更好的结果,您应该将此类序列化代码添加到所有工具栏和可停靠栏 类.
仅删除文本并仍然保存菜单的 positions/customization...
您将不得不超越 CMFCToolbarButton class 并在您不想保存的地方使用该按钮。在 CMFCMenuBar 中,可能有一种方法可以传递用于按钮的 class 类型。那么你的按钮 class 可以有一个 BOOL 来打开或关闭保存文本。
如果无法在菜单中传递按钮 class 类型,那么您将不得不覆盖创建这些按钮的人。
与所有序列化代码一样,一个对象序列化另一个对象。
CMFCMenuBar 最终序列化 CBCGPToolbarButton::Serialize 的项目。如果您查看此代码,您会发现文本已存储并重新加载到那里...
因此,您唯一的机会就是将工具栏中的所有控件更改为您的 class。而这几乎是不可能的。更改序列化中的行为不是可行的方法。
所以从我的角度来看,除了选择不同的方法外,没有很好的答案来解决你的问题。