CMyPrintDialog::OnInitDialog() is not called in IE10 - c++

I have a class named CMyPrintDialog derived from CPrintDialog of MFC. It's used as an ActiveX in IE, and the project is linked to MFC statically. It works well in IE8 for many years.
But the same binary of the project doesn't work well on IE10. The print dialog could pop up, but unfortunately its OnInitDialog is never called and causes problems.
The strange thing is that if I attach the VS debugger to IE, OnInitDialog will be called correctly and the customized print dialog works well.
Seems Microsoft has change something and causes the problem.
I found a similar link but it doesn't work.
Thanks a million for any ideas.

The issue is caused by IE's new feature after IE9 - "Hang Resistance". We can avoid the issue by disabling the new feature: Set below value as 0, and close all IE windows. HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\ Type: REG_DWORD Name: HangRecovery Value: 0

I am not getting your point exactly you want to say, Consider CPrintDialog crash your application with IE10.What is you need to do is,
Set up the message hook function, _AfxCommDlgProc(), in the constructor of your
CPrintDialog-derived class as shown below:
// CMyPrintDialog is a CPrintDialog-derived class.
CMyPrintDialog::CMyPrintDialog(DWORD dwFlags)
: CPrintDialog(FALSE,dwFlags)
{
//{{AFX_DATA_INIT(CMyPrintDialog)
//}}AFX_DATA_INIT
// MFCBUG: MFC 6.0 doesn't set the message hook!
m_pd.Flags |= PD_ENABLEPRINTHOOK | PD_ENABLESETUPHOOK;
// _AfxCommDlgProc is exported from static MFC libraries
m_pd.lpfnPrintHook = _AfxCommDlgProc;
m_pd.lpfnSetupHook = _AfxCommDlgProc;
}

Related

How to get CDocument for derived CMFCShellTreeCtl on an Outlook Style MFC program?

I am new to MFC and have built an "outlook" style MFC app using the wizard. I've extended the CMFCShellTreetCtrl using CMyShellTreeCtrl and had data member variables and all was working fine. Now I want to move the data over to the CDocument class. Since there is several accesses to the data as each item is clicked or enumerated, I thought I would create a member variable m_pDoc to access the public variables in the CDocument. The problem I'm having, I can't find where to get the CDocument as it appears it's not setup when the trees OnCreate is called. That is in OnCreate
CWnd* pWndMain = AfxGetMainWnd();
ASSERT(pWndMain);
ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)) && !pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an SDI app.
m_pDoc = (CMyDoc*) ((CFrameWnd*)pWndMain)->GetActiveDocument();
returns NULL in m_pDoc and if I tried in an AfterCreate() (which is called after CreateOutlookBar) it's too late as m_pDoc is already being used and get a crash.
// Create and setup "Outlook" navigation bar:
if (!CreateOutlookBar(m_wndNavigationBar, ID_VIEW_NAVIGATION, m_wndTree, m_wndCalendar, 250))
{
TRACE0("Failed to create navigation pane\n");
return -1; // fail to create
}
m_wndTree.AfterCreate();
Any Ideas?
TIA!!
I came up with the following but I'm not sure if this is the proper way. Again, I'm new to MFC (I always have used Win32 directly). This works so it's AN answer, but is it THE correct answer?
POSITION docpos = AfxGetApp()->GetFirstDocTemplatePosition();
CDocTemplate *doctemplate = AfxGetApp()->GetNextDocTemplate(docpos);
docpos=doctemplate->GetFirstDocPosition();
m_pDoc = (CMyDoc*)doctemplate->GetNextDoc(docpos);
ASSERT(m_pDoc);
ASSERT(m_pDoc->IsKindOf(RUNTIME_CLASS(CMyDoc)));
TIA!!

Handle to window for PropertySheet

The below code, creating a Property Sheet, works without problem in an Application File.
.......
CProp_Sheet Pr_Sheet(_T("PS"));
CPr_Page_1 Pr_Page_1;
CPr_Page_2 Pr_Page_2;
Pr_Sheet.AddPage(&Pr_Page_1);
Pr_Sheet.AddPage(&Pr_Page_2);
m_pMainWnd = &Pr_Sheet;
int nResponse = Pr_Sheet.DoModal();
However, when I put the same code in a DLL, and call it from a menu item in another Application, m_pMainWnd cannot be used (the menu in the Application is to remain visible behind the Property Sheet).
I have tried to create a handle
CWnd* m_pWnd = &Pr_Sheet;
and use m_pWnd in the CProp_Sheet constructor, but although compiling correctly at run time failure always occurs at
CProp_Sheet::OnInitDialog().
Thanks in advance for any comments.

CWinApp OpenDocumentFile "unsupported operation" error

Problem
I'm trying to open an MFC program that reads a Microsoft Access database (.mdb) and allows the user to view or modify the data. This is an existing program (and source code) given to me by a group in another lab where the program opens and works just fine.
In our lab, I have yet to see it load properly. When run, it pops up a dialog box that says, "Attempted an unsupported operation". Windows then offers me a chance to debug and such before it crashes.
Environment
In the other lab, they use Windows 7 and Microsoft Office 2010, and it works.
In our lab, I've tried Windows 7 with Office 2013 and Windows XP with Office 2010. The latter crashes without giving me the dialog box. I don't know if we have a Win7/MSO2010 machine.
The Function
I have the source code for the program. The solution file implies it was last developed in VS2010, which the computers I tested on had installed as well. Running it out of Visual Studio 2010 or straight from the executable yields the same results.
I have added additional debug dialog boxes to the code that narrow down the problem to this function call, which the code never gets past:
CwinApp:OpenDocumentFile(LPCTSTR lpszPathName)
The single string passed into the function is a path and filename for the MS Access database to be opened. It exists in a temporary directory created by another program. This is on a drive other than C, though I've tested some there, as well. Problems with programs related to this one often stem from files with "read only" status, but I continually check the temporary files created, and they are write-able.
Documentation
I found this information titled "Breaking Changes in Visual C++" for VS2010 through another SO question:
A new virtual function was added to the CDocTemplate class. This new virtual function is CDocTemplate::OpenDocumentFile. The previous version of OpenDocumentFile had two parameters. The new version has three parameters. To support the restart manager, any class derived from CDocTemplate must implement the version that has three parameters. For more information about the function, see CDocTemplate::OpenDocumentFile. The new parameter is bAddToMRU.
Code
I feel this might be the answer! But I don't have a strong idea of exactly what to change to get this to work. Here's where I stopped:
Program.cpp
CDocument* ProgramApp::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToLRU, BOOL bMakeVisible)
{
// Add specialized code here and/or call base class
// Debug messages added
CDocument* tempDoc;
AfxMessageBox(lpszFileName);
tempDoc = CWinApp::OpenDocumentFile(lpszFileName, bAddToMRU);
AfxMessageBox("Opened database!");
return tempDoc;
}
Program.h
class ProgramApp : public CWinApp
{
public:
...
virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU, BOOL bMakeVisible);
afxwin.h
class CWinApp : public CWinThread
{
...
virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName);
virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU);
Changing the Program.cpp call to be from a "Template" class caused errors, but I wouldn't be surprised if that's towards the answer. This solution looks similar, but I'm not sure exactly what to do.
My hope is that this problem has a simple solution that someone more knowledgeable can give me. I would be much appreciative, and additional context would help a lot.
Edit: Debugging
I drilled down into the Windows code to see what was precisely going wrong. It seemed too dense to understand, but a coworker and I may have clues based on it. The failure message happens here:
dlgdata.cpp
// Could be a windowless OCX
pSite = m_pDlgWnd->GetOldControlSite(nIDC);
if (pSite == NULL)
{
TRACE(traceAppMsg, 0, "Error: no data exchange control with ID 0x%04x.\n", nIDC);
ASSERT(FALSE);
AfxThrowNotSupportedException();
}
...Although we are seeing debugger issues here:
occcont.cpp
COleControlSiteOrWnd *pemp = new COleControlSiteOrWnd(hwndCtrl, pOccDlgInfo->m_pItemInfo[i].bAutoRadioButton);
ASSERT(IsWindow(pTemp->m_hWnd));
if (IsWindow(pTemp->m_hWnd))
{
hwndStart = pTemp->m_hWnd;
...
My coworker believes this could have little to do with the opening of this document as I suspected and more to do with objects/controls we don't have on our lab computers trying to be used for the program.
I have faced the same problem in opendocumentfile(), there was a control in CFormView class which i was not using so i commented it out but forget to delete from .rc file. Once i remove the control entry from .rc file the problem disappear.
there should be no control variable uninitialize , please check that also

windows 8 IShellIconOverlayIdentifier shell extension not working properly

I have an application where i want to have icon overlays for specific files and folders.
For this purpose i've written a shell extension that implements the IShellIconOverlayIdentifier interface. Its written in c++ / Qt (activeqt) as a dll that connects to the application in question using tcp to query the application to decide wether to show the icon overlay or not. Its buildt much the same way this is.
It works fine in XP/Vista/7 but it wont work in windows 8.
In windows 8 the dll is loaded. I can see it in process explorer and also as a part of debugging it also logs output to a file so i can see whats happening and infer whats not.
Using ShellExView i can also see thats its registered, not disabled and in general everything looks ok.
The class declaration looks more or less like this:
class Q_DECL_EXPORT OverlayClass :
public QAxAggregated,
public IShellIconOverlayIdentifier{
public:
// Implements IUnknown
QAXAGG_IUNKNOWN;
JShellOverlayWorking();
// Implements IShellIconOverlayIdentifier
STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile, int cchMax, int *pIndex, DWORD* pdwFlags);
STDMETHOD(GetPriority)(int* pPriority);
STDMETHOD(IsMemberOf)(LPCWSTR pwszPath, DWORD dwAttrib);
//pure virtual from QAxAggregated
long queryInterface(const QUuid &iid, void**iface);
};
Whats happens on XP/Vista/7 :
that explorer on load first call queryInterface() and gets an S_OK if iid == IID_IShellIconOverlayIdentifier and E_NOINTERFACE for all other iid's
and then it goes on to call GetOverlayInfo() to initialize stuff. Get the icon file path etc.
And then as the shell needs to it calls IsMemberOf() to see if it should display the icon for a file or folder.
What happens on windows 8 :
that explorer on load calls queryInterface() and gets an S_OK when iid == IID_IShellIconOverlayIdentifier and E_NOINTERFACE for all other iid's
And nothing else. queryInterface() is getting called, but after that nothing happens. I can see my application connecting successfully to the tcp socket created by the shell extension and IPC is working( i can send data back and forth between the application and the dll, but again. Nothing else happens. Explorer is not using the implemented interface.
The dll is registered using:
regsvr32.exe shellext.dll
and the registry key below is also added
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\Shellextname ( value = CSLID )
for testing on windows 8 i've also added the following key to
HKCU\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved
with my shell extensions CSLID as the name and data = Shellextname ( as above in the previous key) though this doesn't seem to matter on XP/Vista/7 so i'm guessing its inconsequential here as well.
Again, this works on every windows( >= xp) except windows 8.
What am i missing? Where do i go from here to find out?
It seems the problem was that the registry key
HKEY_CLASSES_ROOT\CLSID\{myguid}\InprocServer32
ThreadingModel = Apartment
as specified here was not set by regsvr32.exe. I guess previous windows versions ignored this if it wasn't set, but windows 8 required it. Setting it manually worked.

ActiveX plugin causes ASSERT to fail on application exit in VS2008

My MFC application using the "ESRI MapObjects LT2" ActiveX plugin throws an ASSERT at me when closing it.
The error occurs in cmdtarg.cpp:
CCmdTarget::~CCmdTarget()
{
#ifndef _AFX_NO_OLE_SUPPORT
if (m_xDispatch.m_vtbl != 0)
((COleDispatchImpl*)&m_xDispatch)->Disconnect();
ASSERT(m_dwRef <= 1); //<--- Fails because m_dwRef is 3
#endif
m_pModuleState = NULL;
}
I built the (native C++) application with VC9.
When I compile the application with VC6, it behaves nicely.
What could be the reason for this?
That looks like a reference count. Could this "target" be referenced by something else, something that's not releasing it?
You can trace the Addref and Release calls defining _ATL_DEBUG_INTERFACES
from http://msdn.microsoft.com/en-us/library/sycfy8ec(VS.80).aspx
_ATL_DEBUG_INTERFACES
Define this macro before including any ATL header files to trace all AddRef and Release calls on your components' interfaces to the output window.
Using _ATL_DEBUG_INTERFACES did not yield any additional output...
I defined it on the first line of stdafx.h, directly after #pragma once so I guess this is early enough.
Maybe the reason is how I am using the ActiveX control:
I'm not calling AddRef() or Release() by myself.
The MapObjects Installer comes with sample code with lots of wrapper classes which must have been generated by VC6 or something earlier.
I tried to generate wrapper classes myself with VC9 but there occured errors which I wasn't able to fix.
I use the control by letting one of my windows have a member of type CMap1 (derived from CWnd), which is one of those generated wrapper classes. In CMyWnd::OnCreate() I also call CMap1::Create() and that's it, I'm finished: I can add a layer and the control displays a world map.
I have pretty much no idea what the reference-count stuff is about as I have not added or released any references. At least not knowingly...
The control is pretty old: The .OCX file has the year 2000 in its version information.
It's also not officially supported anymore but I don't have any substitue.
The following solved it for me:
In the window that contains the control, add an OnDestroy() handler:
void CMyWnd::OnDestroy()
{
// Apparently we have to disconnect the (ActiveX) Map control manually
// with this undocumented method.
COleControlSite* pSite = GetOleControlSite(MY_DIALOG_CONTROL_ID);
if(NULL != pSite)
{
pSite->ExternalDisconnect();
}
CWnd::OnDestroy();
}