0

Calling SetThemeAppProperties with argument which has flag STAP_ALLOW_CONTROLS unset causes CoCreateInstance for Common Dialogs (or at list File Open Dialog, CLSID_FileOpenDialog) to return error 0x80040111.

Sample code is following:

HRESULT hResult;
CComPtr< IFileOpenDialog > pFileOpenInterface1;
CComPtr< IFileOpenDialog > pFileOpenInterface2;

hResult = ::CoCreateInstance( CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &pFileOpenInterface1 ) );
::SetThemeAppProperties( 0 );
hResult = ::CoCreateInstance( CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS( &pFileOpenInterface2 ) );

To make it into running code I have created (in Visual Studio 2010 Professional) a simple Win32 GUI application and added that code to menu Help|About handler.

Why is it so and how to work around that issue?

Adam Badura
  • 5,069
  • 1
  • 35
  • 70
  • I have reposted this after lack of activity in original post at MSDN Forums (http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/f6c65f9b-f2e2-4a15-b535-3a909526e884) – Adam Badura Mar 11 '11 at 07:02
  • it might help if you explained why where and when you are calling SetThemeAppProperties – David Heffernan Mar 11 '11 at 07:05
  • In original application it is called at startup in a module providing own skinning for the application. (As usually I don't have much options with that and honestly I'm not sure why the module even calls this function.) But the issue seems more general as the same thing happens in a sample app (as described by the question). – Adam Badura Mar 11 '11 at 07:08
  • what happens if you add that flag back in? – David Heffernan Mar 11 '11 at 07:13
  • Then the second CoCreateInstance succeeds. – Adam Badura Mar 11 '11 at 10:13

3 Answers3

1

Disabling visual styles on all controls is a pretty heavy hammer. Not that surprising that the latest version of the dialogs don't support it. Try to fall back to the legacy shell dialog interface with GetOpenFileName(). Next remove the manifest entry that enables the 6.0 version of the common controls. A bit anathema to the idea of skinning perhaps.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    GetOpenFileName will use the new common item dialog. You'll have to persuade it to use the legacy dialog, for example by using one of the older versions of OPENFILENAME. – David Heffernan Mar 11 '11 at 07:49
  • @David - I'm fairly sure that's not the case. Notoriously, WPF in 3.5 gets the non-Vista enhanced dialog because it uses GetOpenFileName(). It got updated in 4.0 to use IFileDialog. – Hans Passant Mar 11 '11 at 08:02
  • 2
    @Hans `GetOpenFileName()` does give the new dialog if you use it right. So long as you don't need customisation you can get the new dialogs through the old function calls. It's only when you need customisation that you are forced into the new COM interface. – David Heffernan Mar 11 '11 at 08:10
  • The problem is that we are adding custom controls to the dialog (a check box) and this is done easily with the new COM dialog while the old dialogs required some undocumented hacking to do that (if I'm not mistaken). Also they looked ugly. – Adam Badura Mar 11 '11 at 10:15
  • 2
    @Adam Customisation of the old dialogs is documented and uses dialog templates. They are ugly though and you are right to shun them. Your problem is the skinning code. That's the boil you should lance. – David Heffernan Mar 11 '11 at 10:26
  • @David Heffernan Yes, the skinning module we use is problematic. But saddly is has to stay and now there is no one any longer to at least maintain it. Thanks for the advice with the templates. – Adam Badura Mar 11 '11 at 11:23
0

Maybe a stupid question: but do you call InitCommonControlsEx() and CoInitializeEx() before you try to use CoCreateInstance?

My guess is that your call to SetThemeAppProperties initializes COM automatically if the STAP_ALLOW_CONTROLS flag is set. But you have to do it yourself if that flag isn't set.

Stefan
  • 43,293
  • 10
  • 75
  • 117
  • I suspected it will not work but tried it non the less hoping it will. But it didn't. A clue is that the first `CoCreateInstance` call always succeeds. – Adam Badura Mar 11 '11 at 14:12
0

Using Templates to customize common dialog it's not that easy on Windows 7. First you have to force GetOpenFileName to call legacy function from DoModal which can be easily done with m_bVistaStyle = false. But than i had to deal with some assertion

ASSERT(pThreadState->m_pAlternateWndInit == NULL);
pThreadState->m_pAlternateWndInit = NULL;

I am still not sure what is it for but it can be 'work arounded' with handling WM_NCDESTROY and simply assigning

_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
if( ::IsWindow( pThreadState->m_pAlternateWndInit->m_hWnd ) )
TRACE( "scary..." );
else
pThreadState->m_pAlternateWndInit = NULL;
TRACE( "WM_NCDESTROY");
return false;

in window procedure. However what i didn't managed is to obtain selected file names from OpenFile Dialog on CDN_SELCHANGE. Sending CDM_GETFILEPATH returns only 256 chars, no matter how big is the buffer using with this msg. Maybe someone know a way to do this on windows 7?