Solved

Timer locked when holding mouse down (WinNT)

Posted on 1998-03-03
9
419 Views
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.
0
Comment
Question by:SergeDePauw
  • 4
  • 3
  • 2
9 Comments
 
LVL 4

Expert Comment

by:jtwine100697
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.
0
 

Author Comment

by:SergeDePauw
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.
0
 
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.


0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

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

 

Author Comment

by:SergeDePauw
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:

Having:
- 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);
pPresetThread->CreateThread();

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

Thanks.
0
 
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.


0
 

Author Comment

by:SergeDePauw
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...
0
 
LVL 4

Accepted Solution

by:
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.
0
 
LVL 4

Expert Comment

by:jtwine100697
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
    }
};


0
 

Author Comment

by:SergeDePauw
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.
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
How to create frequencies of a variable from SAS dataset? 10 133
repeateFront java challenge 31 94
zeroMAx challenge 20 111
"Black Box" Testing of Control System Software 2 69
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: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
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.
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

790 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