How to send a user-defined message with SendMessage, PostMessage or PostThreadMessage






4.11/5 (18 votes)
Jan 20, 2004
18 min read

220526

2631
How to send a user-defined message with SendMessage, PostMessage or PostThreadMessage
Introduction
If you try to send a user-defined message with SendMessage
,
PostMessage
or PostThreadMessage
, you will
unfortunately recognize, that some messages won't work and a direct "normal"
access of the desired member-function from different classes, created by the app
wizard, seems not to be possible.
This article is written to show how to access a member-function of any class
by a member-function of any other class. To send a message means nothing
different, than to call indirectly another member-function instead of a direct
call. But a direct call of a member-function is better, especially if you have
to use a message of type PostThreadMessage
. The reason for this
is described below in this article.
I named my project Test_SDI and the application wizard of VC++ 5 creates the derived classes with the following names:
Base Class Derived Class
---------------------------------
CFrameWnd CMainFrame
CWinApp CTest_SDIApp
CDocument CTest_SDIDoc
CView CTest_SDIView
A self-implemented class used in the source code of the project called
CTestMessage
is not derived from a MFC-class.
In which cases can you use SendMessage or PostMessage?
The supposition, that the destination class can receive a message of type
SendMessage
or PostMessage
is, to be a
member-function of the class CWnd
or its derived class(es). In my
project only the classes CMainFrame
and
CTest_SDIView
, created by the app wizard, can receive a message
of type SendMessage
or PostMessage
.
If you try to create your own class, derived from CWnd
,
messages won't be received by the member-function of your own class, because the
additional condition for receiving a message is, that the receiving class is
implemented into the message-system of the MFC-structure, created by the app
wizard. And your self created class, even if derived from class
CWnd
is NOT implemented into the message-system of the
MFC-structure. This second condition is not mentioned in the
online-documentation of VC5.
But in most cases this is not a disadvantage, because there is the
possibility of the direct call of a member-function. And if it is important for
you, that your own class can get window-messages, then there are two choices.
Subclass a window, using CWnd::SubclassWindow
(for more
information, have a look at article Windows Message Handling - Part 4 written
by Daniel Kopitchinski ) or make a workaround. Realize it by creating your own
member-function of class CMainFrame
(derived from
CFrameWnd
) or CTest_SDIView
(derived from
CView
), which can receive windows-messages and user-defined
messages (using SendMessage
or PostMessage
) and
then call the member-function of your own class directly from this
member-function of class CMainFrame
or
CTest_SDIView
.
The classes CWinApp
, CDocument
and their
derivations are not derived from class CWnd or its derived class(es) and
therefore they are NOT able to receive messages of type
SendMessage
or PostMessage
.
In which cases you can (but nevertheless never should) use PostThreadMessage?
The supposition, that the destination class can receive a message of type
PostThreadMessage
is, to be a member-function of the class
CWinThread
or its derived class(es). In my project the class
CTest_SDIApp
, created by the app wizard, can receive a message of
type PostThreadMessage
.
Using the built-in help of VC++ 5, you get no information about an extreme
important disadvantage of PostThreadMessage
. The message, sent by
PostThreadMessage
, get lost or could get lost, if one of the
conditions, mentioned in article "ID: Q183116, PRB: PostThreadMessage
Messages Lost When Posted to UI Thread" (refer to the MSDN Library on CD
or on Microsoft's MSDN-Homepage:
Messages sent to a UI thread through PostThreadMessage
ARE LOST
if the messages are posted while the user is manipulating a window owned by the
thread. Messages MIGHT BE LOST if they are sent while the user moves or resizes
the window or if the window is a modal dialog box.) is fulfilled !!
But why using this very unsafe way, if there's a safe solution ?
The safe way doesn't use PostThreadMessage
, but it calls a
function delivering a pointer to the class CTest_SDIApp
(created
by the application wizard), which is derived from CWinApp
and has
no limitations !!
The classes CFrameWnd
, CView
and
CDocument
and their derivations are not derived from class
CWinThread
or its derived class(es) and therefore it is
impossible for the member-functions of CFrameWnd
,
CView
, CDocument
and their derivations to receive
messages of type PostThreadMessage
.
Another point of view on how to call members:
How to call a member of class CMainFrame derived from CFrameWnd:
Every member-function of every class, even NON-MFC-classes, can send a
message of type SendMessage
or PostMessage
to
CMainFrame
using AfxGetMainWnd()
, which calls a
member-function of CMainFrame
. A sample of code is shown in
3.1
How to call a member of class CTest_SDIView derived from CView:
Only messages of type SendMessage
or
PostMessage
sent by a member of CMainFrame
can be
received by class CTest_SDIView
. A message of type
SendMessage
or PostMessage
sent by all other
classes cannot be received by the members of class CTest_SDIView
.
In the case of all other classes, including non-MFC-classes, use the
self-implemented function GetView
described in the Microsoft MSDN
article ID: Q108587. A sample of code is shown in 4.1 or 4.2.
With the self-implemented function GetView
every class can
send a message of type SendMessage
or PostMessage
.
But a direct call of a member of CTest_SDIView
, which is also
possible, using GetView()
probably needs less overhead of code
(and time) than using the message-system of the MFC-structure.
How to call a member of class CTest_SDIApp derived from CWinApp
Every member-function of every class, even NON-MFC-classes, can send a
message of type PostThreadMessage
to CTest_SDIApp
using AfxGetApp()
, which calls a member-function of
CTest_SDIApp
. But there are important limitations (Microsoft
article ID: Q183116), so use the self-implemented function
GetApp
(the principles are described in the Microsoft MSDN
article ID: Q108587) for all classes, including non-MFC-classes, which want to
call a member of CTest_SDIApp
. A sample of code is shown in 2.1
or 2.2.
How to call a member of class CTest_SDIDoc derived from CDocument:
None of the user-defined messages (SendMessage
,
PostMessage
or PostThreadMessage
) can be received
by members of class CTest_SDIDoc
. If a member of class
CTest_SDIView
want to call a member of class
CTest_SDIDoc
, then use the pointer supported by the code created
from the application wizard. In the case of all other classes, including
non-MFC-classes, use the self-implemented function GetDoc
described in the Microsoft MSDN article ID: Q108587. A sample of code is shown
in 1.1 or 1.2.
How to call a member of class CMyOwnClass, not derived from any MFC-class:
The members of your own class cannot receive any kind of message, even if
your own class is derived from class CWnd
. If the members of your
own class should be called from another class from another file of your project,
your own class must be declared as extern
. Then every class can
access the members of CMyOwnClass
.
General advice
If you define your user-defined message WM_MyOwnMessage
, it is
not recommended to use WM_USER
. In the beginning of the Windows
programming it was recommended to define user-defined messages using the symbol
WM_USER
. But there were too many problems with
WM_USER
-based symbols conflicting with messages that Microsoft was
using. Nowadays use WM_APP
.
Example: #define WM_MyOwnMessage (WM_APP + 1)
This article refers to SDI-applications (SDI = Single Document Interface). For MDI-apps (MDI = Multiple Document Interface) please have a look at Microsoft MSDN article ID: Q108587, HOWTO: Get Current CDocument or CView from Anywhere
The chapters below often show several ways for a solution, but only one solution is active at a time and not every solution is implemented within the source code of the project. If you want to test the other solutions described, activate them, while erasing the two slashes in front of every line of code.
The following lines shows which cases of calling members of other classes are treated. The calls of the members will be executed in the sequence within the compiled source code of the project as listed below.
Overview
- A member of class
CTest_SDIApp
(base:CWinApp
) calls a member of classCTest_SDIDoc
base:CDocument
) - A member of class
CTest_SDIDoc
(base:CDocument
) calls a member of classCTest_SDIApp
(base:CWinApp
) - A member of class
CTest_SDIDoc
(base:CDocument
) calls a member of classCMainFrame
(base:CFrameWnd
) - A member of class
CTest_SDIDoc
(base:CDocument
) calls a member of classCTest_SDIView
(base:CView
) - A member of class
CTest_SDIApp
(base:CWinApp
) calls a member of classCMainFrame
(base:CFrameWnd
) - A member of class
CMainFrame
(base:CFrameWnd
) calls a member of classCTest_SDIApp
(base:CWinApp
) - A member of class
CMainFrame
(base:CFrameWnd
) calls a member of classCTest_SDIDoc
(base:CDocument
) - A member of class
CMainFrame
(base:CFrameWnd
) calls a member of classCTest_SDIView
(base:CView
) - A member of class
CTest_SDIApp
(base:CWinApp
) calls a member of classCTest_SDIView
(base:CView
) - A member of class
CTest_SDIView
(base:CView
) calls a member of classCTest_SDIApp
(base:CWinApp
) - A member of class
CTest_SDIView
(base:CView
) calls a member of classCMainFrame
(base:CFrameWnd
) - A member of class
CTest_SDIView
(base:CView
) calls a member of classCTest_SDIDoc
(base:CDocument
) - A member of class
CTest_SDIApp
(base:CWinApp
) calls a member of classCTestMessage
(no base class) - A member of class
CTestMessage
(no base class) calls a member of classCTest_SDIApp
(base:CWinApp
) - A member of class
CTestMessage
(no base class) calls a member of classCTest_SDIDoc
(base:CDocument
) - A member of class
CTestMessage
(no base class) calls a member of classCMainFrame
(base:CFrameWnd
) - A member of class
CTestMessage
(no base class) calls a member of classCTest_SDIView
(base:CView
)
Detailed description
1. A member of class CTest_SDIApp
(base:
CWinApp
) calls a member of class CTest_SDIDoc
(base: CDocument
)
There are two ways to make a call:
1.1 A member-function of class CTest_SDIApp
(a derivation of
CWinApp
) calls a member-function of CTest_SDIDoc
using a pointer delivered by a manually implemented member-function with the
name CTest_SDIDoc::GetDoc()
(refer to Microsoft MSDN article ID:
Q108587). This version is easy to implement.
// Header-File Test_SDIDoc.h class CTest_SDIDoc : public CDocument { public: static CTest_SDIDoc *GetDoc(); // GetDoc() is necessary to //get the pointer anywhere else void AppToDoc() ; // Test-function that will be called } // Implementation-File Test_SDIDoc.cpp CTest_SDIDoc *CTest_SDIDoc::GetDoc() // GetDoc() is //necessary to get the pointer anywhere else { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTest_SDIDoc*) pFrame->GetActiveDocument(); } void CTest_SDIDoc::AppToDoc() // Test-function that will be called { AfxMessageBox(CTest_SDIDoc::AppToDoc was called ...) ; } // Implementation-File Test_SDI.cpp #include Test_SDIDoc.h // If you forget to include //Test_SDIDoc.h, then the members of // CTest_SDIApp don't know class CTest_SDIDoc //and its member-functions BOOL CTest_SDIApp::InitInstance() // The function //InitInstance() calls AppToDoc() { AfxMessageBox( CTest_SDIApp::InitInstance was called and calls AppToDoc()) ; CTest_SDIDoc::GetDoc()->AppToDoc() ; }
1.2 A member-function of class CTest_SDIApp
(a derivation of
CWinApp
) sends a message to CMainFrame
and calls a
self-written member-function of class CMainFrame
, which sends a
message to CTest_SDIView
(a derivation of CView
).
The pointer of the document, available in CTest_SDIView
, allows
to access the desired member-function of class CTest_SDIDoc
. This
version is more conventional, but there's more work to implement it.
// Implementation-File Test_SDI.cpp BOOL CTest_SDIApp::InitInstance() // InitInstance is //created by the app wizard { AfxMessageBox(CTest_SDIApp::InitInstance was called ...) ; AfxGetMainWnd()->SendMessage(WM_AppToFrameToDoc) ; // First step is to send a // message to a own member-function of class CMainFrame } // Header-File MainFrm.h #define WM_AppToFrameToDoc WM_APP+30 class CMainFrame : public CFrameWnd { public: void AppToFrameToDoc() ; } // Implementation-File MainFrm.cpp BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) //}}AFX_MSG_MAP ON_MESSAGE(WM_AppToFrameToDoc, AppToFrameToDoc) END_MESSAGE_MAP() void CMainFrame::AppToFrameToDoc() { AfxMessageBox(CMainFrame::AppToFrameToDoc was called and calls FrameToViewToDoc()) ; CView *pView = GetActiveView(); if (pView == NULL) { // error handling routine // Fail if view is of wrong kind // (this could occur with splitter windows, or additional // views on a single document } pView->SendMessage(WM_FrameToViewToDoc); // Second step is to send a // message to a own member-function of class CTest_SDIView } // Header-File Test_SDIView.h #define WM_FrameToViewToDoc WM_APP+31 class CTest_SDIView : public CView // Original { public: void FrameToViewToDoc() ; } // Implementation-File Test_SDIView.cpp BEGIN_MESSAGE_MAP(CTest_SDIView, CView) //{{AFX_MSG_MAP(CTest_SDIView) //}}AFX_MSG_MAP ON_MESSAGE(WM_FrameToViewToDoc, FrameToViewToDoc) END_MESSAGE_MAP() void CTest_SDIView::FrameToViewToDoc() { AfxMessageBox(CTest_SDIView::FrameToViewToDoc was called and calls AppToDoc()) ; CTest_SDIDoc* pDoc = GetDocument(); pDoc->AppToDoc() ; // Third step makes a direct //call of member-function // AppToDoc() of class CTest_SDIDoc } // Header-File Test_SDIDoc.h class CTest_SDIDoc : public CDocument { public: void AppToDoc() ; // Test-function to call } // Implementation-File Test_SDIDoc.cpp void CTest_SDIDoc::AppToDoc() // Test-function to call { AfxMessageBox(CTest_SDIDoc::AppToDoc was called ...) ; }
2. A member of class CTest_SDIDoc
(base:
CDocument
) calls a member of class CTest_SDIApp
(base: CWinApp
)
There are two ways to make a call:
2.1 A member-function of class CTest_SDIDoc
(a derivation of
CDocument
) calls a member-function of CTest_SDIApp
using message of type PostThreadMessage
. But in this surrounding,
this won't work, because of the following message boxes. If you would deactivate
all following message boxes in this project, except that in the member-function
CTest_SDIApp::DocToApp()
, then it would work. And that's why it
is not recommended to use PostThreadMessage
.
// Implementation-File Test_SDIDoc.cpp void CTest_SDIDoc::AppToDoc() { AfxMessageBox(CTest_SDIDoc::AppToDoc was called and calls DocToApp()) ; AfxGetApp()->PostThreadMessage(WM_DocToApp, 5, 7) ; // All following AfxMessageBox have to be deactivated //if this should work // successfully, except in CTest_SDIApp::DocToApp() } // Header-File Test_SDI.h class CTest_SDIApp : public CWinApp { void DocToApp() ; } // Implementation-File Test_SDI.cpp BEGIN_MESSAGE_MAP(CTest_SDIApp, CWinApp) ON_THREAD_MESSAGE(WM_DocToApp, DocToApp) END_MESSAGE_MAP()void CTest_SDIApp::DocToApp() { AfxMessageBox(CTest_SDIApp::DocToApp was called) ; }
2.2 A member-function of class CTest_SDIDoc
(a derivation of
CDocument
) calls a member-function of CTest_SDIApp
using a pointer delivered by a manually implemented member-function named
CTest_SDIApp::GetApp()
(refer to Microsoft MSDN article ID:
Q108587).
// Header-File Test_SDI.h class CTest_SDIApp : public CWinApp { public: static CTest_SDIApp *GetApp(); // GetApp() is necessary //to get the pointer anywhere else void DocToApp() ; // Test-function that will be called } // Implementation-File Test_SDI.cpp CTest_SDIApp *CTest_SDIApp::GetApp() // GetApp() is necessary //to get the pointer anywhere else { CWinApp *pApp = AfxGetApp() ; if (pApp == 0) { // error handling } return (CTest_SDIApp*) pApp; } void CTest_SDI::DocToApp() // Test-function that will be called { AfxMessageBox(CTest_SDI::DocToApp was called ...) ; } // Implementation-File Test_SDIDoc.cpp #include Test_SDI.h // If you forget to include //Test_SDI.h, then the members of // CTest_SDIDoc don't know class CTest_SDIApp and //its member-functions BOOL CTest_SDIDoc::AppToDoc() // The function //AppToDoc() calls DocToApp() { AfxMessageBox( CTest_SDIDoc::AppToDoc was called and calls DocToApp()) ; CTest_SDIApp::GetApp()->DocToApp() ; }
2.3 A third theoretical option is the usage of AfxGetApp()
to
apply it to the call of CTest_SDIApp::DocToApp()
, but this won't
work, because the usage of AfxGetApp()
is limited to the members
of CWinApp
and DocToApp()
is only a member of a
derivation of CWinApp
.
3. A member of class CTest_SDIDoc
(base:
CDocument
) calls a member of class CMainFrame
(base: CFrameWnd
)
3.1 A member-function of class CTest_SDIDoc
(a derivation of
CDocument
) calls a member-function of CMainFrame
using message of type SendMessage
or
PostMessage
.
// Implementation-File Test_SDIDoc.cpp void CTest_SDIDoc::AppToDoc() { AfxMessageBox(CTest_SDIDoc::AppToDoc was called and calls DocToFrame()) ; AfxGetMainWnd()->SendMessage(WM_DocToFrame) ; } // Header-File MainFrm.h #define WM_DocToFrame WM_APP+15 class CMainFrame : public CFrameWnd { //{{AFX_MSG(CMainFrame) //}}AFX_MSG afx_msg void DocToFrame() ; DECLARE_MESSAGE_MAP() }; // Implementation-File MainFrm.cpp void CMainFrame::DocToFrame() { AfxMessageBox(CMainFrame::DocToFrame was called) ; }
3.2 A second theoretical option is the usage of
AfxGetMainWnd()
to apply it to the call of
CMainFrame::DocToFrame()
, but this won't work, because the usage
of AfxGetMainWnd()
is limited to the members of
CFrameWnd
and DocToFrame()
is only a member of a
derivation of CFrameWnd
.
4. A member of class CTest_SDIDoc
(base:
CDocument
) calls a member of class CTest_SDIView
(base: CView
)
There are two ways to make a call:
4. 1 A member-function of classCTest_SDIDoc
(a derivation of CDocument
) calls a
member-function of CTest_SDIView
(a derivation of
CView
) using a message of type SendMessage
or
PostMessage
using AfxGetMainWnd()
, which calls a
self-implemented member-function of class CMainFrame
. For
realizing this, look at 3.1 (which is similar to this case) or analyze the
source code of the project. The next step is to send a message of type
SendMessage
or PostMessage
from the
self-implemented member-function of class CMainFrame
to
CTest_SDIView
. This is a conventional way of realizing the call.
4.2 Another solution is to call a member-function of
CTest_SDIView
(a derivation of CView
) by
member-function of class CTest_SDIDoc
(a derivation of
CDocument
) using a self-implemented member-function
GetView
of class CTest_SDIView
. For details
analyze the source code of the project or 1.1 with
CTest_SDIDoc::GetDoc()
(refer to Microsoft MSDN article ID:
Q108587), which is similar to this case.
5. A member of class CTest_SDIApp
(base:
CWinApp
) calls a member of class CMainFrame
(base:
CFrameWnd
) Analyze the source code of the project or 3.1, which
is similar to this case.
6. A member of class CMainFrame
(base:
CFrameWnd
) calls a member of class CTest_SDIApp
(base: CWinApp
)
There are two ways to make a call:
6.1 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) calls a member-function of CTest_SDIApp
using message of type PostThreadMessage
. But in this surrounding,
this won't work, because of the following message boxes. If you would deactivate
all following message boxes in this project, except that in the member-function
CTest_SDIApp::FrameToApp()
, then it would work. And that's why it
is not recommended to use PostThreadMessage
. This example only
works within the boundaries mentioned in Microsoft's article "ID: Q183116".
Analyze 2.1, which is similar to this case.
6.2 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) calls a member-function of CTest_SDIApp
using a pointer delivered by a manually implemented member-function with the
name CTest_SDIApp::GetApp()
(refer to Microsoft MSDN article ID:
Q108587). Analyze 2.2, which is similar to this case.
7. A member of class CMainFrame
(base:
CFrameWnd
) calls a member of class
CTest_SDIDoc
(base: CDocument
)
There are two ways to make a call:
7.1 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) calls a member-function of CTest_SDIDoc
using a pointer delivered by a manually implemented member-function with the
name CTest_SDIDoc::GetDoc()
(refer to Microsoft MSDN article ID:
Q108587). Analyze 1.1, which is similar to this case.
7.2 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) sends a message to CTest_SDIView
(a
derivation of CView
). The pointer of the document, available in
CTest_SDIView
, allows to access the desired member-function of
class CTest_SDIDoc
. Analyze 1.2, which is similar to this case.
8. A member of class CMainFrame
(base:
CFrameWnd
) calls a member of class CTest_SDIView
(base: CView
)
There are three ways to make a call:
8.1 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) sends a message to CTest_SDIView
(a
derivation of CView
) using the function
CFrameWnd::GetActiveView()
// Implementation-File MainFrm.cpp void CMainFrame::AppToFrame() { AfxMessageBox(CMainFrame::AppToFrame was called and calls FrameToView()) ; CView *pView = GetActiveView(); if (pView == NULL) { // error handling routine // Fail if view is of wrong kind // (this could occur with splitter windows, or additional // views on a single document } pView->SendMessage(WM_FrameToView); } // Header-File Test_SDIView.h #define WM_FrameToView WM_APP+9 class CTest_SDIView : public CView { protected: //{{AFX_MSG(CTest_SDIView) //}}AFX_MSG afx_msg void FrameToView() ; DECLARE_MESSAGE_MAP() }; // Implementation-File Test_SDIView.cpp BEGIN_MESSAGE_MAP(CTest_SDIView, CView) //{{AFX_MSG_MAP(CTest_SDIView) //}}AFX_MSG_MAP ON_MESSAGE(WM_FrameToView, FrameToView) END_MESSAGE_MAP() void CTest_SDIView::FrameToView() { AfxMessageBox(CTest_SDIView::FrameToView was called) ; }
8.2 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) sends a message to CTest_SDIView
(a
derivation of CView
) using a pointer delivered by a manually
implemented member-function named CTest_SDIView::GetView()
(refer
to Microsoft MSDN article ID: Q108587) and SendMessage
or
PostMessage
.
// Implementation-File MainFrm.cpp #include Test_SDIView.h // If you forget to include //Test_SDIView.h, then the members of // MainFrm don't know class CTest_SDIView and //its member-functions void CMainFrame::AppToFrame() { AfxMessageBox(CMainFrame::AppToFrame was called and calls FrameToView()) ; CTest_SDIView::GetView()->SendMessage(WM_FrameToView); } // Header-File Test_SDIView.h #define WM_FrameToView WM_APP+9 class CTest_SDIView : public CView { public: static CTest_SDIView *GetView(); // GetView() is necessary to get the pointer // anywhere else protected: //{{AFX_MSG(CTest_SDIView) //}}AFX_MSG afx_msg void FrameToView() ; DECLARE_MESSAGE_MAP() }; // Implementation-File Test_SDIView.cpp BEGIN_MESSAGE_MAP(CTest_SDIView, CView) //{{AFX_MSG_MAP(CTest_SDIView) //}}AFX_MSG_MAP ON_MESSAGE(WM_FrameToView, FrameToView) END_MESSAGE_MAP() void CTest_SDIView::FrameToView() { AfxMessageBox(CTest_SDIView::FrameToView was called) ; } CTest_SDIView *CTest_SDIView::GetView() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); CView * pView = pFrame->GetActiveView(); if ( !pView ) { return NULL; // Fail if view is of wrong kind // (this could occur with splitter windows, or additional // views on a single document } if ( ! pView->IsKindOf( RUNTIME_CLASS(CTest_SDIView) ) ) return NULL; return (CTest_SDIView*) pView; }
8.3 A member-function of class CMainFrame
(a derivation of
CFrameWnd
) calls a member of CTest_SDIView
(a
derivation of CView
) using a pointer delivered by a manually
implemented member-function named CTest_SDIView::GetView()
(refer
to Microsoft MSDN article ID: Q108587) and makes a direct call of
FrameToView()
.
// Implementation-File MainFrm.cpp #include Test_SDIView.h // If you forget to include //Test_SDIView.h, then the members of // MainFrm don't know class CTest_SDIView //and its member-functions void CMainFrame::AppToFrame() { AfxMessageBox( CMainFrame::AppToFrame was called and calls FrameToView()) ; CTest_SDIView::GetView()->FrameToView(); } // Header-File Test_SDIView.h #define WM_FrameToView WM_APP+9 class CTest_SDIView : public CView { public: static CTest_SDIView *GetView(); // GetView() is necessary to get the pointer // anywhere else protected: //{{AFX_MSG(CTest_SDIView) //}}AFX_MSG afx_msg void FrameToView() ; DECLARE_MESSAGE_MAP() }; // Implementation-File Test_SDIView.cpp BEGIN_MESSAGE_MAP(CTest_SDIView, CView) //{{AFX_MSG_MAP(CTest_SDIView) //}}AFX_MSG_MAP ON_MESSAGE(WM_FrameToView, FrameToView) END_MESSAGE_MAP() void CTest_SDIView::FrameToView() { AfxMessageBox(CTest_SDIView::FrameToView was called) ; } CTest_SDIView *CTest_SDIView::GetView() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); CView * pView = pFrame->GetActiveView(); if ( !pView ) { return NULL; // Fail if view is of wrong kind // (this could occur with splitter windows, or additional // views on a single document } if ( ! pView->IsKindOf( RUNTIME_CLASS(CTest_SDIView) ) ) return NULL; return (CTest_SDIView*) pView; }
9. A member of class CTest_SDIApp
(base:
CWinApp
) calls a member of class CTest_SDIView
(base: CView
)
There are three ways to make a call:
9.1 A member-function of classCTest_SDIApp
(a derivation of CWinApp
) sends a
message to CMainFrame
and calls a self-written member-function of
class CMainFrame
, which sends a message to
CTest_SDIView
(a derivation of CView
). For details
look at 1.2, which is similar to this case.
9.2 A member-function of class CTest_SDIApp
(a derivation of
CWinApp
) sends a message to CTest_SDIView
(a
derivation of CView
) using a pointer delivered by a manually
implemented member-function named CTest_SDIView::GetView()
(refer
to Microsoft MSDN article ID: Q108587) and SendMessage
or
PostMessage
. For details look at 8.2, which is similar to this
case.
9.3 A member-function of class CTest_SDIApp
(a derivation of
CWinApp
) calls a member of CTest_SDIView
(a
derivation of CView
) using a pointer delivered by a manually
implemented member-function named CTest_SDIView::GetView()
(refer
to Microsoft MSDN article ID: Q108587) and makes a direct call of
AppToView()
. For details look at 8.3, which is similar to this
case.
10. A member of class CTest_SDIView
(base:
CView
) calls a member of class CTest_SDIApp
(base:
CWinApp
)
There are two ways to make a call:
10.1 A member-function of class CTest_SDIView
(a derivation of
CView
) calls a member-function of CTest_SDIApp
using message of type PostThreadMessage
. But in this surrounding,
this won't work, because of the following message boxes. If you would deactivate
all following message boxes in this project, except that in the member-function
CTest_SDIApp::ViewToApp()
, then it would work. And that's why it
is not recommended to use PostThreadMessage
. Analyze 2.1, which
is similar to this case.
10.2 A member-function of class CTest_SDIView
(a derivation of
CView
) calls a member-function of CTest_SDIApp
using a pointer delivered by a manually implemented member-function named
CTest_SDIApp::GetApp()
(refer to Microsoft MSDN article ID:
Q108587). Analyze 2.2, which is similar to this case.
11. A member of class CTest_SDIView
(base:
CView
) calls a member of class CMainFrame
(base:
CFrameWnd
) using message of type SendMessage
or
PostMessage
. Analyze 3.1, which is similar to this case.
12. A member of class CTest_SDIView
(base:
CView
) calls a member of class CTest_SDIDoc
(base:
CDocument
)
There are two ways to make a call:
12.1 A member-function of class CTest_SDIView
(a derivation of
CView
) calls a member-function of CTest_SDIApp
(a
derivation of CWinApp
) using the pointer delivered by the
skeleton created by the app wizard.
12.2 A second way is similar and uses the pointer delivered by a manually
implemented member-function named CTest_SDIDoc::GetDoc()
(refer
to Microsoft MSDN article ID: Q108587), analyze 1.1, which is similar to this
case.
13. A member of class CTest_SDIApp
(base:
CWinApp
) calls a member of class CTestMessage
making a direct call, using the extern declaration. There are some points to
notice if using extern
. First step is to instantiate the function
or in this project the class CTestMessage
in the
Implementation-File TestMessage.cpp. Second step is to instantiate the
class CTestMessage
for a second time and declare it as extern
in the Header-File TestMessage.h. Third step is to include the
Header-File, containing the class declared as extern, within every
Implementation-File, which uses a member-function of the class
CTestMessage
.
// Header-File TestMessage.h class CTestMessage { ....... }; extern CTestMessage TestMessage ; // Second step // Implementation-File TestMessage.cpp CTestMessage TestMessage ; // First step // Implementation-File Test_SDI.App #include TestMessage.h // Third step BOOL CTest_SDIApp::InitInstance() { TestMessage.MessageWorks() }
14. A member of class CTestMessage
calls a member of class
CTest_SDIApp
(base: CWinApp
)
14.1 A member-function of class CTestMessage
calls a
member-function of CTest_SDIApp
using message of type
PostThreadMessage
. But in this surrounding, this won't work,
because of the following message boxes. If you would deactivate all following
message boxes in this project, except that in the member-function
CTest_SDIApp::TestToApp()
, then it would work. And that's why it
is not recommended to use PostThreadMessage
. Analyze 2.1, which
is similar to this case.
14.2 A member-function of class CTestMessage
calls a
member-function of CTest_SDIApp
using a pointer delivered by a
manually implemented member-function named CTest_SDIApp::GetApp()
(refer to Microsoft MSDN article ID: Q108587). Analyze 2.2, which is similar
to this case.
15. A member of class CTestMessage
calls a member of class
CTest_SDIDoc
(base: CDocument
)
There are two ways to make a call:
15.1 A member-function of class CTestMessage
calls a
member-function of CTest_SDIDoc
using a pointer delivered by a
manually implemented member-function with the name
CTest_SDIDoc::GetDoc()
(refer to Microsoft MSDN article ID:
Q108587). Analyze 1.1, which is similar to this case.
15.2 A member-function of class CTestMessage
sends a message
to CMainFrame
and calls a self-written member-function of class
CMainFrame
, which sends a message to CTest_SDIView
(a derivation of CView
). The pointer of the document, available
in CTest_SDIView
, allows to access the desired member-function of
class CTest_SDIDoc
. Analyze 1.2, which is similar to this case.
16. A member of class CTestMessage
calls a member of class
CMainFrame
(base: CFrameWnd
) using message of type
SendMessage
or PostMessage
.
17. A member of class CTestMessage
calls a member of class
CTest_SDIView
(base: CView
)
There are three ways to make a call:
17.1 A member-function of class CTestMessage
calls a
member-function of CTest_SDIView
(a derivation of
CView
) using a message of type SendMessage
or
PostMessage
using AfxGetMainWnd()
, which calls a
self-implemented member-function of class CMainFrame
. The next
step is to send a message of type SendMessage
or
PostMessage
from the self-implemented member-function of class
CMainFrame
to CTest_SDIView
.
17.2 A second solution is to call a member-function of
CTest_SDIView
(a derivation of CView
) by
member-function of class CTestMessage
using a self-implemented
member-function GetView
of class CTest_SDIView
and
sending a message of type SendMessage
or
PostMessage
. For details analyze the source code of the project
and Microsoft MSDN article ID: Q108587.
17.3 A third solution is to call a member-function of
CTest_SDIView
(a derivation of CView
) by
member-function of class CTestMessage
using a self-implemented
member-function GetView
of class CTest_SDIView
and
making a direct call of CTest_SDIView::TestToView()
. For details
analyze the source code of the project and Microsoft MSDN article "ID: Q108587".