如何?全螢幕顯示
全螢幕顯示是一些應用軟體程式必不可少的功能。比如在用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));
}