Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Timer locked when holding mouse down (WinNT)

Posted on 1998-03-03
Medium Priority
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
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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.

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.


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 600 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

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 …
In this post we will learn different types of Android Layout and some basics of an Android App.
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.
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA:…

704 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