-
1 Attachment(s)
[RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in Windows 10?
I have been using the vb6.exe.manifest file for years since the days of Windows XP to enable visual styles and other cool ComCtl v6 features like 32-bit images with transparency in image lists in VB6 IDE. But it seems, this thing no longer works in Windows 10. At least, here is the picture I see when I upload 32-bit images with transparency into vbAccelerator ImageList control in my Windows 10:
Attachment 148411
This approach definitely worked in the previous versions of the OS like Windows 7. Have I missed something when I switched to Windows 10?
-
Re: Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in Windows 10
Do you use an external manifest file?
I believe dilettante posted somewhere that for manifest files to work on W10 they need to be embedded in the application.
-
Re: Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in Windows 10
Oh, yes, I needed to mention this explicitly - I am using an external manifest file. Can anybody point me in the right direction - how to embed this manifest into VB6.exe an easy and correct way?
-
Re: Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in Windows 10
On my W7 machine I had a modified VB6.EXE, but on W10 I just use the original version.
Don't care how it looks in the IDE and when my own applications are compiled I do embed a manifest in the EXE.
You can use mt.exe to update an executable with a manifest file.
https://stackoverflow.com/questions/...e-using-mt-exe
-
1 Attachment(s)
Re: Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in Windows 10
Tons of thanks!! The following cmd helped me to enable visual styles in VB6 IDE in Windows 10:
Quote:
"C:\Program Files (x86)\Windows Kits\10\bin\x86\mt.exe" -nologo -manifest "D:\Development\Manifests\vb6.exe.manifest" -outputresource:"C:\Program Files (x86)\Microsoft Visual Studio\VB98\VB6.EXE;#1"
The interface items and images in my image list mentioned above look as expected now:
Attachment 148413
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
External manifest can still be used, though they have been strongly discouraged for over a decade. Embedded manifests take priority over them unless a registry hack is done to reverse the change in policy since the XP days.
Most likely they are working for you, but you have run into the caching that Windows does. If you compile and run a program without a manifest, subsequently plopping one alongside the EXE will not take effect immediately.
If you want to embed manifests in VB6 it is a fairly trivial process.
Create the manifest file as either an ANSI text file that carefully avoid any non-ASCII characters OR an actual BOM-less UTF-8 file. It is worth the effort to pad the file with spaces to an exact multiple of 4 bytes, just in case you run into DWORD padding woes when you embed it.
Then add this file as a Custom resource using the IDE Resource Editor add-in. Rename it as Type #24 and ID #1 and then save the .res file.
When you compile your program, voila!
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Generally I produce res files with the ComCtl v6 manifest and other useful stuff like 48x48 modern app icons using an .rc template like this:
Quote:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
#define CONTROL_PANEL_RESOURCE_ID 123
// Icons for this application
AppIcon ICON MOVEABLE PRELOAD App.ico
// Visual styles manifest
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "XpStyles.exe.manifest"
I feed it to rc.exe:
Quote:
"C:\Program Files\Microsoft Visual Studio\VB98\Wizards\RC.EXE" /r /fo App.res App.rc
An yes, it seems external manifests still work - even for compiled VB6 executables.
Quote:
Originally Posted by
dilettante
Most likely they are working for you, but you have run into the caching that Windows does. If you compile and run a program without a manifest, subsequently plopping one alongside the EXE will not take effect immediately.
Do you know how to clear this cache to force Windows to use the external manifest file if it is provided?
And if you can answer, one more related question. As I understand, the 2010 and 2016 versions of MS Access are linked to ComCtl32 v6 using the custom resource with ID 3:
Quote:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity processorArchitecture="X86" type="win32" name="msaccess" version="14.0.7162.5001"/>
<description>Microsoft� Office Access</description>
<dependency optional="yes">
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.1.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"/>
</dependentAssembly>
</dependency>
</assembly>
However, the behavior of vbAccelerator ImageList differs in these versions. We can't use images with transparency in Access 2010, though in Access 2016 all works as expected (the property page of the ImageList OCX is also rendered correctly with visual styles in Access 2016 too). Do you know a way how to force Access 2010 to use ComCtl32 v6 in ActiveX's?
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by
dilettante
If you want to embed manifests in VB6 it is a fairly trivial process.
Create the manifest file as either an ANSI text file that carefully avoid any non-ASCII characters OR an actual BOM-less UTF-8 file. It is worth the effort to pad the file with spaces to an exact multiple of 4 bytes, just in case you run into DWORD padding woes when you embed it.
Oh, one more question regarding this. Don't we need to also call InitCommonControlsEx in addition to this, as it is stated in the article at vbAccelerator.com I referred in my very first post?
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by
wisekat
Oh, one more question regarding this. Don't we need to also call InitCommonControlsEx in addition to this, as it is stated in the article at vbAccelerator.com I referred in my very first post?
Yes, you need to
1) start your app using Sub Main
2) load shell32 prior to comctl32 (I use dil's method of calling IsUserAnAdmin to force the runtime to manage loading it)
3) call InitCommonControlsEx or InitCommonControls
Code:
Private Declare Function InitShell Lib "shell32" Alias "IsUserAnAdmin" () As Long
Private Declare Sub InitCommonControls Lib "comctl32" ()
Public Sub Main()
InitShell
InitCommonControls
Form1.Show
End Sub
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
1) start your app using Sub Main
or place it inside Form_Initialize().
Also, use Ex-version, otherwise your program will crash on XP in certain circumstances.
Code:
Private Type tagINITCOMMONCONTROLSEX
dwSize As Long
dwICC As Long
End Type
Private Declare Function InitShell Lib "shell32" Alias "IsUserAnAdmin" () As Long
Private Declare Sub InitCommonControls Lib "comctl32" ()
Private Declare Function InitCommonControlsEx Lib "comctl32.dll" (iccex As Any) As Boolean
Private Const ICC_STANDARD_CLASSES As Long = &H4000&
Private Sub Form_Initialize()
On Error Resume Next
Dim ICC As tagINITCOMMONCONTROLSEX
With ICC
.dwSize = Len(ICC)
.dwICC = ICC_STANDARD_CLASSES
End With
InitShell
lr = InitCommonControlsEx(ICC)
If lr = 0 Or Err.Number <> 0 Then
InitCommonControls ' 9x version
End If
end sub
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
I've looked into my code I have been using for years since the days of WinXP:
Code:
Private Sub Form_Initialize()
' Initialize Common Control in order to turn on
' Windows XP visual styles (if possible).
' Use only this approach in VB6 as other approaches may crash your
' compiled app which uses UserControls when you terminate the app!
m_hMod = LoadLibrary("shell32.dll")
InitCommonControls
End Sub
Private Sub Form_Unload(Cancel As Integer)
' unload shell32.dll - used only to turn on using visual styles
FreeLibrary m_hMod
End Sub
I do not use the *Ex version of InitCommonControls. Is it bad?
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
InitCommonControls() literally does nothing. It is a no-op and has been for a very long time. Calling it via VB's Declare Function causes the DLL to be loaded, something you want to have occur before anything in the runtime or an OCX tries to.
InitCommonControlsEx() does do something, but unless you are creating controls yourself by pure API calls you don't need it. The VB runtime and any OCXs for use with VB already do that themselves as required.
It is just a matter of getting the correct DLL assemblies loaded into your process.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
The manifest cache is cleared every reboot, and as space fills up over time during a Windows run.
Something that changed in Windows 10 was an enhancement that makes shutdown/startup use a hibernate process in most cases. So restarting a hibernated Windows 10 might possibly leave stuff cached.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
It's good to know Form_Initialize works because it gets called before any controls are loaded.
Also I've never seen a crash from not calling InitCommonControlsEx vs InitCommonControls?
Also if it's just a nop can we just forgo calling either?
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
The purpose is to force loading the correct assembly. You could also just make use of an explicit LoadLibrary call.
If your code ends up linking to a DLL that loaded the older assembly your process will use that old assembly. The idea is for you to get linked to the newer CC6 DLLs before linking to any other UI DLLs.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by
dilettante
The purpose is to force loading the correct assembly. You could also just make use of an explicit LoadLibrary call.
If your code ends up linking to a DLL that loaded the older assembly your process will use that old assembly. The idea is for you to get linked to the newer CC6 DLLs before linking to any other UI DLLs.
right, so i'm figuring if you trigger the loading if shell32 first, that's all that needs to happen? (I don't actually know I haven't tested this)
The controls each call InitCommonControlsEx before loading.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
I definitely had a problem with crash on XP with some versions of my programs due to the InitCommonControls preference.
For some unknown reasons I cannot reproduce it now.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
As far as I can determine you need to cause shell32.dll to load first, then comctl32.dll, and then you are ok on any version of Windows (er, from XP to present).
There have always been cases where skipping one or both DLL loads would work... until suddenly the same program just crashes. it probably has to do with what has already been loaded by other processes in the system. DLLs are shared unless isolated through one technique or another.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
There is a link within my post here:
http://www.vbforums.com/showthread.p...=1#post5177519
It has some additional background that may help explain why those DLLs need to get loaded early, for example:
Quote:
Also note, that historically some controls used to be implemented in USER32.DLL (window classes like, for example, BUTTON or EDIT), while others (known as common controls) resided in COMCTL32.DLL. This has changed with the introduction of COMCTL32.DLL version 6, and now all theming-aware controls live there.
Gotcha: The old (unthemed) implementation of standard controls is still available in USER32.DLL. If you instruct the linker to link your application with COMCTL32.DLL, it may silently omit it if the application never calls any function from it. Hence I recommend you to call InitCommonControls() when initializing the application. Otherwise, the app may be just unthemed instead of not working, using the old controls, masking perfectly the root cause of the problem.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by
dilettante
Interesting, Thanks for the info. Basically if any control is loaded that doesn't call InitCommonControls/Ex the app may end up using an older (unthemed) control.
Knowing the history - It's much better being safe than sorry.
-
1 Attachment(s)
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Basically if any control is loaded that doesn't call InitCommonControls/Ex the app may end up using an older (unthemed) control.
You can also manage "themed" of each control
Code:
Private Declare Function SetWindowTheme Lib "UxTheme.dll" (ByVal hWnd As Long, ByVal pszSubAppName As Long, ByVal pszSubIdList As Long) As Long
...
' OFF
SetWindowTheme Command1.hWnd, StrPtr(" "), StrPtr(" ")
...
' ON
SetWindowTheme Command1.hWnd, StrPtr("Explorer"), 0&
E.g., usefull in XP, where some controls is visually bugged (on frames e.t.c.).
-
2 Attachment(s)
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by
dilettante
If you want to embed manifests in VB6 it is a fairly trivial process.
Create the manifest file as either an ANSI text file that carefully avoid any non-ASCII characters OR an actual BOM-less UTF-8 file. It is worth the effort to pad the file with spaces to an exact multiple of 4 bytes, just in case you run into DWORD padding woes when you embed it.
Then add this file as a Custom resource using the IDE Resource Editor add-in. Rename it as Type #24 and ID #1 and then save the .res file.
I tried to do this for the sake of interest - to see whether I can complete this task using only VB IDE. And know what? I could not specify the type 24 AS NUMBER for the custom resource with the manifest. Can you tell me the secret how to do that? I always get a string "24" but not 24 as a number if I use the Properties dialog for that:
Attachment 148641
To compare. Here are the same resource editor windows for the resource file that specifies the manifest as a resource correctly (what I created using rc.exe):
Attachment 148643
As you can see, the Type field is even absent!
P.S. Sorry for these big screens from an UltraHD monitor :)
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
It is sort of like the confusion produced by implicit type coercion in source code expressions.
For a Custom resource the Type and Id are always String values. But because every so often you need them to be "Int Resource" format as produced by the MAKEINTRESOURCE macro, the VB Resource Editor add-in accepts a "#" prefix to tell it what to do with the numeric String following it.
In a way it is like the difference between "1/1/1990" and #1/1/1990# in VB source code.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
When you see 24 (not "24") then more than likely the resource file was created with a tool like my Manifest Creator, RC.exe, etc. As mentioned in previous two posts, if adding it with the VB resource editor, then prefix with the # sign.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by wisekat
Do you know how to clear this cache to force Windows to use the external manifest file if it is provided?
See my notes in post #3 here.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
The 24 is a MANIFEST resource type, and the VB6 add-in doesn't support adding them. The trick is to use a CUSTOM resource with ID #24, and when it saves as .RES it retains that... but by the time the EXE is created these become MANIFEST (24) type resources.
You can use ResHacker, etc. to open your compiled EXE and see that.
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Windows Vista Sxs Activation Context Cache may have helpful info:
Quote:
3. Life time of the cache
The cache is only stored in memory. The first time CreateActCtx is called, it adds an entry to the cache. Next time when the same CreateActCtx is called, the result is returned from the cache immediately, saving the expensive probing and xml parsing. The cache is lost when the machine reboots.
Quote:
5. Cache Key
The activation context stores the parsed content of all manifests in the full assembly binding closure. Ideally, the cache key should be the path of all the manifests, and their last modified time.
However, if Sxs uses that as the key to the cache, it means Sxs will have to do all the expensive probing, parsing, which makes the cache useless.
To make a compromise, Sxs chooses the path of the entry manifest of CreateActCtx and its last modified time as the key. This means, if one of its dependent assemblies has changed, it is necessary to “touch” (i.e. change the last modified time of) the entry manifest for Sxs to see the change.
Here is an example. You may have a manifest myapp.exe.manifest depending on VC80, and you decides to deploy vc80 privately. So you have a private Microsoft.VC80.CRT.manifest. In Vista, when you change Microsoft.VC80.CRT.manifest, in order for Sxs to see the change in this manifest, you need to change the last modified time of myapp.exe.manifest.
-
2 Attachment(s)
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
Quote:
Originally Posted by
dilettante
The 24 is a MANIFEST resource type, and the VB6 add-in doesn't support adding them. The trick is to use a CUSTOM resource with ID #24, and when it saves as .RES it retains that... but by the time the EXE is created these become MANIFEST (24) type resources.
You can use ResHacker, etc. to open your compiled EXE and see that.
Yes, you are right. It still looks like "#24" in the native VB6 resource editor:
Attachment 148697
But when I open this exe say in VS 2017 to see its resources, I see this:
Attachment 148699
A miracle :)
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
It's similar to how the Declare statement can be used to Alias a DLL Export by ordinal.
Code:
Private Declare Function SetWindowSubclass Lib "comctl32" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As ISubclass, ByVal dwRefData As Long) As Long
-
Re: [RESOLVED] Enabling ComCtl 6 in VB6 IDE with the manifest file no longer works in
sorry, reply to wront thread