自绘一个位图按钮,重载了DrawItem,设置了按钮在普通状态和按下状态的不同的样式。但是我发现在快速点击按钮的时候,它的按下和弹起反应不是很即时。我用了一下CButtonST,它的好像没有这个问题。这是怎么造成的呢?

解决方案 »

  1.   

    是不是你只重载了DrawItem,而没有重载鼠标消息响应函数LBUTTONDOWN LBUTTONUP呢?
      

  2.   

    1.那你先参考一下CButtonST的代码,和你的有什么不同,会不会就是这这不同造成的呢?
    2.另外不仅仅是重载DrawItem就可以的,你还得响应BN_CLICKED消息,在内部调用Invalidate,刷新按钮
      

  3.   

    drawitem的效率要提高,不然太快切换的话就卡在drawitem那里了
      

  4.   

    不知道是不是双击造成的影响,因为我发现鼠标定在一个点上不动,快速点击,它会反应不过来。但是点击的过程中鼠标一边慢慢移动,反应是即时的。我用了下CButtonST的Demo,它确实解决了这个问题啊,但不知是怎么做到的。
      

  5.   

    看一下CPU占用和内存占用,确认问题的响应造成
      

  6.   


    我把DrawItem全部注释掉了,这样只能看到灰色的一片,可我点击的时候它还是反应不过来啊!
      

  7.   

    CButton屏蔽了双击消息,
    是不是没有按钮没有刷新?
    你有没有响应BN_CLICKED消息,在内部调用Invalidate
      

  8.   

    CButtonST屏蔽了双击消息, 
      

  9.   

    笔者编写了一个小演示程序,简单模拟电器开关功能。它有两个位图按钮和一个用作状态显示屏的编辑控制框。当鼠标位于位图按钮之上时,状态显示屏均显示"鼠标的光标在位图按钮上"。电源开关开时,按“喇叭”位图按钮则会发声;否则“喇叭”位图按钮变灰,不起作用。   
        
      void   CBmpDlg::OnMouseMove(UINT   nFlags,   CPoint   point)   
        
      {   
        
      CWnd   *   pWnd;     
        
      HCURSOR   MyCursor;     
        
      CRgn   m_regionPower;   //Region   of   POWER   Button   
        
      CRgn   m_regionPlay;   //Region   of   PLAY   Button   
        
      //建立位图按钮的矩形区域   
        
      m_regionPower.CreateEllipticRgnIndirect(CRect(27,56,72,92));     
        
      m_regionPlay.CreateEllipticRgnIndirect(CRect(78,56,120,92));   
        
      CString   ShowString0   =   "鼠标的光标在位图按钮上!!!";   
        
      …   …   …   …   
        
      m_bPlay   =   FALSE;   
        
      m_bPower=   FALSE;   
        
      if   (m_regionPower.PtInRegion(point))   //鼠标落在位图按钮之上     
        
      {   
        
      m_bPower   =   TRUE;     
        
      //将位图按钮设置成获得输入状态   
        
      pWnd=   GetDlgItem(IDC_BUTTON_POWER);   
        
      pWnd->SetFocus();     
        
      SetCapture();   
        
      InputEdit().SetWindowText(ShowString0);   
        
      InputEdit().ShowWindow(TRUE);     
        
      //将鼠标光标变成小手形状   
        
      MyCursor   =   AfxGetApp()->LoadCursor(IDC_MYCURSOR);     
        
      ::SetCursor(MyCursor);   
        
      VERIFY(m_Play.LoadBitmaps("PLAYU","PLAYD","PLAYF","PLAYX"));   
        
      m_bPressedPlay   =   FALSE;   
        
      return;   
        
      }   
        
      if   (m_regionPlay.PtInRegion(point))   //鼠标落在位图按钮之上     
        
      {     
        
      if   (m_bPowerOn)   {   //如果电源已被开启   
        
      m_bPlay   =   TRUE;     
        
      pWnd=   GetDlgItem(IDC_BUTTON_PLAY);   
        
      pWnd->SetFocus();     
        
      SetCapture();   
        
      InputEdit().SetWindowText(ShowString0);   
        
      InputEdit().ShowWindow(TRUE);   
        
      MyCursor   =   AfxGetApp()->LoadCursor(IDC_MYCURSOR);   
        
      ::SetCursor(MyCursor);     
        
      VERIFY(m_Power.LoadBitmaps("POWERONU","POWEROND","POWERONF"));   
        
      }   
        
      else   {   //如果电源已被关闭   
        
      ReleaseCapture();   
        
      InputEdit().SetWindowText(ShowString0+ShowString2);   
        
      InputEdit().ShowWindow(TRUE);     
        
      VERIFY(m_Power.LoadBitmaps("POWEROFU","POWEROFD","POWEROFF"));   
        
      }     
        
      m_bPressedPower=   FALSE;   
        
      return;   
        
      }   
        
      //鼠标落在所有的位图按钮之外     
        
      ReleaseCapture();   
        
      InputEdit().SetWindowText(ShowString1);   
        
      InputEdit().ShowWindow(TRUE);     
        
      pWnd=   GetDlgItem(IDOK);   
        
      pWnd->SetFocus();     
        
      VERIFY(m_Play.LoadBitmaps("PLAYU","PLAYD","PLAYF","PLAYX"));   
        
      if   (m_bPowerOn)   
        
      VERIFY(m_Power.LoadBitmaps("POWERONU","POWEROND","POWERONF"));   
        
      else   
        
      VERIFY(m_Power.LoadBitmaps("POWEROFU","POWEROFD","POWEROFF"));   
        
      m_bPressedPlay   =   FALSE;   
        
      m_bPressedPower=   FALSE;   
        
      CDialog::OnMouseMove(nFlags,   point);   
        
      }   
        
      void   CBmpDlg::OnLButtonDown(UINT   nFlags,   CPoint   point)   
        
      {   
        
      CWnd   *pWnd;   
        
      if   (m_bPlay   &&   m_bPowerOn)   {     
        
      //   Change   Focus   so   as   to   Change   the   bitmap   of   m_Play   
        
      pWnd=   GetDlgItem(IDOK);   
        
      pWnd->SetFocus();     
        
      VERIFY(m_Play.LoadBitmaps("PLAYD"));   
        
      m_Play.UpdateWindow();   
        
      m_Play.Invalidate(TRUE);   
        
      OnButtonPlay();     
        
      m_bPressedPlay   =   TRUE;   
        
      }     
        
      if   (m_bPower==   TRUE)   {     
        
      //   Change   Focus   so   as   to   Change   the   bitmap   of   m_Power   
        
      pWnd=   GetDlgItem(IDOK);   
        
      pWnd->SetFocus();     
        
      if   (m_bPowerOn)   
        
      VERIFY(m_Power.LoadBitmaps("POWEROND"));   
        
      else   
        
      VERIFY(m_Power.LoadBitmaps("POWEROFD"));     
        
      m_Power.UpdateWindow();   
        
      m_Power.Invalidate(TRUE);   
        
      OnButtonPower();     
        
      m_bPressedPower   =   TRUE;   
        
      }     
        
      CDialog::OnLButtonDown(nFlags,   point);   
        
      }   
        
          
        
      void   CBmpDlg::OnLButtonUp(UINT   nFlags,   CPoint   point)   
        
      {   
        
      CWnd   *   pWnd;     
        
      if   (m_bPressedPlay   ==   TRUE)   {   
        
      pWnd=   GetDlgItem(IDOK);   
        
      pWnd->SetFocus();     
        
      VERIFY(m_Play.LoadBitmaps("PLAYF"));   
        
      m_Play.UpdateWindow();   
        
      m_Play.Invalidate(TRUE);   
        
      m_bPressedPlay   =   FALSE;   
        
      }     
        
      if   (m_bPressedPower   ==   TRUE)   {   
        
      pWnd=   GetDlgItem(IDOK);   
        
      pWnd->SetFocus();     
        
      if   (m_bPowerOn)   
        
      VERIFY(m_Power.LoadBitmaps("POWERONF"));   
        
      else   
        
      VERIFY(m_Power.LoadBitmaps("POWEROFF"));     
        
      m_Power.UpdateWindow();   
        
      m_Power.Invalidate(TRUE);   
        
      m_bPressedPower   =   FALSE;   
        
      }     
        
      CDialog::OnLButtonUp(nFlags,   point);   
        
      }   你可以参照一下
      

  10.   

    CButtonST貌似是重载了按钮的PreTranslateMessage,如果是鼠标双击消息WM_LBUTTONDBLCLK时,则替换为鼠标单击消息WM_LBUTTONDOWN
      

  11.   

    我响应了OnLButtonDblClk,里面什么也不做。也响应了OnBnClicked,里面做Invalidate(),还是没效果。
      

  12.   

    不能这样,你点击太快就成了双击了,就不会刷新按钮
    LRESULT CXXButton::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    {
    if (message == WM_LBUTTONDBLCLK)
    {
    message = WM_LBUTTONDOWN; //在这里屏蔽双击消息
    }
    return CButton::DefWindowProc(message, wParam, lParam);
    } // End of DefWindowProc
      

  13.   

    绘制消息属于低优先级消息,只有线程空闲才处理绘制,在其它消息(鼠标键盘)没有处理完之前,绘制消息只能在队列中排队,而且队列中的多个绘制消息会合并成一个。如果快速点击鼠标,各种鼠标消息将优先处理,按钮状态不停改变,等到绘制消息有机会处理的时候,按钮的状态已经回到了原始状态,所以绘制的还是原始状态。如果发生这种情况,说明鼠标消息的响应函数过于耗时才导致线程没机会进入空闲状态,绘制消息不会立即发生。如果希望见到立即改变,可以在每个鼠标消息处理完之后立即调用RedrawWindow,它会立即进入绘制过程。