Timer locked when holding mouse down (WinNT)

Posted on 1998-03-03
Last Modified: 2013-11-20
I have a MDI application which uses MultiDocTemplate as well.

My CFormView derived class contains a timer proc which is interrupted by some events; like holding down the mouse button on the window's title bar. This is what I want to avoid (my timer proc. which does audio playback CAN'T be interrupted).
Remark: By "holding down the mouse button" I also mean: not moving the mouse. If I move the mouse (thus the window) then the timer proc gets called.

I tried to implement a CWinThread to handle the events as shown in the MTBounce sample code (which "bounces" a ball even when holding the mouse down on the window's title bar).

The difference is that the MTBounce sample doesn't use a MultiDocTemplate. So I've put the creation of my Thread (which must create itself the CFormView derived object) in the "OnCreateClient" proc of my CMDIChilWindow derived class.

The problem is: it makes no difference, the same events are "locking" the application and prevent the timer proc to run.

I'm quite new to MFC programming but I think I correctly applied the source code of MTBounce in my app, except that I'm not sure at all regarding what MultiDocTemplate could do to interfere.

Thanks to all.
Question by:SergeDePauw
  • 4
  • 3
  • 2

Expert Comment

ID: 1316697
Are you using the timer via the WM_TIMER message, or a callback?

   Using the WM_TIMER message means thay your app will not process the message unless it is pumping it's message queue.

   Try using a timer with a callback function.

   You could also create a simple (non-UI) worker thread to handle the audio playback.

-=- James.

Author Comment

ID: 1316698
Thanks for you quick answert but...

I tried using the timer via WM_TIMER and via a callback timer proc and it does the same: as soon as I hold the mouse button on the window's title bar, my timer proc is not called anymore.

I would prefer not to use a worker thread because my timer will not only play audio but also display a progress bar, handle sound file auto-chain and so on... So I think I really need a thread that handles the events for my window, letting the main thread running normally whatever the user is doing with the mouse or keyboard.
LVL 15

Expert Comment

by:Tommy Hui
ID: 1316699
I suspect your are not using the form of timers that is not message based. Make sure you are doing this:

      m_TimerId = ::SetTimer(NULL, NULL, 1000, MyTimerProc);

and that MyTimerProc is doing this:

void CALLBACK MyTimerProc(HWND hwnd, UINT msg, UINT idEvent, DWORD dwTime)
      TRACE("0x%08X  msg: %d  id: %d  time:%d\r\n", hwnd, msg, idEvent, dwTime);

Then if you run this in the debugger, you'll see that the function is called even when you are dragging the window around.


Author Comment

ID: 1316700
I tried both using MFC's SetTimer for a callback timer proc and the one you show: the results are the same.
Let just me remind you: if I MOVE the window: it works; the problem comes up only if the mouse button is down and the mouse DOESN'T MOVE.

Anyway, the MTBounce sample code doesn't use a callback timer but a WM_TIMER message based proc located in the window class.
I guess that it is much easier to access the view's and other object's globals so I think I need to do it the same way.

I experienced further more and I think I found the reason to my problem (but not the solution, so I still need you guys !):

- When I place the "SetTimer" in the same proc where I create the view (in my CWinThread derived class): the timer is still locked by the "mouse button down on wdw title"
- When I call "SetTimer" in the "InitInstance" proc: it works just fine !

So the solution to my problem is to find a way to implement a CWinThread in a MDI / CMultiDocTemplate application.

Here are some details about what I've done so far.

As MTBounce sample doesn't use resources or DocTemplates, it simply implements a "direct" creation of the CMDIChildWindow which itself creates the CWinThread, which itself creates the CWnd (in the "InitInstance" proc of the Thread).

I tried to implement the same hierarchy BUT I wasn't able to create my CFormView in the InitInstance of my Thread (because I use resources and multidoctemplate). Instead, this is what I've done:

- CChildFrame derived from CMDIChildWnd
- CPresetThread derived from CWinThread
- CTestFormView derived from CFormView

I overided "OnCreateClient" in CChildFrame where I replaced the creation of CTestFormView by the creation of CPresetThread as follow:

CPresetThread* pPresetThread = new CPresetThread(m_hWnd);

Right after that, I also call my own proc in CPresetThread in order to create the CTestFormView:

m_TestFormView = pPresetThread->CreateView(this, pContext, AFX_IDW_PANE_FIRST);

"OnCreateClient" is the best place I found to put this call because this is where I have access to the CCreateContext object (created by the CMultiDocTemplate).

I figured out that CPresetThread::InitInstance is only called later on (I expected it to be called during "CreateThread()" but it seems it is not the case).
If I relate this to the "SetTimer" call experience, the creation of the CTestFormView is made too soon.

As I don't know where else I could create CTestFormView: does anyone know how I should proceed from there ?

Other solutions to my problem could be:

1. to create the CWinThread independently from the rest and "assigning" it a window to handle events afterwords. But I'm not sure this is possible.

2. create the CTestFormView (from a dialog resource) directly in the InitInstance and assigning it afterwords in the doctemplate.

Did anyone succeed in implementing a CWinThread in a MDI / CMultiDocTemplate application ? Isn't that a "common need" ?

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

LVL 15

Expert Comment

by:Tommy Hui
ID: 1316701
Okay, I see your problem now. When the mouse is clicked without moving the mouse, the timer callback isn't called. You can only achieve your results with a thread. You should take a look at the O'Reilly book Win32 Multithreaded Programming. Look specifically at chapter 13 at the Animator program.


Author Comment

ID: 1316702
Yes,...and No.
As I said, I finally made the timer proc work (even whit mouse-click without moving the mouse): if I put the "SetTimer" call in the "InitInstance" of my Thread-derivec class.

I need a user-interface Thread (not a simple timer proc) and it seems the problem is to make a CWinThread handle events for a View that is normally created by the CMultiDocTemplate.

I'll try to find the book you're talking about, but in the meantime, if anyone knows the way to achieve that...

Accepted Solution

jtwine100697 earned 200 total points
ID: 1316703
  If you want a thread to manipulate controls in another window (hence another Message Queue) you are going to have to pass the HWNDs of the controls it needs to manipulate to the thread.

   The thread can sit in a tight loop, looping every (for example) 100ms and preform whatever updates you need.

   What you as can be done, of couse, but I need you to specify exactly what controls and "events" you will need to manipulate and/or work with in the thread.

-=- James.

Expert Comment

ID: 1316704
Basically, it looks something like this:

// Data To Pass To Thread...
struct  SThreadData
    CMyView m_*pView;
    HWND    m_hWndProgress;
    HWND    m_hWndStatus;
(Pass MyThreadProc a pointer to a populated SThreadData structure: AfxBeginThread( MyThreadProc, pTData ) )

UINT    MyThreadProc( VOID *pParam )
    SThreadData     *pTData = (SThreadData*)pParam;// Get Thread Data
    CMyView         *pThis = pTData -> m_pView;    // Get "this" Pointer
    CProgressCtrl   pgProgress;
    CStatic         scStatus;
    CString         sMessage;
    int             iPercent;

    pgProgress.Attach( pTData -> m_hWndProgress ); // Attach Object To Window
    scStatus.Attach( pTData -> m_hWndStatus );     // Attach Object To Window

    while( !ms_bAppDone )                          // While Not Done
        pThis -> UpdateAudioData();                // Update Audio
        iPercent = pThis -> GetAudioDataDone();    // Get Percentage
        sMessage.Format( "Audio Data %d%% Done",
            iPercent );                            // Format Message
        pgProgress.SetPos( iPercent );             // Set Progress Pos
        scStatus.SetWindowText( sMessage );        // Set Status Message
        Sleep( 100 );                              // Sleep Until Next Update


Author Comment

ID: 1316705
This is not exactly what I wanted to do but I combined your idea with another sample code I found and I think that will do the job.

I also now have the book "thui" told me about. It seems to be very interesting and I'm sure it will also be helpfull.

Thanks to all for your help.

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
if loop error 4 77
VB.NET how to use the Vertical ScrollBar 5 87
fix34  challenge 9 98
Path of Workbook 3 45
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now