• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            tqsheng

            go.....
            隨筆 - 366, 文章 - 18, 評論 - 101, 引用 - 0
            數據加載中……

            Visual C++窗體設計技巧集

            [前言:]有好的界面軟件就成功了一半,本文將向您介紹怎樣設計一些有“稀奇古怪”形狀的窗體,如何設定窗體的顏色、如何設置任務欄和狀態欄以及菜單圖標等等,通過這些技巧能更深入的理解VC的文檔-視圖結構。   如何制作透明窗體   使用SetLayeredWindowAttributes可以方便的制作透明窗體,此函數在w2k以上才支持,而且如果希望直接使用的話,可能需要下載最新的SDK。不過此函數在w2k的user32.dll里有實現,所以如果你不希望下載巨大的sdk的話,可以直接使用GetProcAddress獲取該函數的指針。   SetLayeredWindowAttributes的函數原型如下: BOOL SetLayeredWindowAttributes( HWND hwnd, // handle to the layered window COLORREF crKey, // specifies the color key BYTE bAlpha, // value for the blend function DWORD dwFlags // action ); Windows NT/2000/XP: Included in Windows 2000 and later. Windows 95/98/Me: Unsupported.(注意了,在win9x里沒法使用的) Header: Declared in Winuser.h; include Windows.h. Library: Use User32.lib.   一些常量: WS_EX_LAYERED = 0x80000; LWA_ALPHA = 0x2; LWA_COLORKEY=0x1;   其中dwFlags有LWA_ALPHA和LWA_COLORKEY   LWA_ALPHA被設置的話,通過bAlpha決定透明度.   LWA_COLORKEY被設置的話,則指定被透明掉的顏色為crKey,其他顏色則正常顯示.   要使使窗體擁有透明效果,首先要有WS_EX_LAYERED擴展屬性(舊的sdk沒有定義這個屬性,所以可以直接指定為0x80000).   例子代碼:   在OnInitDialog()加入: //加入WS_EX_LAYERED擴展屬性 SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE, GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)|0x80000); HINSTANCE hInst = LoadLibrary("User32.DLL"); if(hInst) {  typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);  MYFUNC fun = NULL;  //取得SetLayeredWindowAttributes函數指針  fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");  if(fun)fun(this->GetSafeHwnd(),0,128,2);  FreeLibrary(hInst); }   稍加修改還可以作出淡出淡入的效果. 注意第三個參數(128)不要取得太小了,為0的話就完全透明,看不到了。   如何使框架窗口的圖標為動畫顯示   可以用TIMER,但是TIMER不能有效的定時。因為TIMER發送的是窗口消息,當窗口忙于處理鍵盤、鼠標等消息時就不能及時處理TIMER,會使間隔時間變得很長 。   可以考慮用一個單獨得TIMER線程,用Sleep()定時來解決此問題。 UINT Timer(LPVOID param) {  HWND hWnd=(HWND)param;  while(1)  {   Sleep(ms);   PostMessage(hWnd,CH_PICTURE,NULL,NULL)  } }   Sleep(ms)后發送自定義消息。消息處理函數就選擇某一個ICON或BITMAP來顯示。如 : MyBotton.SetBitmap((HBITMAP)Bitmap[i]);   Bitmap是一個位圖數組,存放有j個位圖。消息處理函數運行一次,i就累加一次,當i==j時,i就回到0;   防止窗口閃爍的方法   1、將Invalidate()替換為InvalidateRect()。   Invalidate()會導致整個窗口的圖象重畫,需要的時間比較長,而InvalidateRect()僅僅重畫Rect區域內的內容,所以所需時間會少一些。蟲蟲以前很懶,經常為一小塊區域的重畫就調用Invalidate(),不愿意自己去計算需要重畫的Rect,但是事實是,如果你確實需要改善閃爍的情況,計算一個Rect所用的時間比起重畫那些不需要重畫的內容所需要的時間要少得多。   2、禁止系統搽除你的窗口。   系統在需要重畫窗口的時候會幫你用指定的背景色來搽除窗口。可是,也許需要重畫的區域也許非常小。或者,在你重畫這些東西之間還要經過大量的計算才能開始。這個時候你可以禁止系統搽掉原來的圖象。直到你已經計算好了所有的數據,自己把那些需要搽掉的部分用背景色覆蓋掉(如:dc.FillRect(rect,&brush);rect是需要搽除的區域,brush是帶背景色的刷子),再畫上新的圖形。要禁止系統搽除你的窗口,可以重載OnEraseBkgnd()函數,讓其直接返回TRUE就可以了。如 BOOL CMyWin::OnEraseBkgnd(CDC* pDC) { return TRUE; //return CWnd::OnEraseBkgnd(pDC);//把系統原來的這條語句注釋掉。 }   3、有效的進行搽除。   搽除背景的時候,不要該搽不該搽的地方都搽。比如,你在一個窗口上放了一個很大的Edit框,幾乎占了整個窗口,那么你頻繁的搽除整個窗口背景將導致Edit不停重畫形成劇烈的閃爍。事實上你可以CRgn創建一個需要搽除的區域,只搽除這一部分。如 GetClientRect(rectClient); rgn1.CreateRectRgnIndirect(rectClient); rgn2.CreateRectRgnIndirect(m_rectEdit); if(rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR) == ERROR)//處理后的rgn1只包括了Edit框之外的客戶區域,這樣,Edit將不會被我的背景覆蓋而導致重畫。 { ASSERT(FALSE); return ; } brush.CreateSolidBrush(m_clrBackgnd); pDC->FillRgn(&rgn1,&brush); brush.DeleteObject();   注意:在使用這個方法的時候要同時使用方法二。別忘了,到時候又說蟲蟲的辦法不靈。   4、使用MemoryDC先在內存里把圖畫好,再復制到屏幕上。   這對于一次畫圖過程很長的情況比較管用。畢竟內存操作比較快,而且復制到屏幕又是一次性的,至少不會出現可以明顯看出一個東東從左畫到右的情況。 void CMyWin::OnPaint() { CPaintDC dc1(this); // device context for painting dcMemory.CreateCompatibleDC(&dc1); CBitmap bmp;//這里的Bitmap是必須的,否則當心弄出一個大黑塊哦。 bmp.CreateCompatibleBitmap(&dc1,rectClient.Width(),rectClient.Height()); dcMemory.SelectObject(&bmp); //接下來你想怎么畫就怎么畫吧。 //dcMemory.FillRect(rectClient,&brush); dc1.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&dcMemory,0,0,SRCCOPY); dcMemory.DeleteDC(); // Do not call CWnd::OnPaint() for painting messages }   如何實現全屏顯示   全屏顯示是一些應用軟件程序必不可少的功能。比如在用VC++編輯工程源文件或編輯對話框等資源時,選擇菜單“ViewFull Screen”,即可進入全屏顯示狀態,按“Esc”鍵后會退出全屏顯示狀態。   在VC++6.0中我們用AppWizard按默認方式生成單文檔界面的應用程序框架。下面將先討論點擊菜單項“ViewFull Screen”實現全屏顯示的方法,再講述按“Esc”鍵后如何退出全屏顯示狀態。   1) 在CMainFrame類中,增加如下三個成員變量。   private:     WINDOWPLACEMENT m_OldWndPlacement; //用來保存原窗口位置     BOOL m_bFullScreen; //全屏顯示標志     CRect m_FullScreenRect; //表示全屏顯示時的窗口位置   2)在資源編輯器中編輯菜單IDR_MAINFRAME。在“View”菜單欄下添加菜單項“Full Screen”。在其屬性框中,ID設置為ID_FULL_SCREEN,Caption為“Full Screen”。還可以在工具欄中添加新的工具圖標,并使之與菜單項“Full Screen”相關聯,即將其ID值也設置為ID_FULL_SCREEN。   3)設計全屏顯示處理函數,在CMainFrame類增加上述菜單項ID_FULL_SCREEN消息的響應函數。響應函數如下:   void CMainFrame::OnFullScreen()   { GetWindowPlacement(&m_OldWndPlacement);    CRect WindowRect;    GetWindowRect(&WindowRect);    CRect ClientRect;    RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &ClientRect);    ClientToScreen(&ClientRect);    // 獲取屏幕的分辨率    int nFullWidth=GetSystemMetrics(SM_CXSCREEN);    int nFullHeight=GetSystemMetrics(SM_CYSCREEN);    // 將除控制條外的客戶區全屏顯示到從(0,0)到(nFullWidth, nFullHeight)區域, 將(0,0)和(nFullWidth, nFullHeight)兩個點外擴充原窗口和除控制條之外的 客戶區位置間的差值, 就得到全屏顯示的窗口位置    m_FullScreenRect.left=WindowRect.left-ClientRect.left;    m_FullScreenRect.top=WindowRect.top-ClientRect.top;    m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth;    m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight;    m_bFullScreen=TRUE; // 設置全屏顯示標志為 TRUE    // 進入全屏顯示狀態    WINDOWPLACEMENT wndpl;    wndpl.length=sizeof(WINDOWPLACEMENT);    wndpl.flags=0;    wndpl.showCmd=SW_SHOWNORMAL;    wndpl.rcNormalPosition=m_FullScreenRect;    SetWindowPlacement(&wndpl); }   4)重載CMainFrame類的OnGetMinMaxInfo函數,在全屏顯示時提供全屏顯示的位置信息。   void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)   { if(m_bFullScreen)    { lpMMI->ptMaxSize.x=m_FullScreenRect.Width();    lpMMI->ptMaxSize.y=m_FullScreenRect.Height();    lpMMI->ptMaxPosition.x=m_FullScreenRect.Width();    lpMMI->ptMaxPosition.y=m_FullScreenRect.Height();    //最大的Track尺寸也要改變    lpMMI->ptMaxTrackSize.x=m_FullScreenRect.Width();    lpMMI->ptMaxTrackSize.y=m_FullScreenRect.Height();    } CFrameWnd::OnGetMinMaxInfo(lpMMI) ;   }   完成上面的編程后,可以聯編執行FullScreen.exe,選擇菜單“ViewFull Screen”或點擊與之關聯的工具欄按鈕即可進入全屏顯示狀態。但現在還需要增加用戶退出全屏顯示狀態的操作接口,下面講述如何編程實現按“Esc”鍵退出全屏顯示狀態。   1)在ClassView中選中CMainFrame并單擊鼠標右鍵,選擇“Add Member Function...”,添加public類型的成員函數EndFullScreen,該函數將完成退出全屏顯示的操作。   void CMainFrame::EndFullScreen()   { if(m_bFullScreen)    {// 退出全屏顯示, 恢復原窗口顯示   ShowWindow(SW_HIDE);    SetWindowPlacement(&m_OldWndPlacement); } }   2)函數EndFullScreen可以退出全屏顯示狀態,問題是如何在“Esc”鍵被按下之后調用執行此函數。由于視圖類可以處理鍵盤輸入的有關消息(如WM_KEYDOWN表示用戶按下了某一個鍵),我們將在視圖類CFullScreenView中添加處理按鍵消息WM_KEYDOWN的響應函數OnKeyDown。判斷如果按的鍵為“Esc”鍵,則調用CMainFrame類的函數EndFullScreen,便可退出全屏顯示狀態。   void CFullScreenView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)   { if(nChar==VK_ESCAPE) // 如果按的鍵為Esc鍵    {// 獲取主框架窗口的指針    CMainFrame *pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;    // 調用主窗口類的自定義函數 EndFullScreen ,便可退出全屏顯示狀態   pFrame->EndFullScreen(); }   CView::OnKeyDown(nChar, nRepCnt, nFlags); }   更改窗口圖標并將其顯示在任務欄   以下兩個函數可以為應用程序中的各子窗口顯示一個任務條到任務欄并更改它們的圖標。對那些象QQ一樣隱藏主窗口的應用程序特別有用。 //函數用途:更改一個窗口的圖標并將其顯示在任務欄、任務切換條、任務管理器里 //參數說明: //hWnd 要改變圖標的窗口句柄 //hLargeIcon 顯示到任務切換條上的圖標 32*32 //hSmallIcon 顯示到除任務切換條之外的圖標 16*16 //hIcon 顯示的圖標,32*32,在顯示到任務切換條之外的其余地方時會被自動壓縮成16*16的。 //注釋: //此函數對于模式對話框無能為力。 //如果HICON 為NULL,函數不改變窗口圖標,但是將原有圖標顯示到任務欄、 // 任務切換條、任務管理器里。 //此函數是通過將窗口的父窗口指針置空來實現將圖標顯示到任務欄、任務切換條、 // 任務管理器里的,所以調用完成后,其父窗口指針不再可用。 BOOL SendWndIconToTaskbar(HWND hWnd,HICON hLargeIcon,HICON hSmallIcon); BOOL SendWndIconToTaskbar(HWND hWnd,HICON hIcon); BOOL CUIApp::SendWndIconToTaskbar(HWND hWnd,HICON hLargeIcon,HICON hSmallIcon) {  BOOL ret = TRUE;  ASSERT(hWnd);  if(!::IsWindow(hWnd))   return FALSE;  //獲取窗口指針  CWnd* pWnd;  pWnd = pWnd->FromHandle(hWnd);  ASSERT(pWnd);  if(!pWnd)   return FALSE;  //將父窗口設為NULL  if(pWnd->GetParent())   if(::SetWindowLong(hWnd,GWL_HWNDPARENT,NULL) == 0)    return FALSE;   if(!(pWnd->ModifyStyle(NULL,WS_OVERLAPPEDWINDOW)))    ret = FALSE;   //設置窗口圖標   if(hLargeIcon && hSmallIcon)   {    pWnd->SetIcon(hSmallIcon,FALSE);    pWnd->SetIcon(hLargeIcon,TRUE);   }   return ret;  } BOOL CUIApp::SendWndIconToTaskbar(HWND hWnd,HICON hIcon) {  BOOL ret = TRUE;  ASSERT(hWnd);  if(!::IsWindow(hWnd))   return FALSE;   //獲取窗口指針  CWnd* pWnd;  pWnd = pWnd->FromHandle(hWnd);  ASSERT(pWnd);  if(!pWnd)   return FALSE;  //將父窗口設為NULL  if(pWnd->GetParent())   if(::SetWindowLong(hWnd,GWL_HWNDPARENT,NULL) == 0)    return FALSE;  if(!(pWnd->ModifyStyle(NULL,WS_OVERLAPPEDWINDOW)))   ret = FALSE;  //設置窗口圖標  pWnd->SetIcon(hIcon,TRUE);  pWnd->SetIcon(hIcon,FALSE);  return ret; }   如何隱藏應用程序在任務欄上的顯示   對于CFrameWnd可以在PreCreateWindow()函數中修改窗口的風格。 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { cs.style |=WS_POPUP;//使主窗口不可見 cs.dwExStyle |=WS_EX_TOOLWINDOW;//不顯示任務按鈕 return CFrameWnd::PreCreateWindow(cs); }   對于其他窗口,可以在窗口被Create出來之后ShowWindow之前使用ModifyStyle()和ModifyStyleEx()來修改它的風格。   如何控制窗口框架的最大最小尺寸?   要控制一個框架的的最大最小尺寸,你需要做兩件事情。   第一步:在CFrameWnd的繼承類中處理消息WM_GETMINMAXINFO,結構MINMAXINFO設置了整個窗口類的限制,因此記住要考慮工具條,滾動條等等的大小。 // 最大最小尺寸的象素點 - 示例 #define MINX 200 #define MINY 300 #define MAXX 300 #define MAXY 400 void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) {  CRect rectWindow;  GetWindowRect(&rectWindow);  CRect rectClient;  GetClientRect(&rectClient);  // get offset of toolbars, scrollbars, etc.  int nWidthOffset = rectWindow.Width() - rectClient.Width();  int nHeightOffset = rectWindow.Height() - rectClient.Height();  lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;  lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;  lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;  lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset; }   第二步:在CFrameWnd的繼承類的PreCreateWindow函數中去掉WS_MAXIMIZEBOX消息,否則在最大化時你將得不到預料的結果. BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs) {  cs.style &= ~WS_MAXIMIZEBOX;  return CFrameWnd::PreCreateWindow(cs); }   如何修改frame窗口的背景顏色?   MDI窗口的客戶區是由frame窗口擁有的另一個窗口覆蓋的。為了改變frame窗口背景的顏色,只需要這個客戶區的背景顏色就可以了。你必須自己處理WM_ERASEBKND消息。下面是工作步驟:   創建一個從CWnd類繼承的類,就叫它CMDIClient吧;   在CMDIFrameWnd中加入CMDIClient變量;(具體情況看下面的代碼) #include "MDIClient.h" class CMainFrame : public CMDIFrameWnd { ... protected: CMDIClient m_wndMDIClient; }   重載CMDIFrameWnd::OnCreateClient,下面是這段代碼,請注意其中的SubclassWindow(); BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) ) { m_wndMDIClient.SubclassWindow(m_hWndMDIClient); return TRUE; } else return FALSE; }   最后要在CMDIClient中加入處理WM_ERASEBKGND的函數。   如何改變view的背景顏色?   若要改變CView,CFrameWnd或CWnd對象的背景顏色需要處理WM_ERASEBKGND消息,下面就是一個范例代碼: BOOL CSampleView::OnEraseBkgnd(CDC* pDC) { //設置brush為希望的背景顏色 CBrush backBrush(RGB(255, 128, 128)); //保存舊的brush CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); //畫需要的區域 pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC->SelectObject(pOldBrush); return TRUE; }   若要改變CFromView繼承類的背景顏色,下面是一個范例代碼: HBRUSH CMyFormView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {  switch (nCtlColor)  {   case CTLCOLOR_BTN:   case CTLCOLOR_STATIC:   {    pDC->SetBkMode(TRANSPARENT);    //不加任何處理或設置背景為透明   }   case CTLCOLOR_DLG:   {    CBrush* back_brush;    COLORREF color;    color = (COLORREF) GetSysColor(COLOR_BTNFACE);    back_brush = new CBrush(color);    return (HBRUSH) (back_brush->m_hObject);   }  }  return(CFormView::OnCtlColor(pDC, pWnd, nCtlColor)); } 在任務欄狀態區如何顯示應用程序圖標   有關的數據由NOTIFYICONDATA結構描述: typedef struct _NOTIFYICONDATA { DWORD cbSize; //結構的大小,必須設置 HWND hWnd; //接受回調消息的窗口的句柄 UINT uID; //應用程序定義的圖標標志 UINT uFlags; //標志,可以是NIF_ICON、NIF_MESSAGE、NIF_TIP或其組合 UINT uCallbackMessage;//應用程序定義的回調消息標志 HICON hIcon; //圖標句柄 char szTip[64]; //提示字串 } NOTIFYICONDATA, *PNOTIFYICONDATA;   函數說明   由Shell_NotifyIcon()函數向系統發送添加、刪除、更改圖標的消息。 WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA pnid);   DwMessage為所發送消息的標志:    NIM_ADD 添加圖標到任務欄通知區;    NIM_DELETE 刪除任務欄通知區的圖標;    NIM_MODIFY 更改任務欄通知區的圖標、回調消息標志、回調窗口句柄或提示字串;    pnid為NOTIFYICONDATA結構的指針。   回調信息的獲得及處理   如果一個任務欄圖標有應用程序定義的回調消息,那么當這個圖標有鼠標操作時,系統將給hWnd所標志的窗口發送下列的消息: messageID = uCallbackMessage wParam = uID lParam = mouse event(例如WM_LBUTTONDOWN)   通過這種方式,系統通知應用程序用戶對圖標的操作。如果一個應用程序生成了兩個以上的圖標,那么你可以根據wParam來判斷是哪個圖標返回的鼠標操作。通常,標準的Win95任務欄圖標有以下鼠標操作響應:   當鼠標停留在圖標上時,系統應顯示提示信息tooltip;   當使用鼠標右鍵單擊圖標時,應用程序應顯示快捷菜單;   當使用鼠標左鍵雙擊圖標時,應用程序應執行快捷菜單的缺省菜單項。   在Microsoft Windows環境中,0x8000到0xBFFF的消息是保留的,應用程序可以定義自定義消息。   關于消息處理的詳細內容,請參考下一部分。   源碼及實現   在本文中關于任務欄圖標的類叫做CTrayIcon,這個類由CCmdTarget(或CObject)類派生,它有如下的成員變量和成員函數: // TrayIcon.h // CTrayIcon command target class CTrayIcon : public CCmdTarget { public: NOTIFYICONDATA m_nid;//NOTIFYICONDATA結構,你的圖標要用的啊 BOOL m_IconExist;//標志,看看圖標是不是已經存在了 CWnd* m_NotificationWnd;//接受回調消息的窗口,有它就不必經常AfxGetMainWnd了 public: CWnd* GetNotificationWnd() const;//得到m_NotificationWnd BOOL SetNotificationWnd(CWnd* pNotifyWnd);//設置(更改)m_NotificationWnd CTrayIcon();//構造函數 virtual ~CTrayIcon();//析構函數 BOOL CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon, LPSTR lpszTip, UINT CallBackMessage);//在任務欄上生成圖標 BOOL DeleteIcon();//刪除任務欄上的圖標 virtual LRESULT OnNotify(WPARAM WParam, LPARAM LParam);//消息響應函數 BOOL SetTipText(UINT nID);//設置(更改)提示字串 BOOL SetTipText(LPCTSTR lpszTip);//設置(更改)提示字串 BOOL ChangeIcon(HICON hIcon);//更改圖標 BOOL ChangeIcon(UINT nID);//更改圖標 BOOL ChangeIcon(LPCTSTR lpszIconName);//更改圖標 BOOL ChangeStandardIcon(LPCTSTR lpszIconName);//更改為標準圖標 ...... };   下面是成員函數的定義: // TrayIcon.cpp // CTrayIcon CTrayIcon::CTrayIcon() {//初始化參數 m_IconExist = FALSE; m_NotificationWnd = NULL; memset(&m_nid, 0, sizeof(m_nid)); m_nid.cbSize = sizeof(m_nid);//這個參數不會改變 } CTrayIcon::~CTrayIcon() { if (m_IconExist) DeleteIcon();//刪除圖標 } BOOL CTrayIcon::CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon, LPSTR lpszTip, UINT CallBackMessage) { //確定接受回調消息的窗口是有效的 ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd())); ASSERT(CallBackMessage >= WM_USER);//確定回調消息不發生沖突 ASSERT(_tcslen(lpszTip) <= 64);//提示字串不能超過64個字符 m_NotificationWnd = pNotifyWnd;//獲得m_NotificationWnd //設置NOTIFYICONDATA結構 m_nid.hWnd = pNotifyWnd->GetSafeHwnd(); m_nid.uID = uID; m_nid.hIcon = hIcon; m_nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; m_nid.uCallbackMessage = CallBackMessage; //設置NOTIFYICONDATA結構的提示字串 if (lpszTip) lstrcpyn(m_nid.szTip, lpszTip, sizeof(m_nid.szTip)); else m_nid.szTip[0] = '\0'; //顯示圖標 m_IconExist = Shell_NotifyIcon(NIM_ADD, &m_nid); return m_IconExist; } BOOL CTrayIcon::DeleteIcon() {//刪除圖標 if (!m_IconExist) return FALSE; m_IconExist = FALSE; return Shell_NotifyIcon(NIM_DELETE, &m_nid); } LRESULT CTrayIcon::OnNotify(WPARAM WParam, LPARAM LParam) {//處理圖標返回的消息 if (WParam != m_nid.uID)//如果不是該圖標的消息則迅速返回 return 0L; //準備快捷菜單 CMenu menu; if (!menu.LoadMenu(IDR_POPUP))//你必須確定資源中有ID為IDR_POPUP的菜單 return 0; CMenu* pSubMenu = menu.GetSubMenu(0);//獲得IDR_POPUP的子菜單 if (!pSubMenu) return 0; if (LParam == WM_RBUTTONUP) {//右鍵單擊彈出快捷菜單 //設置第一個菜單項為缺省 ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE); CPoint pos; GetCursorPos(&pos); //顯示并跟蹤菜單 m_NotificationWnd->SetForegroundWindow(); pSubMenu->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON |TPM_RIGHTBUTTON, pos.x, pos.y, m_NotificationWnd, NULL); } else if (LParam == WM_LBUTTONDOWN) {//左鍵單擊恢復窗口 m_NotificationWnd->ShowWindow(SW_SHOW);//恢復窗口 m_NotificationWnd->SetForegroundWindow();//放置在前面 } else if (LParam == WM_LBUTTONDBLCLK) {//左鍵雙擊執行缺省菜單項 m_NotificationWnd->SendMessage(WM_COMMAND, pSubMenu->GetMenuItemID(0), 0); } return 1L; } BOOL CTrayIcon::SetTipText(LPCTSTR lpszTip) {//設置提示文字 if (!m_IconExist) return FALSE; _tcscpy(m_nid.szTip, lpszTip); m_nid.uFlags |= NIF_TIP; return Shell_NotifyIcon(NIM_MODIFY, &m_nid); } BOOL CTrayIcon::SetTipText(UINT nID) {//設置提示文字  CString szTip;  VERIFY(szTip.LoadString(nID));  return SetTipText(szTip); } BOOL CTrayIcon::ChangeIcon(HICON hIcon) {//更改圖標 if (!m_IconExist) return FALSE; m_nid.hIcon = hIcon; m_nid.uFlags |= NIF_ICON; return Shell_NotifyIcon(NIM_MODIFY, &m_nid); } BOOL CTrayIcon::ChangeIcon(UINT nID) {//更改圖標  HICON hIcon = AfxGetApp()->LoadIcon(nID);  return ChangeIcon(hIcon); } BOOL CTrayIcon::ChangeIcon(LPCTSTR lpszIconName) {//更改圖標  HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);  return ChangeIcon(hIcon); } BOOL CTrayIcon::ChangeStandardIcon(LPCTSTR lpszIconName) {//更改為標準圖標  HICON hIcon = AfxGetApp()->LoadStandardIcon(lpszIconName);  return ChangeIcon(hIcon); } BOOL CTrayIcon::SetNotificationWnd(CWnd * pNotifyWnd) {//設置接受回調消息的窗口  if (!m_IconExist)   return FALSE;  //確定窗口是有效的  ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd()));  m_NotificationWnd = pNotifyWnd;  m_nid.hWnd = pNotifyWnd->GetSafeHwnd();  m_nid.uFlags |= NIF_MESSAGE;  return Shell_NotifyIcon(NIM_MODIFY, &m_nid); } CWnd* CTrayIcon::GetNotificationWnd() const {//返回接受回調消息的窗口  return m_NotificationWnd; }   三點補充:   關于使用回調消息的補充說明:   首先,在MainFrm.cpp中加入自己的消息代碼; // MainFrm.cpp : implementation of the CMainFrame class // #define MYWM_ICONNOTIFY WM_USER + 10//定義自己的消息代碼   第二步增加消息映射和函數聲明,對于自定義消息不能由ClassWizard添加消息映射,只能手工添加。 // MainFrm.cpp : implementation of the CMainFrame class BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) //其他的消息映射 ...... //}}AFX_MSG_MAP ON_MESSAGE(WM_ICONNOTIFY,OnNotify) END_MESSAGE_MAP() 并且在頭文件中添加函數聲明 // MainFrm.h afx_msg LRESULT OnNotify(WPARAM WParam, LPARAM LParam);   第三步增加消息處理函數定義 LRESULT CMainFrame::OnNotify(WPARAM WParam, LPARAM LParam) { return trayicon.OnNotify(WParam, LParam);//調用CTrayIcon類的處理函數 }   如何隱藏任務欄上的按鈕   可以使用下列兩種方法:   1.在CreateWindowEx函數中使用WS_EX_TOOLWINDOW窗口式樣(相反的如果要確保應用程序在任務欄上生成按鈕,可以使用WS_EX_APPWINDOW窗口式樣)。 The problem with this is that the window decorations are as for a small floating toolbar, which isn't normally what's wanted.   2.生成一個空的隱藏的top-level窗口,并使其作為可視窗口的父窗口。   3.在應用程序的InitInstance()函數中使用SW_HIDE式樣調用ShowWindow()函數。 //pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->ShowWindow(SW_HIDE); pMainFrame->UpdateWindow();   如何動畫任務欄上的圖標   在TrayIcon類中加入下列兩個函數: BOOL CTrayIcon::SetAnimateIcons(HICON* hIcon, UINT Number) {//設置動畫圖標  ASSERT(Number >= 2);//圖標必須為兩個以上  ASSERT(hIcon);//圖標必須不為空  m_AnimateIcons = new HICON[Number];  CopyMemory(m_AnimateIcons, hIcon, Number * sizeof(HICON));  m_AnimateIconsNumber = Number;  return TRUE; } BOOL CTrayIcon::Animate(UINT Index) {//動畫TrayIcon  UINT i = Index % m_AnimateIconsNumber;  return ChangeIcon(m_AnimateIcons[i]); }   怎樣在應用程序中添加相應的菜單和函數 void CMainFrame::OnMenuAnimate() {//動畫TrayIcon,設置圖標及定時器  SetTimer(1, 500, NULL);  HICON hIcon[3];  hIcon[0] = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  hIcon[1] = AfxGetApp()->LoadIcon(IDR_MYTURNTYPE);  hIcon[2] = AfxGetApp()->LoadStandardIcon(IDI_HAND);  trayicon.SetAnimateIcons(hIcon, 3); } void CMainFrame::OnTimer(UINT nIDEvent) {//動畫TrayIcon  UINT static i;  i += 1;  trayicon.Animate(i);  CMDIFrameWnd::OnTimer(nIDEvent); }

            posted on 2006-02-10 11:13 tqsheng 閱讀(284) 評論(0)  編輯 收藏 引用

            国色天香久久久久久久小说| 精品久久久久久久久久中文字幕| 超级97碰碰碰碰久久久久最新| 综合网日日天干夜夜久久| 久久久久成人精品无码中文字幕| 国产精久久一区二区三区| 亚洲精品无码专区久久同性男| 热re99久久6国产精品免费| yellow中文字幕久久网| 久久国产色av免费看| 大美女久久久久久j久久| 久久午夜无码鲁丝片秋霞| 久久久九九有精品国产| 亚洲色欲久久久综合网东京热| 久久精品嫩草影院| 日韩精品久久久肉伦网站| 久久精品中文字幕第23页| 好久久免费视频高清| 亚洲中文久久精品无码ww16| 久久久国产精品| 99久久www免费人成精品| 久久成人国产精品| 99久久做夜夜爱天天做精品| 久久人人爽人人爽人人片AV麻豆 | 精品久久久久中文字| 久久免费的精品国产V∧| 麻豆av久久av盛宴av| 久久久久亚洲精品无码网址 | 91精品国产91久久久久福利| 久久久久久久久久久久久久| 久久天天躁狠狠躁夜夜不卡| 国产999精品久久久久久| 久久久久久久尹人综合网亚洲| 久久婷婷激情综合色综合俺也去| 狠狠色婷婷久久一区二区| 久久亚洲AV成人无码软件| 综合网日日天干夜夜久久| 亚洲午夜无码久久久久| 熟妇人妻久久中文字幕| 无码AV中文字幕久久专区| 久久久久亚洲av无码专区喷水|