Sign in to follow this  

where is message loop in mfc application?

This topic is 4814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I changed my win32 application to mfc application, in win32 application, the rendering is after the main message loop, but in mfc application, where can i put "myrender"? because i can't find the main message loop. while (1) { if (PeekMessage( & msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage( &msg, NULL, 0, 0)) { TranslateMessage( &msg); DispatchMessage( &msg); } else { break; } } myrender(); Sleep(10); }

Share this post


Link to post
Share on other sites
The message loop is implemented as a static member of some base class that your MFC class derives from. You can put your rendering function in the OnPaint() method of your render control and have a timer function that calls Invalidate() on the control.

Do you really need MFC?

Share this post


Link to post
Share on other sites
The message loop for a MFC application is a public function of CWinApp. The functions name is Run. So that would make it CWinApp::Run( ).

From MSDN :
Provides a default message loop.
virtual int Run( );

Return Value

An int value that is returned by WinMain
Remarks
Run acquires and dispatches Windows messages until the application receives a WM_QUIT message. If the application's message queue currently contains no messages, Run calls OnIdle to perform idle-time processing. Incoming messages go to the PreTranslateMessage member function for special processing and then to the Windows function TranslateMessage for standard keyboard translation; finally, the DispatchMessage Windows function is called.
Run is rarely overridden, but you can override it to provide special behavior.

Share this post


Link to post
Share on other sites
Quote:
Original post by jefftsai2050
OnIdle and OnPaint are both run while receiving messages. But if i want to make a character to walk, at this time, no messages are received, these functions can't not be called.

He's got a point, and MFC can be very useful for creating tools.

Basically, you have two options:

1. Override your application's Run() method. This isn't difficult, but it is intrusive. Simply copy the code from CWinApp::Run(), paste it into your version, and make the required changes, like having it call your rendering code. You'll also need to override CWinApp::OnIdle, and put those changes in there, too.

2. Create a separate thread for rendering. This needs to be done when your application starts, and you can have the thread call your update functions continuously. Again, not difficult, but you'll probably need to deal with thread issues like mutexes...

Share this post


Link to post
Share on other sites
Mutexes, screw that! It’s so hard just to do a few cool things isn’t it? I would say ditch the OnIdle and OnPaint. Override Run and call your rendering procedure form their.

I use MFC a lot and at times it’s very frustrating and makes me want to revert back to the old fashion Win32-C library. But never fear, because that Win32-C code is used by MFC behind the scenes. So just take all your regular code that you would use in an application not using MFC and put it in the application using MFC.

MFC’s CWinApp is an awesome class. The main things you would want to override are InitInstance, Run, and ExitInstance. InitInstance is called when you application initializes (loads), while Run performs the main logical and message processing loops, then ExitInstance iscalled when your application terminates. CWinApp also supports a rudimentary registry access. You shouldn’t try to override these methods, but you could use them to your benefit.

Many times, the main methods you will override of CWinApp is InitInstance and Run. You wouldn’t override ExitInstance unless you had special component interfaces or resources you would need to release.

So do you get me? If not I can send you a sample of how I handle this with my MFC applications.

Share this post


Link to post
Share on other sites
I'm still not convinced changing CWinApp:Run() is the right thing. MFC can be a pain in the ass if you try to bend it to your will. Using it the way it was intended yields greater results.

All of the tools I have ever written in MFC that use D3D use the OnIdle() function:

BOOL CD3DEditorApp::OnIdle(LONG lCount)
{
// Call base class first
CWinApp:OnIdle( lCount );

// Update the interval timer
m_pTimer->UpdateFrame();

// Update game logic
m_pGame->UpdateGameLogic( m_pTimer->GetFrameDelta() );

// Call my render loop
m_pGame->Render();

// Always return true - this asks the framework to constantly
// call the Idle function when it isn't busy doing something
// else.
return TRUE;
}


The secret is to return TRUE from OnIdle, getting constant updates.

It's important to realize that your renderer just draws everything on the screen, and the game logic is seperate. This makes it easier to write an interface where all you do is tweak game objects in windows message handlers, and then the renderer draws it for you. I've written a bunch of tools and it works really well as long as you work within the paradigm of a windows application.



Share this post


Link to post
Share on other sites
Quote:
Original post by Sphet
I'm still not convinced changing CWinApp:Run() is the right thing. MFC can be a pain in the ass if you try to bend it to your will. Using it the way it was intended yields greater results.

All of the tools I have ever written in MFC that use D3D use the OnIdle() function:

BOOL CD3DEditorApp::OnIdle(LONG lCount)
{
// Call base class first
CWinApp:OnIdle( lCount );

// Update the interval timer
m_pTimer->UpdateFrame();

// Update game logic
m_pGame->UpdateGameLogic( m_pTimer->GetFrameDelta() );

// Call my render loop
m_pGame->Render();

// Always return true - this asks the framework to constantly
// call the Idle function when it isn't busy doing something
// else.
return TRUE;
}


The secret is to return TRUE from OnIdle, getting constant updates.

It's important to realize that your renderer just draws everything on the screen, and the game logic is seperate. This makes it easier to write an interface where all you do is tweak game objects in windows message handlers, and then the renderer draws it for you. I've written a bunch of tools and it works really well as long as you work within the paradigm of a windows application.



I’ll be nice about this, but I strongly disagree with you about OnIdle. But I strongly agree with you about bending MFC to your will. If you applications run using the OnIdle function, how slow are they? I’d rather code my own message loop. There are tutorials on MSDN about this and I’ve seen in almost all of the tutorial that I found that CWinApp::Run( ) was used, no OnIdle. But I bet both methods work just as good.

MFC is great for games and tools, in my opinion. I think if overriding Run works best, but that is what I think. Here is my code to my applications that I use:


// Interface
class CDummyApp : public CWinApp
{
public:

CDummyApp( void ) { }
virtual ~CDumyApp( void ) { }

virtual BOOL InitInstance( void );
virtual int Run( void );
virtual int ExitInstance( void );

protected:

DECLARE_MESSAGE_MAP( )
};

// Implementation

CDummyApp theApp; // Global application instance

BOOL CDummyApp::InitInstance( void )
{
// init stuff
}

int CDummyApp::Run( )
{
MSG msg;
BOOL bGotMsg;

PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );

while ( WM_QUIT != msg.message )
{
if ( /* window is active */ )
{
bGotMsg = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 );
}
else
{
bGotMsg = ( GetMessage( &msg, NULL, 0U, 0U ) != 0 );
}

if ( bGotMsg )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
// TODO : Put code here that perform normal logial routines
}
}

return ( int )msg.wParam;
}

int CDummyApp::ExitInstance( )
{
// Release uses resources

return CWinApp::ExitInstance( );
}



Where /*window is active */ is where I use the CFrameWnd subclass to get the active state of the application via WM_ACTIVATEAPP. That message is sent to the window, not the application. That is how I run my MFC applications.

I never would have used the OnIdle because I don’t want a bunch of crap getting called or slowing down the programs execution for some silly shell or MFC thing I never really wanted to use. The cool thing about MFC is I can get an application up and running quicker and easier then in old Win32.

To me the OnIdle method sucks if you want to use MFC for a game. But if you are working with a networking software or something similar to that, then OnIdle would suffice. Maybe it would do better. Honestly I couldn’t tell you because I never used it. I just wrote my own message loops.

I don’t know Sphet, I would like to see some examples of your work apposed to mine to see if I should incorporate your design into my work.

Share this post


Link to post
Share on other sites

This topic is 4814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this