在用户很长一段时间内无动作的时候就认为空闲,要在空闲状态插播一段FLASH。现在问题是如何判断我的程序处在空闲?在线等后。

解决方案 »

  1.   

    在app中有一个虚函数OnIdle,在其中加入即可
      

  2.   

    CWinApp有OnOdle事件,你可以在里面编程。
      

  3.   

    OnOdle,CWinapp会不停的调用,因为它是先假定现在就是空闲其中有OnOdle(0)和OnOdle(1)两次调用,
      

  4.   

    重载OnIdle()就可以啊。
      

  5.   

    CWinApp::OnIdle 
    virtual BOOL OnIdle( LONG lCount );Return ValueNonzero to receive more idle processing time; 0 if no more idle time is needed.ParameterslCountA counter incremented each time OnIdle is called when the application’s message queue is empty. This count is reset to 0 each time a new message is processed. You can use the lCount parameter to determine the relative length of time the application has been idle without processing a message.ResOverride this member function to perform idle-time processing. OnIdle is called in the default message loop when the application’s message queue is empty. Use your override to call your own background idle-handler tasks.OnIdle should return 0 to indicate that no idle processing time is required. The lCount parameter is incremented each time OnIdle is called when the message  queue is empty and resets to 0 each time a new message is processed. You can call your different idle routines based on this count.The following summarizes idle loop processing: If the message loop in the Microsoft Foundation Class Library checks the message queue and finds no pending messages, it calls OnIdle for the application object and supplies 0 as the lCount argument.
    OnIdle performs some processing and returns a nonzero value to indicate it should be called again to do further processing.
    The message loop checks the message queue again. If no messages are pending, it calls OnIdle again, incrementing the lCount argument.
    Eventually, OnIdle finishes processing all its idle tasks and returns 0. This tells the message loop to stop calling OnIdle until the next message is received from the message queue, at which point the idle cycle restarts with the argument set to 0. 
    Do not perform lengthy tasks during OnIdle because your application cannot process user input until OnIdle returns.Note   The default implementation of OnIdle updates command user-interface objects such as menu items and toolbar buttons, and it performs internal data structure cleanup. Therefore, if you override OnIdle, you must call CWinApp::OnIdle with the lCount in your overridden version. First call all base-class idle processing (that is, until the base class OnIdle returns 0). If you need to perform work before the base-class processing completes, review the base-class implementation to select the proper lCount during which to do your work.ExampleThe following two examples show how to use OnIdle. The first example processes two idle tasks using the lCount argument to prioritize the tasks. The first task is high priority, and you should do it whenever possible. The second task is less important and should be done only when there is a long pause in user input. Note the call to the base-class version of OnIdle. The second example manages a group of idle tasks with different priorities.BOOL CMyApp::OnIdle(LONG lCount)
    {
        BOOL bMore = CWinApp::OnIdle(lCount);    if (lCount == 0)
        {
        TRACE("App idle for short period of time\n");
        bMore = TRUE;
        }
        else if (lCount == 10)
        {
        TRACE("App idle for longer amount of time\n");
            bMore = TRUE;
        }
        else if (lCount == 100)
        {
            TRACE("App idle for even longer amount of time\n");
            bMore = TRUE;
        }
        else if (lCount == 1000)
        {
            TRACE("App idle for quite a long period of time\n");
         // bMore is not set to TRUE, no longer need idle
         // IMPORTANT: bMore is not set to FALSE since CWinApp::OnIdle may
         // have more idle tasks to complete.
        }    return bMore;
         // return TRUE as long as there is any more idle tasks
    }Second Example// In this example, four idle loop tasks are given various 
    // opportunities to run:
    // Task1 is always given a chance to run during idle time, provided
    //   that no message has queued up while the framework was processing
    //   its own idle loop tasks (at lCount levels 0 and 1).
    // Task2 is given a chance to run only if Task1 has already run,
    //   provided that no message has queued up while Task1 was running.
    // Task3 and Task4 are given a chance to run only if both Task1 and
    //   Task2 have already run, and no message has queued up in the mean
    //   time.  If Task3 gets its chance to run, then Task4 always gets
    //   a chance to run immediately after Task3.BOOL CMyApp::OnIdle(LONG lCount)
    {
       // In this example, as in most applications, you should let the
       // base class CWinApp::OnIdle complete its processing before you
       // attempt any additional idle loop processing.
       if (CWinApp::OnIdle(lCount))
          return TRUE;      // The base class CWinApp::OnIdle reserves the lCount values 0 
       // and 1 for the framework's own idle processing.   If you wish to
       // share idle processing time at a peer level with the framework,
       // then replace the above if-statement with a straight call to
       // CWinApp::OnIdle; and then add a case statement for lCount value
       // 0 and/or 1. Study the base class implementation first to 
       // understand how your idle loop tasks will compete with the 
       // framework's idle loop processing.   switch (lCount)
       {
          case 2:
             Task1();
             return TRUE; // next time give Task2 a chance
          case 3:
             Task2();
             return TRUE; // next time give Task3 and Task4 a chance
          case 4:
             Task3();
             Task4();
             return FALSE; // cycle through the idle loop tasks again
       }
       return FALSE;
    }
      

  6.   

    你的办法(MSDN)只能分出很小的时间段,如果是两分钟(或几分钟)就不好办了,因为lCount很难达到一个很大的数象9000等,这就限制了它的作用。
      

  7.   

    设你的程序可以处理n个task: task1()...taskn();每开始一个任务可以是选择菜单,按钮等方法。设一全局变量g_bTaskRunning=false;
    clock_t   lastTaskTimestamp;
    void task1()
    {
    g_btaskrunning=true;
    //process task here/g_btaskrunning=false;
    lastTaskTimestamp=clock();}然后可以使用timer或waitabletimer定时检查当前时间与lastTaskTimestamp的间隔。如果你的task是多线程处理的,需要有同步手段。应该没什么问题
      

  8.   

    你的程序是空闲的,并不代表电脑的使用着是空闲的,比如,如果我把你写好的程序暂时最小化了,然后忙着上网。如果你给我来一幅flash什么的,我会考虑卸载那个程序.
         因此,应该检测用户输入(mouse+keyboard)的空闲时间.在win2000/xp下有API,9x下可能得写hook自己统计.
      

  9.   

    2000下面有GetLastInputInfo(),这个函数使用结构 LASTINPUTINFO 作为参数:LASTINPUTINFO lpi;
    lpi.cbSize = sizeof(lpi);
    GetLastInputInfo(&lpi);调用函数GetLastInputInfo()以后, 结构成员lpi.dwTime 中的值便是自上次输入事件发生以后的毫秒数。这个值也就是键盘、鼠标处于空闲状态的时间。9x下面要通过钩子来实现。
    引用:HHOOK g_hHookKbd = NULL;
    HHOOK g_hHookMouse = NULL;在Windows中,一个系统(相对于一个特定进程而言)钩子必须用一个动态链接库(DLL)来实现。不妨将这个动态链接库命名为IdleUI.dll。 这个动态链接库在Windows 9x和Windows NT4.0中实现了GetLastInputInfo()的功能。IdleUI.dll中有三个函数:BOOL IdleUIInit()
    void IdleUITerm();
    DWORD IdleUIGetLastInputTime();IdleUIInit()是环境初始化函数,IdleUITerm()是环境清理函数,分别在MFC应用程序的InitInstance() 和 ExitInstance()中调用它们。当用IdleUIInit()做完初始化后,就可以调用第三个函数IdleUIGetLastInputTime()来获取最后一次输入事件后的时钟。从而实现与GetLastInputInfo()一样的功能。程序TestIdleUI.exe是用来测试IdleUI动态库的,程序中调用了IdleUIInit 和 IdleUITerm,同时在程序的客户区中间显示键盘、鼠标空闲的秒数。void CMainFrame::OnPaint()
    {
    CPaintDC dc(this);
    CString s;
    DWORD nsec = (GetTickCount() - IdleUIGetLastInputTime())/1000;
    s.Format( "鼠标或键盘空闲 %d 秒。",nsec);
    CRect rc;
    GetClientRect(&rc);
    dc.DrawText(s, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
    }为了连续的显示,TestIdleUI设置刷新定时器间隔为一秒。void CMainFrame::OnTimer(UINT)
    {
    Invalidate();
    UpdateWindow();
    }运行TestIdleUI,当键盘和鼠标什么也不做时,可以看到计时器跳动,当移动鼠标或按键时,计时器又恢复到零,这样就实现了对输入设备空闲状态的监控。实现细节请看下面对IdleUI.dll工作原理的描述:首先调用IdleUIInit ()进行初始化,安装两个钩子:一个用于监控鼠标输入,一个用于监控键盘输入。HHOOK g_hHookKbd;
    HHOOK g_hHookMouse;
    g_hHookKbd = SetWindowsHookEx(WH_KEYBOARD,
    MyKbdHook, 
    hInst, 0);
    g_hHookMouse = SetWindowsHookEx(WH_MOUSE,
    MyMouseHook, 
    hInst, 0);当用户移动鼠标或按下键盘键时,Windows调用其中的一个钩子并且钩子函数开始记录时间: LRESULT CALLBACK MyMouseHook(int code, 
    WPARAM wp, 
    LPARAM lp)
    {
    if (code==HC_ACTION) {
    // note the tick count
    g_dwLastInputTick = GetTickCount();
    }
    return ::CallNextHookEx(g_hHookMouse,
    code, wp, lp);
    }如法炮制MyKbdHook。IdleUIGetLastInputTime 返回结果g_dwLastInputTick, 并且IdleUITerm 卸载两个钩子。这个程序中有一个细节使用了一些技巧:通常,建立一个动态链接库时,链接器将静态数据标记为非共享,也就是说,每一个调用DLL的进程都获得自己的数据拷贝------在本程序中是g_hHookKbd、g_hHookMouse和g_dwLastInputTick。当在整个进程空间中需要且只需要一个这些数据的实例时,这样的静态数据标记就不适合了,为了解决这个问题,必须实现数据共享。为此得把数据放入一个特定的段地址中,然后将它们标记为共享。实现代码如下:#pragma data_seg (".IdleUI") // 可以取任何别的名字
    HHOOK g_hHookKbd = NULL;
    HHOOK g_hHookMouse = NULL;
    DWORD g_dwLastInputTick = 0;
    #pragma data_seg ()这段代码告诉链接器将三个变量放到叫“.IdleUI”的数据段中。然后在模块定义文件.DEF中加入下面的代码来共享这个数据段:SECTIONS .IdleUI READ WRITE SHARED // in IdleUI.def  
     
     
     
     
      

  10.   

    为什么不去取CPU的占用率?就向性能监视器所做的工作一样。
    当然,我没有写过一个VC++的软件。
      

  11.   

    在用户很长一段时间内无动作的时候?checking input then