Callback Routine Not Getting Triggered - c++

I've created a very simple one-button MFC dialog app that attempts to utilize a callback function. The app complies and runs just fine, but the callback routine never gets triggered.
What needs to be modified in order to get the callback to trigger properly?
You can download the test.zip file here (the test app is in VS 2003 to ensure more people can try it out): http://tinyurl.com/testfile-zip
The code utilizes an alarm class on CodeProject, and the callback function is suppsed to get triggered every 3 seconds (as determined by the code being passed in).
Thanks!

I've looked at your code and the I believe the Function called from the button is the problem
void CTestDlg::OnBnClickedButton1()
{
CAlarmClock clock;
REPEAT_PARMS rp;
ZeroMemory(&rp, sizeof(REPEAT_PARMS));
rp.bRepeatForever = TRUE;
rp.Type = Repeat_Interval;
rp.ss = 3;
clock.SetRepeatAlarm(0, 0, 0, rp, CallbackRtn);
}
This creates the Alarm clock on the function stack.
This CAlarmclock object is therefore destroyed at the end of the function along with its contents.
For it to be able to exist for long enough to actually do the callback
you need to add it as a member variable of your dialog class for it to exist and callback for as long as the dialog exists.
See the example code on the CAlarmclock codeproject page for how to use this class correctly.

Related

OnInitialUpdate called twice

One of our MFC legacy applications shows a behavior I do not really understand right now. I am not an MFC expert, however. The symptom that I observe and which is causing problems is that OnInitialUpdate of the views is called twice by the framework during app start-up. As I understand the documentation it should be called only once.
My investigation revealed that the app calls the following code in its InitInstance:
CMainFrame *const pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) { return FALSE; }
m_pMainWnd = pMainFrame;
This causes CFrameWnd::LoadFrame being called inside the framework. From here both calls to OnInitialUpdate originate. The first when Create is called and the second when SendMessageToDescendants is called to send WM_INITIALUPDATE.
Our app overloads CMainFrame::OnCreateClient to create a splitter window:
Splitter.CreateStatic(this, 2, 2);
Splitter.CreateView(0, 0, RUNTIME_CLASS(MyView),CSize(0,0), pContext);
// ...
The call to Splitter.CreateView is what triggers OnInitialUpdate to be called the first time. But as I could see from the documentation this implementation is as intended. So unfortunately this is where I get stuck. I don't understand if the OnInitialUpdate call from SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE) or from CSplitterWnd::CreateView is wrong.
What else could I take a look at to figure out the root cause of this problem?
Is it possible for OnInitialUpdate to be called twice and we need to make sure that our app can cope with this?
If the answer to question 2 is yes: What is the best way to archive this?
EDIT
Further investigation has shown that CSplitterWnd::CreateView only sends WM_INITIALUPDATE if the passed CCreateContext is a nullptr. So I checked CMainFrame::OnCreateClient and it is indeed called by the framework with pContext being nullptr.
EDIT2
As requested in the comments here is the code adding the DocTemplate:
CSingleDocTemplate *const pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMenuView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
There is also a call
Splitter.CreateView(1, 1, RUNTIME_CLASS(CMenuView),CSize(0,0), pContext);
in the CMainFrame::OnCreateClient. If I understand the comments correctly this is wrong?
The two calls of OnInitialUpdate are for the same instances of the views. If I followed the stack trace correctly the reason for the CCreateContext being a nullptr is that no context is passed to LoadFrame. The context passed to CFrameWnd::LoadFrame is just forwarded to CMainFrame::OnCreateClient. But what context should I pass?

C++ MFC - code execution failure without throwing runtime error on CDialog::OnSize event (GetWindowRect)

I'm trying to access control size properties inside a CDialog::OnSize event handler. Code compiles and runs, but seems to fail at GetWindowRect. No run time error is thrown that I can see, but the code including and following the GetWindowRect call silently fails to run.
I have ran in release and debug mode, with breakpoints in appropriate positions (which are not hit GetWindowRect). I have also used code that modifies some member variables following GetWindowRect as an additional test, which I can also see is not running.
virtual void CMainFormDialog::OnSize(UINT nType, int cx, int cy)
{
....
auto pOutputEdit = (CEdit*) GetDlgItem(CE_OutputEdit);
CRect pOutputEditRect;
// No code is executed following this statement...
pOutputEdit->GetWindowRect(&pOutputEditRect);
....
}
Is there something wrong with the way I'm trying to access properties of my CEdit control here, and why does it fail silently?
Thanks.
OnSize is likely called as part of the creation of the dialog, at a point where CE_OutputEditmay not yet have been created. CE_OutputEdit is created and bound as part of OnInitDialog. Check the return value of GetDlgItem and only perform whatever you need to do when it returns non NULL.
If needed use a variable that's set to true after you call CDialog::OnInitDialog and done other necessary initialization. Then use this variable in OnSize to determine if you should do your processing. Regardless of this, you should still check the return value of GetDlgItem

Passing Data to Windows Console Control Handler

I am working on writing a simple game engine and I am having trouble handling Windows console events; specifically, I cannot figure out how to pass custom data to the callback handler.
I first call this code to specify my callback function:
SetConsoleCtrlHandler((PHANDLER_ROUTINE)WindowsSystemManager::ConsoleControlHandler, true);
My static-member callback function is defined as:
bool WINAPI WindowsSystemManager::ConsoleControlHandler(DWORD controlType){
if(controlType == CTRL_CLOSE_EVENT){
MessageBox(NULL, L"Close Event Captured", L"Close Event Captured", NULL);
}
return true;
}
Everything works fine - when I click on the close button in the console, this MessageBox pops up. Only problem is, I need to call code that flushes a logging buffer to a log file on this type of shutdown (as well as other clean-up), and the Logger instance is a member in my WindowsSystemManager.
I have dealt with a similar problem of passing custom data to window handles by using SetWindowLongPtr and GetWindowLongPtr successfully, but I can't find any information on how to do this type of thing with console control handlers. Any thoughts?
EDIT: I got this functionality working based on MSalters' suggestions. The final code for the console control handler is here:
bool WINAPI WindowsSystemManager::ConsoleControlHandler(DWORD controlType){
BerserkEngine* engine = (BerserkEngine*)GetWindowLongPtr(GetConsoleWindow(), GWLP_USERDATA);
if(controlType == CTRL_CLOSE_EVENT){
engine->~BerserkEngine();
PostQuitMessage(0);
}
return true;
}
Where I set this custom data pointer in the WindowsSystemManager constructor:
SetWindowLongPtr(GetConsoleWindow(), GWL_USERDATA, (LONG_PTR)this->engine);
I'm not sure why you'd need this. You can have multiple windows, but only one console.
However, GetConsoleWindow will give you the console HWND, on which you might call SetWindowLongPtr. Not very clean (you're not supposed to do this on windows that you don't manage), but it might just work.

wxProgressDialog somehow keeping app alive after death?

I'm having a strange problem with wxWidgets. I have the following code
MyFrame::OnDoSomeLongThing(...) {
progScreen = new wxProgressDialog(text,text,number,this,wxPD_AUTO_HIDE); // wxProgressDialog *progScreen is class member
doPartOfThing() // calls the update method at the end of it
....
doLastPartOfThing() // again calls update method that pushes value to 100/100
progScreen->Destroy();
}
MyFrame::update() {
progScreen->Update(newValue);
}
Now here's the thing. I can literally comment out the lines relating to progScreen, just let the process go without using a progress dialog, after all is said and done, my apps exits gracefully when I close the main window.
However, just the use of the progress dialog is somehow extending the life of the application. I've tried Destroy(), I've tried simply 'delete progScreen', and both, every time: I'll close the main frame, the process keeps running, and at some point exits with some astronomical number. The only thing I could think might be relevant, is that the doPartsOfThings methods may call boost::this_thread::sleep, because it involves waiting and whatnot down in my model class. But this shouldn't have anything to do with my problem. Or maybe it does... EDIT: I do want to emphasize that progScreen->Update() IS being called from the main (GUI) thread.
So I ask, am I using a wxProgressDialog correctly? If not, how should it be used?
Thanks for your help!
EDIT:
Well... it turns out that removing wxPD_AUTO_HIDE fixed the problem. I'm still not quite sure what the problem is, but the dialog even still behaves as before. App closes as expected.
I think that you need to override the wxApp method that closes the application so that it closes the wxProgressDialog object before it quits.
wxApp::OnExit
virtual int OnExit()
Override this member function for any processing which needs to be
done as the application is about to exit. OnExit is called after
destroying all application windows and controls, but before wxWidgets
cleanup. Note that it is not called at all if OnInit failed.
The return value of this function is currently ignored, return the
same value as returned by the base class method if you override it.
You will need something like, assuming progScreen is a public attribute of your frame
int myApp::OnExit()
{
(MyFrame*)(GetTopWindow())->progScreen->Destroy()
return wxApp::OnExit();
}

Explicit Linking DLL and Program Hangs

I've the following piece of code in my program which dynamically links wtsapi32.dll file for session notifications like WTS_SESSION_LOCK and WTS_SESSION_UNLOCK and runs in background. After the first lock/unlock the program hangs and not responding.
Is this a right way of doing explicit linking ?
void RegisterSession(HWND hwnd)
{
typedef DWORD (WINAPI *tWTSRegisterSessionNotification)( HWND,DWORD );
tWTSRegisterSessionNotification pWTSRegisterSessionNotification=0;
HINSTANCE handle = ::LoadLibrary("wtsapi32.dll");
pWTSRegisterSessionNotification = (tWTSRegisterSessionNotification) :: GetProcAddress(handle,"WTSRegisterSessionNotification");
if (pWTSRegisterSessionNotification)
{
pWTSRegisterSessionNotification(hwnd,NOTIFY_FOR_THIS_SESSION);
}
::FreeLibrary(handle);
handle = NULL;
}
Edited:
I have another method UnRegisterSession() function which calls WTSUnRegisterSessionNotification, I am calling the RegisterSession() in WinMain method ( removed FreeLibrary as suggested by 1800) and calling UnRegisterSession() in WM_DESTROY of CALLBACK WindowProcedure function. But still the application hangs.
I'd say you probably cannot safely call FreeLibrary like that - you will be unloading the code you want to have call you. You should probably ensure not to free the dll until after you are finished getting notifications.
MS documentation suggests that you must call WTSUnRegisterSessionNotification before re-registering the session - as it only happens on your second attempt to lock it perhaps this is your issue?
With 1800 wrt the free library - you must keep this library loaded while you use it.
According to the documentation (http://msdn.microsoft.com/en-us/library/aa383841(VS.85).aspx):
"When a window no longer requires these notifications, it must call WTSUnRegisterSessionNotification before being destroyed."
I would try unregistering the notification during WM___CLOSE instead of WM_DESTROY.