最近用vc6.0做windows SHELL CONTEXT开发,其框架是用ATL向导生成的,并且用了MFC窗体,想使窗体以XP风格显示,在网上搜遍了所有的文章,发现采用通用的方法只能在.exe中实现,用MFC做的dll或者activex无法显示xp风格,就在快要绝望之时,看到了以下文章,请注意红色部分,作者解释的非常清楚,提出了要实现XP风格的通用方法。
Hello all,
I'm working on shell extension which uses ATL for the dialogs. I would like to force my dialog to have the XP look if appropriate. I've My questions are, has anyone heard of this "context?" If so, is there a And yup, I'm following all of the proper guidelines for picking up the XP Thanks, |
>I'm working on shell extension which uses ATL for the dialogs.
Matt,
>( I was using WTL, but I've gone back to simple ATL dialogs for now. ) >An interesting factoid about shell extensions is that if they are invoked >from Explorer the resulting dialogs to not pick up the XP look and feel. If they >are called from Windows open dialog they do pick up the "Luna" look. A bit odd, but that's life. =) This sounds similar to the situation I experienced with an MFC based I don't really understand the fix I was given from MS, but this is the class CMyContext OSVERSIONINFO info = { 0 }; bTemp = GetVersionEx(&info); HINSTANCE hinst = AfxGetInstanceHandle(); actctx.cbSize = sizeof(ACTCTX); actctx.lpSource = szModule; m_hActCtx = ::CreateActCtx(&actctx); return bRet; CMyContext() : m_ulActivationCookie(0), m_hActCtx(0) if (bRet && m_hActCtx && (INVALID_HANDLE_VALUE != ~CMyContext() private:
};
... and before you call DoModal to display your dialog in your shell
extension, create an instance of that class to run the code in that class: CMyContext con; Dave |
The ActCtx functions only exist in XP, so if you link to them statically
your DLL can't get loaded in older Windows versions. So if you want it to run on older Windows versions, you should use dynamic linking. If you don't the version check is wrong. You also make a classical mistake in the version checking: Version 6.0 is higher than 5.1. news:rcqt40159b0i6lj156nl4oalrcb96ojo4t@4ax.com...
> >I'm working on shell extension which uses ATL for the dialogs.
bit odd, but that's life. =)
> >( I was using WTL, but I've gone back to simple ATL dialogs for now. ) > >An interesting factoid about shell extensions is that if they are invoked > >from Explorer the resulting dialogs to not pick up the XP look and feel. If they > >are called from Windows open dialog they do pick up the "Luna" look. A
- 隐藏被引用文字 -
> Matt, > This sounds similar to the situation I experienced with an MFC based > I don't really understand the fix I was given from MS, but this is the > class CMyContext > OSVERSIONINFO info = { 0 }; > bTemp = GetVersionEx(&info); > HINSTANCE hinst = AfxGetInstanceHandle(); > actctx.cbSize = sizeof(ACTCTX); > actctx.lpSource = szModule; > m_hActCtx = ::CreateActCtx(&actctx); > return bRet; > CMyContext() : m_ulActivationCookie(0), m_hActCtx(0) > if (bRet && m_hActCtx && (INVALID_HANDLE_VALUE != > ~CMyContext() > private: > ... and before you call DoModal to display your dialog in your shell > CMyContext con; > Dave
您需要先
登录才能发帖。
要发帖,您需要先
加入此论坛。
请先在
订阅设置页上更新您的昵称,然后再进行发帖。
您没有发帖的权限。
|
>The ActCtx functions only exist in XP, so if you link to them statically
Hmm, my program does work on Win9x systems, so now you've said this.
>your DLL can't get loaded in older Windows versions. So if you want it to >run on older Windows versions, you should use dynamic linking. I'll have to check why - I may have it delayloaded, I can't remember.
>You also make a classical mistake in the version checking: Version 6.0 is
My fault for not checking the code MS gave me - unless they know
>higher than 5.1. something we don't with regards to Windows 6! :) Dave
您需要先
登录才能发帖。
要发帖,您需要先
加入此论坛。
请先在
订阅设置页上更新您的昵称,然后再进行发帖。
您没有发帖的权限。
|
>>The ActCtx functions only exist in XP, so if you link to them statically
In fact those functions are in kernel32 which can't be delayloaded, so
>>your DLL can't get loaded in older Windows versions. So if you want it to >>run on older Windows versions, you should use dynamic linking. >Hmm, my program does work on Win9x systems, so now you've said this. >I'll have to check why - I may have it delayloaded, I can't remember. I don't know how this works with older OS's - there must be something going on that I'm not aware of and hadn't thought to consider since it hadn't shown any problems with older OS's. Looking at my DLL with depends doesn't indicate that the AxtCtx Dave
您需要先
登录才能发帖。
要发帖,您需要先
加入此论坛。
请先在
订阅设置页上更新您的昵称,然后再进行发帖。
您没有发帖的权限。
|
I suspect that you are building with ISOLATION_AWARE_ENABLED defined to 1.
ISOLATION_AWARE_ENABLED enables wrapper functions in winbase.inl (and other files, such an Winuser.inl) for the activation context functions. These wrappers essentially use the function address returned by calling GetProcAddress on Kernel32 to call the specified function. This would allow you to call CreateActCtx, etc. and still run on pre-Windows XP systems. For example, the function that wraps CreateActCtxW (from Winbase.inl): ISOLATION_AWARE_INLINE HANDLE WINAPI IsolationAwareCreateActCtxW(PCACTCTXW
}
ISOLATION_AWARE_ENABLED also enables wrappers for functions in USER32 (such as CreateWindowEx), COMCTL32 (such as PropertySheet), and COMDLG32 (such as GetOpenFileName). These functions will activate the activation context based on the module's manifest, call the specified function, then deactivate the activation context. For example, the function that wraps CreateWindowExW (from Winuser.inl): ISOLATION_AWARE_INLINE HWND WINAPI IsolationAwareCreateWindowExW(DWORD
}
What does ISOLATION_AWARE_ENABLED have to do with creating Window controls from a shell extension? Explorer will load both the 5.82 and 6.0 versions of COMCTL32.DLL when it starts. This allows for components that rely on version 5.82 to continue to get their expected behavior while allowing other components to use 6.0 version. COMCTL32 5.82 and 6.0 implement most of the same window classes (SysListView32, SysTreeView32, etc.), while version 6.0 also implements standard window controls that are found in USER32 (Button, Edit, ComboBox, etc.) How does Windows know which version to use when calling CreateWindowEx? This is where the activation context comes into play. Windows allows for side-by-side window classes and the activation context determines which implementation of the window class to use when a window of that class is created. See "Creating Side-By-Side Window Classes" for more information. < http://msdn.microsoft.com/library/en-us/sbscs/setup/creating_side-by-... indows_classes.asp> So why doesn't defining ISOLATION_AWARE_ENABLED work with shell extensions Anyone that is creating a DLL that is loaded into a process and wants to In the example given above, a DLL calling CButton::Create should call For those interested in how this applies to the .NET Framework, the I recommend reading the "Using the Activation Context API" section in the Dave Anderson This posting is provided "AS IS" with no warranties, and confers no rights.
您需要先
登录才能发帖。
要发帖,您需要先
加入此论坛。
请先在
订阅设置页上更新您的昵称,然后再进行发帖。
您没有发帖的权限。
|
>I suspect that you are building with ISOLATION_AWARE_ENABLED defined to 1.
You're right, I am. Thanks for the explanation Dave, that's certainly
helped clarify what's going on and how it works. There just aren't enough hours in the day to find out about all the Cheers |
另外,根据IsolationAwarePrivateT_SqbjaYRiRY 这个关键字,又搜到了这篇文章,地址:http://blog.csdn.net/zhangym365/article/details/6295127,估计该方法也是来自于以上红色部分的启发。
网上基于vc6.0的activex增加 xp 风格(theme)都不起作用(其实已经实现了,只是大多数程序都是用mfc的创建用户控件函数所以还是不起作用),
如何定义XP风格的文章很多,可参见http://blog.csdn.net/greenerycn/article/details/3150247,但是纯粹采用这个办法采用MFC的Activex或者DLL项目根本就没有反应。原因如下:
原来是因为定义了#define ISOLATION_AWARE_ENABLED 1关键字后,所有的创建函数转到WinBase.Inl中,
通过 application and hosted component来实现,但是mfc中的实现并没有转
,所以只要在调用前稍作修改就能真正实现vc6的 activex控件xp风格了。
所以通过这个方法,用vc6编写的activex IE插件 动态库等应该都能实现xp风格了。
关键代码:
BOOL fResult = FALSE;
ULONG_PTR ulpCookie = 0;
const BOOL fActivateActCtxSuccess = IsolationAwarePrivateG_FqbjaLEiEL || IsolationAwarePrivatenCgIiAgEzlnCgpgk(&ulpCookie);
if (!fActivateActCtxSuccess)
return fResult;
__try
{
//fResult = GetClassInfoExW(unnamed1,unnamed2,unnamed3);
CRect rect(0,0,200,20);
button.Create("test",WS_VISIBLE,rect,this,12); //这里是真正的mfc创建控件的调用
}
__finally
{
if (!IsolationAwarePrivateG_FqbjaLEiEL)
{
const BOOL fPreserveLastError = (fResult == FALSE);
const DWORD dwLastError = fPreserveLastError ? GetLastError() : NO_ERROR;
(void)IsolationAwareDeactivateActCtx(0, ulpCookie);
if (fPreserveLastError)
SetLastError(dwLastError);
}
}
return fResult;
朋友做的封装,可以参考:
class CXP
{
public:
CXP() {
m_ulpCookie = 0;
m_bCtxSuccess = IsolationAwarePrivateG_FqbjaLEiEL || IsolationAwarePrivatenCgIiAgEzlnCgpgk(&m_ulpCookie);
}
virtual ~CXP() {
if(m_bCtxSuccess) IsolationAwareDeactivateActCtx(0, m_ulpCookie);
}
ULONG_PTR m_ulpCookie;
BOOL m_bCtxSuccess;
};
CDlg_Test dlg;
{
CXP XP;
if(dlg.DoModal()==IDCANCEL) return FALSE;
}
根据以上两篇文章,总结出在dll或activex里,如果采用MFC来创建出具有xp风格的窗体,需要经过以下步骤:
1.创建mydll.manifest资源文件,该文件内容为
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="XP style manifest"
processorArchitecture="x86"
version="1.0.0.0"
type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
2.在vc6.0的资源编辑器中,importt一个类型为24,ID为2的资源,文件指向mydll.manifest.
3.在stdafx.h中,在所有的#include语句前加入#define ISOLATION_AWARE_ENABLED 1
4.创建一个类:
class CXP
{
public:
CXP() {
m_ulpCookie = 0;
m_bCtxSuccess = IsolationAwarePrivateG_FqbjaLEiEL || IsolationAwarePrivatenCgIiAgEzlnCgpgk(&m_ulpCookie);
}
virtual ~CXP() {
if(m_bCtxSuccess) IsolationAwareDeactivateActCtx(0, m_ulpCookie);
}
ULONG_PTR m_ulpCookie;
BOOL m_bCtxSuccess;
};
5.你的dll或activex中,在每个要创建的窗体前加上CXP XP,然后再调用创建窗体的语句。