久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

VC窗體設(shè)計(jì)集錦

 浮 生 2009-07-01
                                      

[前言:]有好的界面軟件就成功了一半,,本文將向您介紹怎樣設(shè)計(jì)一些有“稀奇古怪”形狀的窗體,,如何設(shè)定窗體的顏色,、如何設(shè)置任務(wù)欄和狀態(tài)欄以及菜單圖標(biāo)等等,,通過(guò)這些技巧能更深入的理解VC的文檔-視圖結(jié)構(gòu),。

  如何制作透明窗體 

  使用SetLayeredWindowAttributes可以方便的制作透明窗體,此函數(shù)在w2k以上才支持,而且如果希望直接使用的話,,可能需要下載最新的SDK,。不過(guò)此函數(shù)在w2k的user32.dll里有實(shí)現(xiàn),,所以如果你不希望下載巨大的sdk的話,,可以直接使用GetProcAddress獲取該函數(shù)的指針。


  SetLayeredWindowAttributes的函數(shù)原型如下:

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里沒(méi)法使用的)
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被設(shè)置的話,通過(guò)bAlpha決定透明度.

  LWA_COLORKEY被設(shè)置的話,則指定被透明掉的顏色為crKey,其他顏色則正常顯示.

  要使使窗體擁有透明效果,首先要有WS_EX_LAYERED擴(kuò)展屬性(舊的sdk沒(méi)有定義這個(gè)屬性,所以可以直接指定為0x80000). 

  例子代碼:

  在OnInitDialog()加入: 

//加入WS_EX_LAYERED擴(kuò)展屬性
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函數(shù)指針 
 fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
 if(fun)fun(this->GetSafeHwnd(),0,128,2); 
 FreeLibrary(hInst); 


  稍加修改還可以作出淡出淡入的效果. 注意第三個(gè)參數(shù)(128)不要取得太小了,為0的話就完全透明,看不到了。

  如何使框架窗口的圖標(biāo)為動(dòng)畫顯示

  可以用TIMER,,但是TIMER不能有效的定時(shí),。因?yàn)門IMER發(fā)送的是窗口消息,當(dāng)窗口忙于處理鍵盤,、鼠標(biāo)等消息時(shí)就不能及時(shí)處理TIMER,,會(huì)使間隔時(shí)間變得很長(zhǎng) 。

  可以考慮用一個(gè)單獨(dú)得TIMER線程,,用Sleep()定時(shí)來(lái)解決此問(wèn)題,。


UINT Timer(LPVOID param)
{
 HWND hWnd=(HWND)param;
 while(1)
 {
  Sleep(ms);
  PostMessage(hWnd,CH_PICTURE,NULL,NULL)
 }


  Sleep(ms)后發(fā)送自定義消息。消息處理函數(shù)就選擇某一個(gè)ICON或BITMAP來(lái)顯示,。如 :


MyBotton.SetBitmap((HBITMAP)Bitmap[i]); 

  Bitmap是一個(gè)位圖數(shù)組,,存放有j個(gè)位圖。消息處理函數(shù)運(yùn)行一次,,i就累加一次,,當(dāng)i==j時(shí),i就回到0,; 

  防止窗口閃爍的方法

  1,、將Invalidate()替換為InvalidateRect()。

  Invalidate()會(huì)導(dǎo)致整個(gè)窗口的圖象重畫,,需要的時(shí)間比較長(zhǎng),,而InvalidateRect()僅僅重畫Rect區(qū)域內(nèi)的內(nèi)容,所以所需時(shí)間會(huì)少一些,。蟲蟲以前很懶,,經(jīng)常為一小塊區(qū)域的重畫就調(diào)用Invalidate(),不愿意自己去計(jì)算需要重畫的Rect,,但是事實(shí)是,,如果你確實(shí)需要改善閃爍的情況,計(jì)算一個(gè)Rect所用的時(shí)間比起重畫那些不需要重畫的內(nèi)容所需要的時(shí)間要少得多,。

  2,、禁止系統(tǒng)搽除你的窗口。

  系統(tǒng)在需要重畫窗口的時(shí)候會(huì)幫你用指定的背景色來(lái)搽除窗口,??墒牵苍S需要重畫的區(qū)域也許非常小,?;蛘撸谀阒禺嬤@些東西之間還要經(jīng)過(guò)大量的計(jì)算才能開始,。這個(gè)時(shí)候你可以禁止系統(tǒng)搽掉原來(lái)的圖象,。直到你已經(jīng)計(jì)算好了所有的數(shù)據(jù),自己把那些需要搽掉的部分用背景色覆蓋掉(如:dc.FillRect(rect,&brush);rect是需要搽除的區(qū)域,brush是帶背景色的刷子),,再畫上新的圖形,。要禁止系統(tǒng)搽除你的窗口,可以重載OnEraseBkgnd()函數(shù),,讓其直接返回TRUE就可以了,。如

BOOL CMyWin::OnEraseBkgnd(CDC* pDC) 
{
return TRUE;
//return CWnd::OnEraseBkgnd(pDC);//把系統(tǒng)原來(lái)的這條語(yǔ)句注釋掉。


  3,、有效的進(jìn)行搽除,。

  搽除背景的時(shí)候,不要該搽不該搽的地方都搽,。比如,,你在一個(gè)窗口上放了一個(gè)很大的Edit框,幾乎占了整個(gè)窗口,,那么你頻繁的搽除整個(gè)窗口背景將導(dǎo)致Edit不停重畫形成劇烈的閃爍,。事實(shí)上你可以CRgn創(chuàng)建一個(gè)需要搽除的區(qū)域,只搽除這一部分,。如

GetClientRect(rectClient);
rgn1.CreateRectRgnIndirect(rectClient);
rgn2.CreateRectRgnIndirect(m_rectEdit);
if(rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR) == ERROR)//處理后的rgn1只包括了Edit框之外的客戶區(qū)域,,這樣,Edit將不會(huì)被我的背景覆蓋而導(dǎo)致重畫,。
{
ASSERT(FALSE);
return ;
}
brush.CreateSolidBrush(m_clrBackgnd);
pDC->FillRgn(&rgn1,&brush);
brush.DeleteObject(); 

  注意:在使用這個(gè)方法的時(shí)候要同時(shí)使用方法二,。別忘了,到時(shí)候又說(shuō)蟲蟲的辦法不靈,。

  4,、使用MemoryDC先在內(nèi)存里把圖畫好,再?gòu)?fù)制到屏幕上,。

  這對(duì)于一次畫圖過(guò)程很長(zhǎng)的情況比較管用,。畢竟內(nèi)存操作比較快,而且復(fù)制到屏幕又是一次性的,,至少不會(huì)出現(xiàn)可以明顯看出一個(gè)東東從左畫到右的情況,。

void CMyWin::OnPaint() 
{
CPaintDC dc1(this); // device context for painting
dcMemory.CreateCompatibleDC(&dc1);
CBitmap bmp;//這里的Bitmap是必須的,否則當(dāng)心弄出一個(gè)大黑塊哦,。
bmp.CreateCompatibleBitmap(&dc1,rectClient.Width(),rectClient.Height());
dcMemory.SelectObject(&bmp);

//接下來(lái)你想怎么畫就怎么畫吧,。
//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
}
 

  如何實(shí)現(xiàn)全屏顯示

  全屏顯示是一些應(yīng)用軟件程序必不可少的功能。比如在用VC++編輯工程源文件或編輯對(duì)話框等資源時(shí),,選擇菜單“ViewFull Screen”,即可進(jìn)入全屏顯示狀態(tài),,按“Esc”鍵后會(huì)退出全屏顯示狀態(tài),。 

  在VC++6.0中我們用AppWizard按默認(rèn)方式生成單文檔界面的應(yīng)用程序框架。下面將先討論點(diǎn)擊菜單項(xiàng)“ViewFull Screen”實(shí)現(xiàn)全屏顯示的方法,再講述按“Esc”鍵后如何退出全屏顯示狀態(tài),。 

  1) 在CMainFrame類中,,增加如下三個(gè)成員變量。 

  private: 
    WINDOWPLACEMENT m_OldWndPlacement; //用來(lái)保存原窗口位置 
    BOOL m_bFullScreen; //全屏顯示標(biāo)志 
    CRect m_FullScreenRect; //表示全屏顯示時(shí)的窗口位置  

  2)在資源編輯器中編輯菜單IDR_MAINFRAME,。在“View”菜單欄下添加菜單項(xiàng)“Full Screen”,。在其屬性框中,ID設(shè)置為ID_FULL_SCREEN,,Caption為“Full Screen”,。還可以在工具欄中添加新的工具圖標(biāo),并使之與菜單項(xiàng)“Full Screen”相關(guān)聯(lián),,即將其ID值也設(shè)置為ID_FULL_SCREEN,。 

  3)設(shè)計(jì)全屏顯示處理函數(shù),在CMainFrame類增加上述菜單項(xiàng)ID_FULL_SCREEN消息的響應(yīng)函數(shù),。響應(yīng)函數(shù)如下: 


  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); 
   // 將除控制條外的客戶區(qū)全屏顯示到從(0,0)到(nFullWidth, nFullHeight)區(qū)域, 將(0,0)和(nFullWidth, nFullHeight)兩個(gè)點(diǎn)外擴(kuò)充原窗口和除控制條之外的 客戶區(qū)位置間的差值, 就得到全屏顯示的窗口位置 
   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; // 設(shè)置全屏顯示標(biāo)志為 TRUE 
   // 進(jìn)入全屏顯示狀態(tài) 
   WINDOWPLACEMENT wndpl; 
   wndpl.length=sizeof(WINDOWPLACEMENT); 
   wndpl.flags=0; 
   wndpl.showCmd=SW_SHOWNORMAL; 
   wndpl.rcNormalPosition=m_FullScreenRect; 
   SetWindowPlacement(&wndpl);


 

  4)重載CMainFrame類的OnGetMinMaxInfo函數(shù),,在全屏顯示時(shí)提供全屏顯示的位置信息。 


  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) ; 
  }
 

  完成上面的編程后,,可以聯(lián)編執(zhí)行FullScreen.exe,,選擇菜單“ViewFull Screen”或點(diǎn)擊與之關(guān)聯(lián)的工具欄按鈕即可進(jìn)入全屏顯示狀態(tài)。但現(xiàn)在還需要增加用戶退出全屏顯示狀態(tài)的操作接口,下面講述如何編程實(shí)現(xiàn)按“Esc”鍵退出全屏顯示狀態(tài),。 

  1)在ClassView中選中CMainFrame并單擊鼠標(biāo)右鍵,,選擇“Add Member Function...”,添加public類型的成員函數(shù)EndFullScreen,,該函數(shù)將完成退出全屏顯示的操作,。 


  void CMainFrame::EndFullScreen() 
  {

if(m_bFullScreen) 
   {// 退出全屏顯示, 恢復(fù)原窗口顯示 
  ShowWindow(SW_HIDE); 
   SetWindowPlacement(&m_OldWndPlacement);

}

}
 

  2)函數(shù)EndFullScreen可以退出全屏顯示狀態(tài),問(wèn)題是如何在“Esc”鍵被按下之后調(diào)用執(zhí)行此函數(shù),。由于視圖類可以處理鍵盤輸入的有關(guān)消息(如WM_KEYDOWN表示用戶按下了某一個(gè)鍵),,我們將在視圖類CFullScreenView中添加處理按鍵消息WM_KEYDOWN的響應(yīng)函數(shù)OnKeyDown。判斷如果按的鍵為“Esc”鍵,,則調(diào)用CMainFrame類的函數(shù)EndFullScreen,,便可退出全屏顯示狀態(tài)。 


  void CFullScreenView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  {

if(nChar==VK_ESCAPE) // 如果按的鍵為Esc鍵 
   {// 獲取主框架窗口的指針 

   CMainFrame *pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd; 
   // 調(diào)用主窗口類的自定義函數(shù) EndFullScreen ,,便可退出全屏顯示狀態(tài) 
  pFrame->EndFullScreen();


  CView::OnKeyDown(nChar, nRepCnt, nFlags);


 

  更改窗口圖標(biāo)并將其顯示在任務(wù)欄 

  以下兩個(gè)函數(shù)可以為應(yīng)用程序中的各子窗口顯示一個(gè)任務(wù)條到任務(wù)欄并更改它們的圖標(biāo),。對(duì)那些象QQ一樣隱藏主窗口的應(yīng)用程序特別有用。

//函數(shù)用途:更改一個(gè)窗口的圖標(biāo)并將其顯示在任務(wù)欄,、任務(wù)切換條,、任務(wù)管理器里
//參數(shù)說(shuō)明:
//hWnd 要改變圖標(biāo)的窗口句柄
//hLargeIcon 顯示到任務(wù)切換條上的圖標(biāo) 32*32
//hSmallIcon 顯示到除任務(wù)切換條之外的圖標(biāo) 16*16
//hIcon 顯示的圖標(biāo),32*32,,在顯示到任務(wù)切換條之外的其余地方時(shí)會(huì)被自動(dòng)壓縮成16*16的,。
//注釋:
//此函數(shù)對(duì)于模式對(duì)話框無(wú)能為力,。
//如果HICON 為NULL,函數(shù)不改變窗口圖標(biāo),,但是將原有圖標(biāo)顯示到任務(wù)欄,、
// 任務(wù)切換條、任務(wù)管理器里,。
//此函數(shù)是通過(guò)將窗口的父窗口指針置空來(lái)實(shí)現(xiàn)將圖標(biāo)顯示到任務(wù)欄,、任務(wù)切換條、
// 任務(wù)管理器里的,,所以調(diào)用完成后,,其父窗口指針不再可用。
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;
 //將父窗口設(shè)為NULL
 if(pWnd->GetParent())
  if(::SetWindowLong(hWnd,GWL_HWNDPARENT,NULL) == 0)
   return FALSE;

  if(!(pWnd->ModifyStyle(NULL,WS_OVERLAPPEDWINDOW)))
   ret = FALSE;
  //設(shè)置窗口圖標(biāo)
  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;
 //將父窗口設(shè)為NULL
 if(pWnd->GetParent())
  if(::SetWindowLong(hWnd,GWL_HWNDPARENT,NULL) == 0)
   return FALSE;

 if(!(pWnd->ModifyStyle(NULL,WS_OVERLAPPEDWINDOW)))
  ret = FALSE;
 //設(shè)置窗口圖標(biāo)
 pWnd->SetIcon(hIcon,TRUE);
 pWnd->SetIcon(hIcon,FALSE);

 return ret;
}

 

如何隱藏應(yīng)用程序在任務(wù)欄上的顯示

  對(duì)于CFrameWnd可以在PreCreateWindow()函數(shù)中修改窗口的風(fēng)格,。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |=WS_POPUP;//使主窗口不可見
cs.dwExStyle |=WS_EX_TOOLWINDOW;//不顯示任務(wù)按鈕
return CFrameWnd::PreCreateWindow(cs);


  對(duì)于其他窗口,,可以在窗口被Create出來(lái)之后ShowWindow之前使用ModifyStyle()和ModifyStyleEx()來(lái)修改它的風(fēng)格。

  如何控制窗口框架的最大最小尺寸?

  要控制一個(gè)框架的的最大最小尺寸,你需要做兩件事情,。

  第一步:在CFrameWnd的繼承類中處理消息WM_GETMINMAXINFO,結(jié)構(gòu)MINMAXINFO設(shè)置了整個(gè)窗口類的限制,因此記住要考慮工具條,滾動(dòng)條等等的大小,。

// 最大最小尺寸的象素點(diǎn) - 示例
#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函數(shù)中去掉WS_MAXIMIZEBOX消息,否則在最大化時(shí)你將得不到預(yù)料的結(jié)果.

BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
 cs.style &= ~WS_MAXIMIZEBOX;
 return CFrameWnd::PreCreateWindow(cs);
}

如何修改frame窗口的背景顏色?

  MDI窗口的客戶區(qū)是由frame窗口擁有的另一個(gè)窗口覆蓋的,。為了改變frame窗口背景的顏色,,只需要這個(gè)客戶區(qū)的背景顏色就可以了。你必須自己處理WM_ERASEBKND消息,。下面是工作步驟: 

  創(chuàng)建一個(gè)從CWnd類繼承的類,,就叫它CMDIClient吧; 

  在CMDIFrameWnd中加入CMDIClient變量,;(具體情況看下面的代碼) 


#include "MDIClient.h"
class CMainFrame : public CMDIFrameWnd
{
...
protected:
CMDIClient m_wndMDIClient;


  重載CMDIFrameWnd::OnCreateClient,,下面是這段代碼,請(qǐng)注意其中的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的函數(shù),。

  如何改變view的背景顏色? 

  若要改變CView,,CFrameWnd或CWnd對(duì)象的背景顏色需要處理WM_ERASEBKGND消息,,下面就是一個(gè)范例代碼:

BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
{

//設(shè)置brush為希望的背景顏色
CBrush backBrush(RGB(255, 128, 128));

//保存舊的brush
CBrush* pOldBrush = pDC->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect);

//畫需要的區(qū)域
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);

return TRUE;

}
 

  若要改變CFromView繼承類的背景顏色,下面是一個(gè)范例代碼:

HBRUSH CMyFormView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{

 switch (nCtlColor)
 {

  case CTLCOLOR_BTN:
  case CTLCOLOR_STATIC:
  {

   pDC->SetBkMode(TRANSPARENT);
   //不加任何處理或設(shè)置背景為透明

  }
  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));

}
 
 

在任務(wù)欄狀態(tài)區(qū)如何顯示應(yīng)用程序圖標(biāo)

  有關(guān)的數(shù)據(jù)由NOTIFYICONDATA結(jié)構(gòu)描述:

typedef struct _NOTIFYICONDATA
{
DWORD cbSize; //結(jié)構(gòu)的大小,,必須設(shè)置
HWND hWnd; //接受回調(diào)消息的窗口的句柄
UINT uID; //應(yīng)用程序定義的圖標(biāo)標(biāo)志
UINT uFlags; //標(biāo)志,,可以是NIF_ICON、NIF_MESSAGE,、NIF_TIP或其組合
UINT uCallbackMessage;//應(yīng)用程序定義的回調(diào)消息標(biāo)志
HICON hIcon; //圖標(biāo)句柄
char szTip[64]; //提示字串
} NOTIFYICONDATA, *PNOTIFYICONDATA; 

  函數(shù)說(shuō)明

  由Shell_NotifyIcon()函數(shù)向系統(tǒng)發(fā)送添加,、刪除、更改圖標(biāo)的消息,。

WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA pnid); 

  DwMessage為所發(fā)送消息的標(biāo)志:

   NIM_ADD 添加圖標(biāo)到任務(wù)欄通知區(qū),;

   NIM_DELETE 刪除任務(wù)欄通知區(qū)的圖標(biāo),;

   NIM_MODIFY 更改任務(wù)欄通知區(qū)的圖標(biāo),、回調(diào)消息標(biāo)志,、回調(diào)窗口句柄或提示字串;

   pnid為NOTIFYICONDATA結(jié)構(gòu)的指針,。

  回調(diào)信息的獲得及處理

  如果一個(gè)任務(wù)欄圖標(biāo)有應(yīng)用程序定義的回調(diào)消息,,那么當(dāng)這個(gè)圖標(biāo)有鼠標(biāo)操作時(shí),系統(tǒng)將給hWnd所標(biāo)志的窗口發(fā)送下列的消息:


messageID = uCallbackMessage
wParam = uID
lParam = mouse event(例如WM_LBUTTONDOWN) 

  通過(guò)這種方式,,系統(tǒng)通知應(yīng)用程序用戶對(duì)圖標(biāo)的操作,。如果一個(gè)應(yīng)用程序生成了兩個(gè)以上的圖標(biāo),那么你可以根據(jù)wParam來(lái)判斷是哪個(gè)圖標(biāo)返回的鼠標(biāo)操作,。通常,,標(biāo)準(zhǔn)的Win95任務(wù)欄圖標(biāo)有以下鼠標(biāo)操作響應(yīng):

  當(dāng)鼠標(biāo)停留在圖標(biāo)上時(shí),系統(tǒng)應(yīng)顯示提示信息tooltip,;

  當(dāng)使用鼠標(biāo)右鍵單擊圖標(biāo)時(shí),,應(yīng)用程序應(yīng)顯示快捷菜單;

  當(dāng)使用鼠標(biāo)左鍵雙擊圖標(biāo)時(shí),,應(yīng)用程序應(yīng)執(zhí)行快捷菜單的缺省菜單項(xiàng),。

  在Microsoft Windows環(huán)境中,0x8000到0xBFFF的消息是保留的,,應(yīng)用程序可以定義自定義消息,。

  關(guān)于消息處理的詳細(xì)內(nèi)容,請(qǐng)參考下一部分,。

  源碼及實(shí)現(xiàn)

  在本文中關(guān)于任務(wù)欄圖標(biāo)的類叫做CTrayIcon,,這個(gè)類由CCmdTarget(或CObject)類派生,它有如下的成員變量和成員函數(shù):

// TrayIcon.h
// CTrayIcon command target

class CTrayIcon : public CCmdTarget
{
public:
NOTIFYICONDATA m_nid;//NOTIFYICONDATA結(jié)構(gòu),,你的圖標(biāo)要用的啊
BOOL m_IconExist;//標(biāo)志,,看看圖標(biāo)是不是已經(jīng)存在了
CWnd* m_NotificationWnd;//接受回調(diào)消息的窗口,有它就不必經(jīng)常AfxGetMainWnd了
public:
CWnd* GetNotificationWnd() const;//得到m_NotificationWnd
BOOL SetNotificationWnd(CWnd* pNotifyWnd);//設(shè)置(更改)m_NotificationWnd
CTrayIcon();//構(gòu)造函數(shù)
virtual ~CTrayIcon();//析構(gòu)函數(shù)
BOOL CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon,
LPSTR lpszTip, UINT CallBackMessage);//在任務(wù)欄上生成圖標(biāo)
BOOL DeleteIcon();//刪除任務(wù)欄上的圖標(biāo)
virtual LRESULT OnNotify(WPARAM WParam, LPARAM LParam);//消息響應(yīng)函數(shù)
BOOL SetTipText(UINT nID);//設(shè)置(更改)提示字串
BOOL SetTipText(LPCTSTR lpszTip);//設(shè)置(更改)提示字串
BOOL ChangeIcon(HICON hIcon);//更改圖標(biāo)
BOOL ChangeIcon(UINT nID);//更改圖標(biāo)
BOOL ChangeIcon(LPCTSTR lpszIconName);//更改圖標(biāo)
BOOL ChangeStandardIcon(LPCTSTR lpszIconName);//更改為標(biāo)準(zhǔn)圖標(biāo)
......
};
 

  下面是成員函數(shù)的定義:

// TrayIcon.cpp
// CTrayIcon

CTrayIcon::CTrayIcon()
{//初始化參數(shù)
m_IconExist = FALSE;
m_NotificationWnd = NULL;
memset(&m_nid, 0, sizeof(m_nid));
m_nid.cbSize = sizeof(m_nid);//這個(gè)參數(shù)不會(huì)改變
}

CTrayIcon::~CTrayIcon()
{
if (m_IconExist)
DeleteIcon();//刪除圖標(biāo)
}

BOOL CTrayIcon::CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon,
LPSTR lpszTip, UINT CallBackMessage)
{
//確定接受回調(diào)消息的窗口是有效的
ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd()));

ASSERT(CallBackMessage >= WM_USER);//確定回調(diào)消息不發(fā)生沖突

ASSERT(_tcslen(lpszTip) <= 64);//提示字串不能超過(guò)64個(gè)字符

m_NotificationWnd = pNotifyWnd;//獲得m_NotificationWnd

//設(shè)置NOTIFYICONDATA結(jié)構(gòu)
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;

//設(shè)置NOTIFYICONDATA結(jié)構(gòu)的提示字串
if (lpszTip)
lstrcpyn(m_nid.szTip, lpszTip, sizeof(m_nid.szTip));
else
m_nid.szTip[0] = '\0';

//顯示圖標(biāo)
m_IconExist = Shell_NotifyIcon(NIM_ADD, &m_nid);
return m_IconExist;
}

BOOL CTrayIcon::DeleteIcon()
{//刪除圖標(biāo)
if (!m_IconExist)
return FALSE;
m_IconExist = FALSE;
return Shell_NotifyIcon(NIM_DELETE, &m_nid);
}

LRESULT CTrayIcon::OnNotify(WPARAM WParam, LPARAM LParam)
{//處理圖標(biāo)返回的消息
if (WParam != m_nid.uID)//如果不是該圖標(biāo)的消息則迅速返回
return 0L;

//準(zhǔn)備快捷菜單
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)
{//右鍵單擊彈出快捷菜單

//設(shè)置第一個(gè)菜單項(xiàng)為缺省
::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)
{//左鍵單擊恢復(fù)窗口
m_NotificationWnd->ShowWindow(SW_SHOW);//恢復(fù)窗口
m_NotificationWnd->SetForegroundWindow();//放置在前面
}
else if (LParam == WM_LBUTTONDBLCLK)
{//左鍵雙擊執(zhí)行缺省菜單項(xiàng)
m_NotificationWnd->SendMessage(WM_COMMAND,
pSubMenu->GetMenuItemID(0), 0);
}
return 1L;
}

BOOL CTrayIcon::SetTipText(LPCTSTR lpszTip)
{//設(shè)置提示文字
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)
{//設(shè)置提示文字
 CString szTip;
 VERIFY(szTip.LoadString(nID));

 return SetTipText(szTip);
}
BOOL CTrayIcon::ChangeIcon(HICON hIcon)
{//更改圖標(biāo)
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)
{//更改圖標(biāo)
 HICON hIcon = AfxGetApp()->LoadIcon(nID);
 return ChangeIcon(hIcon);
}

BOOL CTrayIcon::ChangeIcon(LPCTSTR lpszIconName)
{//更改圖標(biāo)
 HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);
 return ChangeIcon(hIcon);
}

BOOL CTrayIcon::ChangeStandardIcon(LPCTSTR lpszIconName)
{//更改為標(biāo)準(zhǔn)圖標(biāo)
 HICON hIcon = AfxGetApp()->LoadStandardIcon(lpszIconName);
 return ChangeIcon(hIcon);
}

BOOL CTrayIcon::SetNotificationWnd(CWnd * pNotifyWnd)
{//設(shè)置接受回調(diào)消息的窗口
 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
{//返回接受回調(diào)消息的窗口
 return m_NotificationWnd;
}
 

  三點(diǎn)補(bǔ)充:

  關(guān)于使用回調(diào)消息的補(bǔ)充說(shuō)明:


  首先,在MainFrm.cpp中加入自己的消息代碼,;


// MainFrm.cpp : implementation of the CMainFrame class
//
#define MYWM_ICONNOTIFY WM_USER + 10//定義自己的消息代碼 

  第二步增加消息映射和函數(shù)聲明,,對(duì)于自定義消息不能由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()
并且在頭文件中添加函數(shù)聲明
// MainFrm.h
afx_msg LRESULT OnNotify(WPARAM WParam, LPARAM LParam); 

  第三步增加消息處理函數(shù)定義


LRESULT CMainFrame::OnNotify(WPARAM WParam, LPARAM LParam)
{
return trayicon.OnNotify(WParam, LParam);//調(diào)用CTrayIcon類的處理函數(shù)


  

如何隱藏任務(wù)欄上的按鈕

  可以使用下列兩種方法:

  1.在CreateWindowEx函數(shù)中使用WS_EX_TOOLWINDOW窗口式樣(相反的如果要確保應(yīng)用程序在任務(wù)欄上生成按鈕,,可以使用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.生成一個(gè)空的隱藏的top-level窗口,,并使其作為可視窗口的父窗口,。

  3.在應(yīng)用程序的InitInstance()函數(shù)中使用SW_HIDE式樣調(diào)用ShowWindow()函數(shù)。


//pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->ShowWindow(SW_HIDE);
pMainFrame->UpdateWindow(); 

  

如何動(dòng)畫任務(wù)欄上的圖標(biāo)

  在TrayIcon類中加入下列兩個(gè)函數(shù):

BOOL CTrayIcon::SetAnimateIcons(HICON* hIcon, UINT Number)
{//設(shè)置動(dòng)畫圖標(biāo)
 ASSERT(Number >= 2);//圖標(biāo)必須為兩個(gè)以上
 ASSERT(hIcon);//圖標(biāo)必須不為空

 m_AnimateIcons = new HICON[Number];
 CopyMemory(m_AnimateIcons, hIcon, Number * sizeof(HICON));
 m_AnimateIconsNumber = Number;
 return TRUE;
}

BOOL CTrayIcon::Animate(UINT Index)
{//動(dòng)畫TrayIcon
 UINT i = Index % m_AnimateIconsNumber;
 return ChangeIcon(m_AnimateIcons[i]);
}
 

怎樣在應(yīng)用程序中添加相應(yīng)的菜單和函數(shù)

void CMainFrame::OnMenuAnimate()
{//動(dòng)畫TrayIcon,設(shè)置圖標(biāo)及定時(shí)器
 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)
{//動(dòng)畫TrayIcon
 UINT static i;
 i += 1;
 trayicon.Animate(i);

 CMDIFrameWnd::OnTimer(nIDEvent);
}
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多