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.

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


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" ?

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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
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.
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

713 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