|
PPS: Here are the requested code snippets, perhaps it helps to trace the problem.
BOOL CBlueSharkEngine::Run()
{
if(!ShowWindow()) return FALSE;
m_bEngineRunning=TRUE;
m_timer.Init();
for (;; )
{
TRACE("\\Mainloop running\n");
if(!m_pWindow->PumpMessage()) break;
TRACE("/Mainloop running\n");
}
TRACE("Mainloop leaving..\n");
DestroyWindow();
m_bEngineRunning=FALSE;
return TRUE;
}
void CBlueSharkEngine::Stop()
{
if(m_bEngineRunning) PostQuitMessage(0);
}
BOOL CBlueSharkEngineWindow::PumpMessage()
{
MSG msg;
TRACE(" \\PumpMessage\n");
while (::PeekMessage (&msg,NULL,0,0,PM_NOREMOVE))
{
TRACE(" PumpMessage message 0x%04x\n",msg.message);
if (!::GetMessage (&msg, NULL, 0, 0))
{
TRACE(" /PumpMessage WM_QUIT\n");
return FALSE;
}
::TranslateMessage (&msg);
::DispatchMessage (&msg);
}
TRACE(" /PumpMessage\n");
return TRUE;
}
CBlueSharkEngine:: ~CBlueSharkEngine()
{
Stop();
assert(!m_bEngineRunning);
DestroyWindow();
if(m_pWindow) delete m_pWindow;
if(m_pTexture) delete m_pTexture;
if(m_pFont) delete m_pFont;
if(m_pInterface) delete m_pInterface;
}
CBlueSharkEngineWindow:: ~CBlueSharkEngineWindow() {}
|
|
|
|
|
OK, try that: I don't think you need any extra message pump (since the main frame is active even when the OpenGL window shows). So, remove the pump out of CBlueSharkEngine::Run , move DestroyWindow to the handling code for WM_CLOSE , and elminate the post-run portion in CMainFrame::OnAppToggle3DDialog . Now replace your CBlueSharkEngine::Stop with a call to CloseWindow (i.e. send a WM_CLOSE to yout OpenGL window.) There are some more details to be adjusted, but I think the general scheme should work.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Thx, Joaquín.
Oops, the main important line in CBlueSharkEngine::Run() is what I commented out previously:
EngineMain(m_timer.GetElapsedSeconds());
This method will render the OpenGL scene (depending from elapsed time). Right now I called it from inside my message loop CBlueSharkEngine::Run() . I need to call this method regular (and as fast as possible to get a high frame rate). Hmm, I think I found a possible replacement, when couldn't start my main message loop. With some structure changes:
LRESULT CALLBACK Wnd_ProcMessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_PAINT:
if(pEngine->m_bEngineRunning)
pEngine->EngineMain(pEngine->m_timer->GetElapsedSeconds());
break;
default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return 0;
}
The "trick" above is to get repeated WM_PAINT messages to render my frames with EngineMain() . The rendering starts, when I set m_bEngineRunning=TRUE (and Invalidate() ). It works in a test project, I will do more testings soon.
Some questions:
* How efficient is it to request repeated WM_PAINT messages generally, don't I loose CPU performance compared to my direct calling message loop? In a game engine or a 3D visualisation you want to reach highest frame rate.
* There is one negative side effect with this new type of message handling. The handling of the system menu became very "blocky", anything else negative that could happen?
Thx again, Moak
|
|
|
|
|
First of all, have you finally solved the message pump mess following my proposal? (just curious, you know.)
As for how to get repainting in your OpenGL window, you have various options:- The most simple way is to set a Windows timer (see
SetTimer ), which sends a message at a given rate. This is not very accurate, but should suffice for say up to 10 fps. - If you need more frames per second, probably your best bet is multimedia timers. These call a user-defined callback with much finer temporal resolution than Windows timers. This callback is executed in a thread different from your app's, so beware of concurrency problems. Probably the best way to avoid them is sending a user message to the OpenGL window from the multimedia timer callback and doing the reapaint there.
For much more info on different timers, read Nemanja Trifunovic's Timers tutorial.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Joaquín M López Muñoz wrote:
First of all, have you finally solved the message pump mess following my proposal?
Yes, your ideas was helpfull! I think it didn't solve the problem yet how to keep the rendering of the OpenGL scene alive? I was thinking about suggestion 1. + 2. too; what do you think about my solution 3. with the repeated WM_PAINT (see my last post)?
Briefly explanation: The trick was letting Windows sending you WM_PAINTs as often as possible, so you do not need an additional timer, multimedia or high resultion timer triggering the rendering. When rendering the OpenGL scene (just imagine a game with at least 30 FPS) you mainly don't need very regular redraws (which usually is an illusion in a multitasking environment). But you want them as often/fast as possible!
The trick with the WM_PAINT is working because you do not validate the update region with DefWindowProc function, Windows will send another WM_PAINT soon. As far as I understood from one Codeproject tutorial, WM_PAINT is a virtual message that is generated on the fly, whenever nothing else is happening. Idea sounds good and testing software showed it works.
I still prefer to use my own message pump and direct triggering of the rendering in a game, but the WM_PAINT trick seems to be a nice way to mix a MFC application with OpenGL.
Well, I need to do some profiling (evaluating FPS). Basically the WM_PAINT thing works... I wonder how efficient it is? What do you think?
Btw, befor you wonder about the timer in pEngine->EngineMain(pEngine->m_timer->GetElapsedSeconds()) . I use this timer to tell the rendering how many time has elapsed since last drawing. The EngineMain() function should update the object depending on time. I allready used this technique before to gain a CPU independent rendering.
Greets, Moak
|
|
|
|
|
I don't really think having your own message pump (unless it is an a separate thread) is a good idea at all. Depending on the host program, the message pump can do a lot of things you don't have the slightest idea about (as indeed does MFC), so replacing it with your own is bound to problems.
As for the WM_PAINT message, well if it works and you're satisfied with it, I guess it's OK. Nevertheless, multimedia timers are probably best fit for this kind of purposes (thery're are designed for this), and they allow for more flexibility to set the framerate desired (as it stands now, I guess the WM_PAINT method causes your app to choke a bit, doesn't it.)
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
A and B are correct.
Just for your knowledges as well, the modal dialog in MFC is different than the modal dialog that you will get with the Win32 API. That is because of that function that you found, RunModalLoop(), MFC creates its own message pump to handle all of the messages, which allows the rest of the app to intervene if necessary, MFC is able to accomplish this because it always creates its dialogs with CreateDialog rather than DialogBox. If you call DialogBox in the Win32 API, windows will create their own modal message pump for you.
Coincidentally this is how the processing for menus works as well, there is a modal message pump involved.
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
|
|
|
|
Is there anyway in code to create a file association. i.e. I want to associate a file type of .log with notepad. I know how to do this via Windows explorer, can I do this at runtime?
Thanks in advance,
Bob
|
|
|
|
|
You can create registry keys at HKEY_CLASSES_ROOT.
Create one for the file extesion (Ex.: .log) and put as default value a mime type (Ex.: text/plain). If the mime doesn´t exists you can create another key at HKEY_CLASSES_ROOT with a subkey shell\open and put the command to open the file there.
Mauricio Ritter - Brazil
Sonorking now: 100.13560 Trank
The alcohol is one of the greatest enemys of man, but a man who flee from his enemys is a coward.
|
|
|
|
|
|
Is there any way to have a combo box without the button to drop the list down? If not can the button be resized in any way?
Ed
|
|
|
|
|
Wow, a combobox without the buttong to drop list !!!!
It became an editbox or a listbox !!!!
I can't understand you !
Hung Son
i-g.hypermart.net
dlhson2001@yahoo.com
|
|
|
|
|
Ha ha, I know it sounds strange, but I still need it to drop the list when the user clicks the box or hits F4, I just can't get the boxes to fit where they need to without getting rid of the button somehow. I am dealing with a screen drawn for a character based program and I have to use the same layout so my space is limited.
Ed
|
|
|
|
|
you would need to do subclassing already.
how about checking this out.
http://www.codejock.com/developer/article02.htm
this makes a flat button.
so now u can don't draw the buttons instead
|
|
|
|
|
Hi,
Is there any way I can convert a HRESULT to the "errorcode string"
I mean, the HRESULT 2147746132 means "Class not registered", is there any functions that takes a HRESULT and gives me a string with the error text?
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
FormatMessage API function will works with predefined HRESULT.
Philippe Mori
|
|
|
|
|
From MSDN Q169498:
// Obtain the error message for a given HRESULT
CString LogCrackHR( HRESULT hr )
{
LPVOID lpMsgBuf;
CString strTmp;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL );
// STR_TMP is defined within LOG.CPP to provide safe format string
// for both ANSI and UNICODE
strTmp.Format( "%s", (char *) lpMsgBuf );
// Free the buffer.
::LocalFree( lpMsgBuf );
return strTmp;
}
Brandon
The WTL newsgroup: over 1400 members! Be a part of it. http://groups.yahoo.com/group/wtl
|
|
|
|
|
I'm subclassing a static control. I would like to get the mouse click messages but they don't seem to get generated. I get them if I subclass from a button.
Cathy
Life's uncertain, have dessert first!
|
|
|
|
|
Mamke sure the static control resource on the dialog has the Notify style set to be able to get mouse messages.
Roger Allen
Sonork 100.10016
If I had a quote, it would be a very good one.
|
|
|
|
|
That did it. Thanks!
Cathy
Life's uncertain, have dessert first!
|
|
|
|
|
I created an ATL DLL server project and inserted a new ATL object as a simple one, named Inter. Next, i added a new BSTR-type property named Str.
I wrote:
STDMETHODIMP CInter::get_Str(BSTR *pVal)
{
_bstr_t x(*pVal, FALSE);
m_str=x.copy();
return S_OK;
}
This code links perfectly on debug versions but generates this error:
LIBCMT.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
on release versions.
Do you know how to handle it?
rechi
|
|
|
|
|
|
This is straight from MSDN, help topic _ATL_MIN_CRT :
Note When building a Release version of a project, you can get the following link error:
LIBCMT.LIB(crt0.obj) : error LNK2001: unresolved external symbol _main
This error occurs if you are using CRT functions that require CRT startup code. The Release configurations define _ATL_MIN_CRT, which excludes CRT startup code from your EXE or DLL. To avoid this error, do one of the following:
Remove _ATL_MIN_CRT from the list of preprocessor defines to allow CRT startup code to be included. On the Project menu, click Settings. In the Settings For: drop-down list, choose Multiple Configurations. In the Select project configuration(s) to modify dialog box that appears, click the check boxes for all Release versions, and then click OK. On the C/C++ tab, choose the General category, then remove _ATL_MIN_CRT from the Preprocessor definitions edit box.
If possible, remove calls to CRT functions that require CRT startup code and use their Win32 equivalents. For example, use lstrcmp instead of strcmp. Known functions that require CRT startup code are some of the string and floating point functions.
Roger Stewart
"I Owe, I Owe, it's off to work I go..."
|
|
|
|
|
Thanx!
That was it.
rechi
|
|
|
|
|
I have written an MDI application and its almost finished. I just need to display a help file written in Compiled HTML.
What's the easiest / quickest way to do this?
Thanks
Ali
|
|
|
|
|