如下托盘程序,在主线程中计时,子线程中用Textout()显示,用Invalidate()显示为何明显抖动?
program.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by RES.rc
//
#define IDI_ICON1                       102
#define IDI_ICON2                       103
#define IDR_MENU1                       105
#define IDB_BITMAP1                     108
#define ID_EXIT                         40001// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        110
#define _APS_NEXT_COMMAND_VALUE         40011
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endifprogram.cpp
#include<afxwin.h>
#include"program.h"
#define WM_THREADEXIT WM_USER+103
#define WM_SHOWTHREAD WM_USER+100
#define WM_THREADQUIT WM_USER+107
BOOL threadflag=FALSE;
static HWND thexit;
NOTIFYICONDATA nid; 
class mywindow: public CFrameWnd
{  public:
mywindow();
~mywindow();
BOOL PreCreateWindow(CREATESTRUCT &cs)
{
cs.hMenu=LoadMenu(NULL,MAKEINTRESOURCE(IDR_MENU1));
return CFrameWnd::PreCreateWindow(cs);
}
afx_msg void OnExit()
{
   PostMessage(WM_CLOSE);
}
afx_msg void OnPaint()
{  CPaintDC paintDC(this);
   paintDC.TextOut(20,20,"亲爱的,你好");
}
afx_msg void OnThreadQuit()
{
   PostMessage(WM_CLOSE);
}

DECLARE_MESSAGE_MAP()
};
mywindow::mywindow()
{
Create(NULL,"用户界面线程"); 
thexit=GetSafeHwnd();
}
mywindow::~mywindow()
{
threadflag=FALSE;
}
class UIthread: public CWinThread
{
DECLARE_DYNCREATE(UIthread)
public:
BOOL InitInstance()
{
CFrameWnd *mythread=new mywindow;
m_pMainWnd=mythread;
mythread->ShowWindow(SW_SHOW);
return TRUE;
}
};
IMPLEMENT_DYNCREATE(UIthread,CWinThread)
BEGIN_MESSAGE_MAP(mywindow,CFrameWnd)
ON_COMMAND(ID_EXIT,OnExit)
ON_WM_PAINT()
ON_MESSAGE(WM_THREADQUIT,OnThreadQuit)
END_MESSAGE_MAP()
class myframewindow: public CFrameWnd
{  public:
myframewindow();
~myframewindow();
afx_msg void OnPaint()
{  CPaintDC paintDC(this);
   paintDC.TextOut(10,5,"这是主线程窗口程序");
}
afx_msg void OnWinexit()
{
PostMessage(WM_CLOSE);
}
afx_msg void OnThreadExit()
{
::PostMessage(thexit,WM_THREADQUIT,0,0);
}
void enablewin(CCmdUI *PCmd);
afx_msg LRESULT onshowthread(WPARAM wParam,LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
myframewindow::myframewindow()
{
  Create(NULL,(LPCTSTR)"这是主线程窗口");
}
myframewindow::~myframewindow()
{
  Shell_NotifyIcon(NIM_DELETE,&nid);
}
void myframewindow::enablewin(CCmdUI *PCmd)
{
PCmd->Enable(threadflag);
}LRESULT myframewindow::onshowthread(WPARAM wParam,LPARAM lParam)
{
if(wParam!=IDI_ICON1)
return 0;
switch(lParam)
{ case WM_RBUTTONUP: 
{
  LPPOINT lpoint=new tagPOINT;
  GetCursorPos(lpoint);
  CMenu menu;
  menu.CreatePopupMenu();  
  menu.AppendMenu(MF_STRING,WM_DESTROY,"退  出");
  menu.AppendMenu(MF_SEPARATOR);
  menu.AppendMenu(MF_STRING,WM_THREADEXIT,"关闭窗口");
  ::SetForegroundWindow(nid.hWnd);
  menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
  HMENU hmenu=menu.Detach();
  menu.DestroyMenu();
  delete lpoint;
      }
break;
case WM_LBUTTONDBLCLK:
{
if(!threadflag)
{ AfxBeginThread(RUNTIME_CLASS(UIthread)); threadflag=TRUE; }
 
}
}
return 1;
}BEGIN_MESSAGE_MAP(myframewindow,CFrameWnd)
ON_WM_PAINT()
ON_COMMAND(WM_DESTROY,OnWinexit)
ON_COMMAND(WM_THREADEXIT,OnThreadExit)
ON_UPDATE_COMMAND_UI(WM_THREADEXIT,enablewin)
ON_MESSAGE(WM_SHOWTHREAD,onshowthread)
END_MESSAGE_MAP()class mainthd: public CWinApp
{
public:
mainthd(): CWinApp("Main Thread!"){}
BOOL InitInstance()
{
HICON hIcon=LoadIcon(IDI_ICON2);
CFrameWnd *myframe=new myframewindow;
m_pMainWnd=myframe;
nid.cbSize=sizeof(NOTIFYICONDATA);
nid.hWnd=myframe->m_hWnd;
nid.uID=IDI_ICON1;
nid.uFlags=NIF_ICON|NIF_TIP|NIF_MESSAGE;
nid.uCallbackMessage=WM_SHOWTHREAD;
nid.hIcon=LoadIcon(IDI_ICON1);
strcpy(nid.szTip,"用户界面线程及托盘演示");
Shell_NotifyIcon(NIM_ADD,&nid);
myframe->SetIcon(hIcon,FALSE);
myframe->ShowWindow(SW_HIDE);
return TRUE;
}
}mainthread;然后在设置里用FMC表态链接,我想知道如何添加program.rc文件?加入托盘图标?

解决方案 »

  1.   

    Invalidate() 改称  InvalidateRect()
      

  2.   

    用Invalidate(FALSE);
    InvalidateRect()也不错
      

  3.   

    减轻抖动,请用双缓冲技术
    搜索一下,so much
      

  4.   

    用Invalidate(FALSE);
    InvalidateRect()用过有减轻。双缓冲没用过程序如下请帮修正:是不是线程序通信有问题?#include<afxwin.h>
    #include"resource.h"
    #define WM_THREADEXIT WM_USER+103
    #define WM_SHOWTHREAD WM_USER+100
    #define WM_THREADQUIT WM_USER+107
    BOOL threadflag=FALSE;
    BOOL m_bStayOnTop=TRUE;
    static HWND thexit;
    NOTIFYICONDATA nid; 
    CString m_nTime;
    static int m_count=0; 
    CEdit m_wndEdit;
    class mywindow: public CFrameWnd
    {  public:
    mywindow(); ~mywindow();
    void SetTopMostState ()
    {
        CMenu* pMenu = GetSystemMenu (FALSE);    if (!m_bStayOnTop) {
            SetWindowPos (&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            pMenu->CheckMenuItem (IDM_SYSMENU_STAY_ON_TOP, MF_CHECKED);
        }       
        else {
            SetWindowPos (&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            pMenu->CheckMenuItem (IDM_SYSMENU_STAY_ON_TOP, MF_UNCHECKED);
        }
    }
    BOOL PreCreateWindow(CREATESTRUCT &cs)
    {
    cs.hMenu=LoadMenu(NULL,MAKEINTRESOURCE(IDR_MENU1));

    return CFrameWnd::PreCreateWindow(cs);
    }
    afx_msg void OnExit()
    {
       PostMessage(WM_CLOSE);
    }afx_msg void OnSysCommand (UINT nID, LPARAM lParam)
    {
        UINT nMaskedID = nID & 0xFFF0;  if (nMaskedID == IDM_SYSMENU_STAY_ON_TOP) {
              m_bStayOnTop = m_bStayOnTop ? 0 : 1;
            SetTopMostState ();
            return;
        }
        CWnd::OnSysCommand (nID, lParam);
    }



    afx_msg void OnPaint()
    {  
          CPaintDC dc(this);
     

         CRect rect;
         CFont m_tFont;
         m_tFont.CreatePointFont(280,_T ("宋体"));
        CFont* pOldFont = dc.SelectObject (&m_tFont);
        GetClientRect (&rect);
        dc.SetViewportOrg (rect.Width () / 2, rect.Height () / 2);
        dc.TextOut(-80,-20,_T(m_nTime));     Invalidate(false);
          dc.SelectObject (pOldFont);
    }
            
    afx_msg int OnCreate (LPCREATESTRUCT lpcs)
    {    if (CFrameWnd::OnCreate (lpcs) == -1)
            return -1;
        if (!SetTimer (2, 1000, NULL)) {
            MessageBox (_T ("Error: SetTimer failed"));
            return -1;
        }
    CMenu* pMenu = GetSystemMenu (FALSE);
     pMenu->AppendMenu (MF_SEPARATOR);
      pMenu->AppendMenu (MF_STRING, IDM_SYSMENU_STAY_ON_TOP,
            _T ("Stay on To&p"));    return 0; }
    afx_msg void OnTimer (UINT nTimerID)
    {
      CTime time = CTime::GetCurrentTime ();
        m_nTime.Format(_T("%0.2d:%0.2d:%0.2d"),int(m_count/3600),m_count%3600/60,m_count%60);
     
    } afx_msg void OnThreadQuit()
    {
       PostMessage(WM_CLOSE); }

    DECLARE_MESSAGE_MAP()
    };
    mywindow::mywindow()
    {
    CBrush brush;
    brush.CreateSolidBrush(RGB(100,255,200));
     CString strWndClass = AfxRegisterWndClass (
            0,
            AfxGetApp ()->LoadStandardCursor (IDC_ARROW),
            (HBRUSH) (COLOR_WINDOW + 1),
            AfxGetApp ()->LoadStandardIcon (IDI_APPLICATION)    ); CreateEx (0, strWndClass,  _T ("用户界面线程"),
            WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL);
        CRect rect (0, 0, 200, 80);
        CalcWindowRect (&rect);    SetWindowPos (NULL, 0, 0, rect.Width (), rect.Height (),
             SWP_NOMOVE );
     thexit=GetSafeHwnd();}mywindow::~mywindow()
    {
    threadflag=FALSE;
    }class UIthread: public CWinThread
    {
    DECLARE_DYNCREATE(UIthread)
    public:
    BOOL InitInstance()
    {
    CFrameWnd *mythread=new mywindow;
    m_pMainWnd=mythread;
    mythread->ShowWindow(SW_SHOW);
    return TRUE;
    }
    };
    IMPLEMENT_DYNCREATE(UIthread,CWinThread)
    BEGIN_MESSAGE_MAP(mywindow,CFrameWnd)
    ON_COMMAND(ID_EXIT,OnExit)
    ON_WM_SYSCOMMAND()
    ON_WM_CREATE ()
    ON_WM_TIMER ()
    ON_WM_PAINT()
    ON_MESSAGE(WM_THREADQUIT,OnThreadQuit)
    END_MESSAGE_MAP()class myframewindow: public CFrameWnd
    {  public:
    myframewindow();
    ~myframewindow();
    afx_msg int OnCreate (LPCREATESTRUCT lpcs)
    {
        if (CFrameWnd::OnCreate (lpcs) == -1)
            return -1;    if (!SetTimer (1, 1000, NULL)) {
            MessageBox (_T ("Error: SetTimer failed"));
            return -1;
        }
        return 0;
    }
    afx_msg void OnTimer (UINT nTimerID)
    {
      CTime time = CTime::GetCurrentTime (); m_count++;
        m_nTime.Format(_T("%0.2d:%0.2d:%0.2d"),int(m_count/3600),m_count%3600/60,m_count%60);}
    afx_msg void OnPaint()
    {      

    } afx_msg void OnWinexit()
    {
    PostMessage(WM_CLOSE);
    } afx_msg void OnThreadExit()
    {
    ::PostMessage(thexit,WM_THREADQUIT,0,0);
    BOOL m_bStayOnTop=TRUE;
    } void enablewin(CCmdUI *PCmd);
    afx_msg LRESULT onshowthread(WPARAM wParam,LPARAM lParam);
    DECLARE_MESSAGE_MAP()
    };
    myframewindow::myframewindow()
    {
      Create(NULL,(LPCTSTR)"这是主线程窗口");
        
    } myframewindow::~myframewindow()
    {
      Shell_NotifyIcon(NIM_DELETE,&nid);
    }
    void myframewindow::enablewin(CCmdUI *PCmd)
    {
    PCmd->Enable(threadflag);
    }LRESULT myframewindow::onshowthread(WPARAM wParam,LPARAM lParam)
    {
    if(wParam!=IDI_ICON1)
    return 0;
    switch(lParam)
    { case WM_RBUTTONUP: 
    {
      LPPOINT lpoint=new tagPOINT;
      GetCursorPos(lpoint);
      CMenu menu;
      menu.CreatePopupMenu();  
      menu.AppendMenu(MF_STRING,WM_DESTROY,"退  出");
      menu.AppendMenu(MF_SEPARATOR);
      menu.AppendMenu(MF_STRING,WM_THREADEXIT,"关闭窗口");
      ::SetForegroundWindow(nid.hWnd);
      menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
      HMENU hmenu=menu.Detach();
      menu.DestroyMenu();
      delete lpoint;
          }
    break;
    case WM_LBUTTONDOWN:
    {
    if(!threadflag)
    { AfxBeginThread(RUNTIME_CLASS(UIthread)); threadflag=TRUE; }
     
    }
    }
    return 1;
    }BEGIN_MESSAGE_MAP(myframewindow,CFrameWnd)
    ON_WM_PAINT()
    ON_COMMAND(WM_DESTROY,OnWinexit)
    ON_COMMAND(WM_THREADEXIT,OnThreadExit)
    ON_UPDATE_COMMAND_UI(WM_THREADEXIT,enablewin)
    ON_MESSAGE(WM_SHOWTHREAD,onshowthread)
    ON_WM_CREATE ()
    ON_WM_TIMER ()END_MESSAGE_MAP()class mainthd: public CWinApp
    {
    public:
    mainthd(): CWinApp("Main Thread!"){}
    BOOL InitInstance()
    {
    HICON hIcon=LoadIcon(IDI_ICON2);
    CFrameWnd *myframe=new myframewindow;
    m_pMainWnd=myframe;
    nid.cbSize=sizeof(NOTIFYICONDATA);
    nid.hWnd=myframe->m_hWnd;
    nid.uID=IDI_ICON1;
    nid.uFlags=NIF_ICON|NIF_TIP|NIF_MESSAGE;
    nid.uCallbackMessage=WM_SHOWTHREAD;
    nid.hIcon=LoadIcon(IDI_ICON1);
    strcpy(nid.szTip,"用户界面线程及托盘演示");
    Shell_NotifyIcon(NIM_ADD,&nid);
    myframe->SetIcon(hIcon,FALSE);
    myframe->ShowWindow(SW_HIDE);
    return TRUE;
    }
    }mainthread;
      

  5.   

    Invalidate(FALSE);重画的时候不擦除背景
    InvalidateRect()只刷新指定的rect
    当然双缓冲效果更好
      

  6.   

    对使用双缓冲技术。。就可以填补这个BUG了。
      

  7.   

    这里说的双缓冲是指创建一个后台DC,在上面画后再blt到前台窗口,如何创建后台DC和如何添加托盘图标,很多文章都有介绍。
      

  8.   

    REDRAWWINDOW加INVALIDATE参数和INVALIDATE(false)效果一样,你有还有别的方法没有