Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to refer to an App variable from Dialog class? 2

Status
Not open for further replies.

skwrox

Programmer
Oct 9, 2001
4
US
I need to refer to, and set an Application variable from my Dialog class. I tried this:

CMyAppApp * pApp = AfxGetApp();

The error says it needs reinterpret_cast, C-style cast or function-style cast. So I tried:

CMyAppApp * pApp = dynamic_cast<CMyAppApp *>(AfxGetApp());

I still get a warning saying 'dynamic_cast' used on polymorphic type 'class CWinApp' with /GR-; unpredictable behavior may result. The app. crashes at that line.

What's wrong? How else can I refer to an App. class variable? Someone please explain?

TIA
Sudhir
 
Just use a static_cast operator.

So
CMyAppApp *pApp = static_cast<CMyAppApp *>(AfxGetApp());

or even just

CMyAppApp *pApp = (CMyAppApp *)AfxGetApp();
 
reinterpret_cast<>() would be really correct since this is not a type safe conversion, although static_cast<>() is accepted by VC++. For type safety you should use dynamic-Cast<>(), but then you must activate the /GR switch for RTTI (the message is really confusing - it means the /GR switch is not set!)

OTOH, why not just use AfxGetApp()-> wherever you need it? The following from MSDN might also interest you:


Q I want to use an enhanced CWinApp object in my apps so my derived CMyWinApp class will not only override the virtual CWinApp methods, but also declare and define a couple of additional members and methods. I still want to use AfxGetApp to retrieve a pointer to my app object. Afx-GetApp seems to use a hardcoded memory location to re-trieve the app object. Do you consider it safe to cast the pointer obtained from AfxGetApp to my derived CMyWinApp type? Also, why is the CWinApp object always allocated NEAR (CMyWinApp NEAR theApp)?
Hermann Pallasch

A If you look at the definition of AfxGetApp in afxwin1.inl, you'll see that it expands to afxCurrentWinApp:

inline CWinApp* AFXAPI AfxGetApp()
{
return afxCurrentWinApp;
}

In earlier versions of MFC, afxCurrentWinApp was an extern pointer, but currently (MFC 4.x) afxCurrentWinApp is #defined in afxwin.h as:

#define afxCurrentWinApp
AfxGetModuleState()->m_pCurrentWinApp

AfxGetModuleState returns a pointer to thread-local storage for a struct called AFX_MODULE_STATE that stores information about the current running module, including a pointer to the application object. The reason for all this subterfuge has to do with DLLs. In a normal (non-DLL) source file, you could just write

theApp.Mumble();

to access the Mumble member of the global object theApp. But if theApp lives in a DLL, this symbol is undefined in the non-DLL file. If theApp is defined in the DLL, it's the DLL's object, not the application's. Remember, functions in a DLL are like subroutines of some app that doesn't exist (isn't linked) until run time. How can an MFC extension DLL get the application object (theApp) of the application calling it?

This is where the module state comes in. Module states deserve more explanation than I can give in a short column, so I'll leave it for another day. The short story is this: MFC maintains something called the module state, which contains pointers to application-wide globals such as the current CWinApp. Each entry point in a DLL or OLE control is responsible for initializing the state through either AFX_MANAGE_STATE or METHOD_PROLOGUE. For more information, read MFC tech note #58.

Based on your question, it sounds like you're not writing a DLL, but just a normal EXE. In that case, the simplest thing to do is declare your application object in some global header file that gets #included everywhere, say myapp.h.

class CMyWinApp : public CWinApp {
// normal class declaration
.
.
.
};

// Declare global app object
extern MyWinApp theApp;

With the extern declaration as I've shown it, you can write

theApp.SomeFunction();

in any CPP file that #includes myapp.h. There's nothing wrong with using the App directly. In fact, it's a faster way of getting the app than AfxGetApp because you don't have to call a function or chase all the state pointers. Since theApp is declared as CMyWinApp, you don't have to cast.

If your app is composed of a main EXE with one or more DLLs, then this won't work in the DLLs. If this is the case, I suggest you write a function similar to AfxGetApp.

inline CMyWinApp* GetMyApp()
{
ASSERT_KINDOF(AfxGetApp(), pApp);
return (CMyWinApp*)AfxGetApp();
}

GetMyApp returns the same pointer as AfxGetApp, but casts to CMyWinApp. The ASSERT checks that the application using your DLL is in fact a CMyWinApp and not some other kind of app. The ASSERT will not be compiled in a release build, so when you get right down to it, GetMy-App is exactly the same thing as AfxGetApp; in a release build it generates exactly the same amount of code as calling AfxGetApp.

As for the second part of your question, theApp is declared NEAR because of an artifact from 16-bit days: to be more efficient, AppWizard generated code that defined theApp as NEAR data. In Win32¨, NEAR and FAR have no meaning since there's only one flat 32-bit memory model (hallelujah). In fact, under Win32, NEAR and FAR are #defined in windef.h to near and far, which are in turn #defined to nothing.

By the way, there's no reason you have to call your global application object theApp. You can call it myApp, or YourApp, or theOneAndOnlyAppJack.
:) Hope that this helped! :)
 
There is a simpler way:
In your .cpp file add this:

#include &quot;MyAppApp.h&quot;
extern CMyAppApp theApp;

The use it like:
theApp.MemeberFunction()

HTH,

s-)

Blessed is he who in the name of justice and goodwill, sheperds the weak through the valley of darkness...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top