七. 介面編程--Windows編程課程學習筆記

來源:互聯網
上載者:User

標籤:

7.1更改視窗大小、標題、風格7.1.1 在視窗建立之前更改

如果希望在應用程式視窗建立之前修改它的大小、標題和風格,應該在CMainFrame類的PreCreateWindow成員函數進行。該函數有個類型是CREATESTRUCT結構的參數,如果在修改了這個參數中的成員變數的值,那麼這種改變會反映到MFC底層代碼中,當MFC底層代碼調用CreateWindowEx函數去建立視窗時,它就會使用改變後的參數值去建立這個視窗。

1)更改視窗大小

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs){    if( !CFrameWnd::PreCreateWindow(cs) )        return FALSE;    //TODO: 在此處通過修改    //  CREATESTRUCT cs 來修改視窗類別或樣式    cs.cx = 400;    cs.cy = 200;    return TRUE;}

2)更改應用程式標題

    架構的預設視窗樣式是WS_OVERLAPPEDWINDOW和FWS_ADDTOTITLE樣式的組合。其中FWS_ADDTOTITLE是MFC特定的一種樣式,指示架構將文檔標題添加到視窗標題上。因此,如果想讓視窗顯示自己的標題,只需將視窗的FWS_ADDTOTITLE樣式去掉即可。設定視窗標題的代碼之前加上:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs){    if( !CFrameWnd::PreCreateWindow(cs) )        return FALSE;    //TODO: 在此處通過修改    //  CREATESTRUCT cs 來修改視窗類別或樣式    cs.cx = 400;    cs.cy = 200;     cs.style = cs.style & ~FWS_ADDTOTITLE;//  cs.style = WS_OVERLAPPEDWINDOW;     cs.lpszName = "標題";    return TRUE;}
7.1.2在視窗建立之後更改其風格

在應用程式視窗建立之後修改它的風格屬性,可在CMainFrame類的OnCreate函數中調用SetWindowLong函數實現。

SetWindowLong(HWND hWnd, int nIndex, LONGdwNewLong)

該函數的作用是改變制定視窗的屬性(包括設定新的視窗風格、設定新的視窗過程、設定新的應用程式執行個體局柄等)。要改變視窗的風格,則將該函數的第二個參數指定為GWL_STYLE,然後由第三個參數指定新的視窗風格。

如果是在已有類型的基礎上進行修改的話,那麼可以利用GetWindowLong這個函數獲得這個視窗的現有類型,然後修改。例如:

    SetWindowLong(m_hWnd, GWL_STYLE, GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);
7.1.3 在視窗建立之後更改標題與大小

在應用程式視窗建立之後修改標題,可在CMainFrame類的OnCreate函數中調用SetWindowText函數實現。

在應用程式視窗建立之後修改大小,可在CMainFrame類的OnCreate函數中調用SetWindowPos函數實現。

7.2 修改游標、表徵圖、背景7.2.3 在視窗建立前更改

之前對於視窗的大小、標題和風格是在建立視窗時設定的。而游標、表徵圖和背景是在設計視窗類別時指定的。視窗類別的設計與註冊是由MFC底層代碼自動完成的,我們不可能、也不應該去修改MFC底層代碼。但是我們可以編寫自己的視窗類別註冊,然後讓隨後的視窗按照我們編寫的視窗類別去建立。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs){    if( !CFrameWnd::PreCreateWindow(cs) )        return FALSE;    …WNDCLASSMyWnd;    MyWnd.cbClsExtra = NULL;MyWnd.cbWndExtra = NULL;    MyWnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);    MyWnd.hCursor = LoadCursor(NULL, IDC_CROSS);    MyWnd.hIcon = LoadIcon(NULL, IDI_WARNING);    MyWnd.hInstance = AfxGetInstanceHandle();    MyWnd.lpfnWndProc = ::DefWindowProc;    MyWnd.lpszClassName = "Hello";    MyWnd.lpszMenuName = NULL;    MyWnd.style = CS_HREDRAW | CS_VREDRAW;    RegisterClass(&MyWnd);    cs.lpszClass = "hello";return TRUE;}

     上述代碼的運行結果是:僅僅是程式的標題列表徵圖發生了改變,但視窗的背景和游標沒有改變。原因是:視類視窗覆蓋在主視窗上面,我們看到的視窗實際上是視類視窗,而上述代碼修改的是架構類視窗的背景和游標。應用程式的表徵圖屬於架構視窗,因此上述程式運行後,表徵圖發生了改變。    

結論:在MFC中,如果要修改應用程式視窗的表徵圖,則應該架構類中進行,因為架構視窗才有標題列;如果要修改程式視窗的背景和游標,則應該在視類中進行。解決方案:在視類的PreCreateWindow函數中添加代碼:   cs.lpszClass="hello";。

同時MFC為我們提供了一個全域函數AfxRegisterWndClass()。

LPCTSTR AFXAPI AfxRegisterWndClass(UINTnClassStyle, HCRSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0);

7.2.2 在視窗建立之後更改

要在應用程式視窗建立之後修改它的游標、表徵圖和背景,可在OnCreate函數中調用SetClassLong函數實現。DWORD SetClassLong(HWNDhWnd, int nIndex, LONG dwNewLong)

該函數的作用是:重新設定指定視窗所屬視窗類別的WNDCLASS結構體中指定資料成員的屬性(包括設定新的視窗背景畫刷、游標、表徵圖和視窗類別樣式)。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)        return -1;    …SetClassLong(m_hWnd,GCL_HICON, (LONG)LoadIcon(NULL, IDI_WARNING));    return 0;}  int CMyMFCAppView::OnCreate(LPCREATESTRUCT lpCreateStruct){    if (CView::OnCreate(lpCreateStruct) == -1)        return -1;       …    //7.2.2 在視窗建立之後更改游標、標題列表徵圖、視窗背景    SetClassLong(m_hWnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(BLACK_BRUSH));    SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_CROSS));    return 0;}
7.3 類比動畫表徵圖7.3.1 載入表徵圖資源

添加IDI_ICON1-4資源,氣候在架構類定義一個表徵圖控制代碼成員變數,添加數組時,類型設定為HICON [4]方能設定成功。在視類添加一下代碼。

    m_hIcons[0] = ::LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));    m_hIcons[1] = ::LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));    m_hIcons[2] = ::LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));    m_hIcons[3] = AfxGetApp()->LoadIcon(IDI_ICON4);

其中LoadIcon第一個參數,載入第一幅時,AfxGetInstanceHandle可以擷取應用程式當前控制代碼。第二個參數,通過MAKEINTRESOURSE宏將ID轉換為相應的資源表示符字串。第二幅應用theApp的擷取應用程式的CWinApp對象,其資料成員m_hInstance得到執行個體控制代碼。但是App檔案中已經定義了一個theApp全域變數,所以在架構類OnCreate函數前extern CMyMFCApp theApp。第三幅載入,用AfxGetApp全域函數實現。

7.3.2設定定時器

在架構類OnCreate函數添加SetTime函數,沒1000ms觸發一次定時器訊息。

    SetTimer(1, 1000, NULL);

在架構類添加定時器訊息(WM_TIMER)的響應函數,並在響應函數調用SetClassLong函數改變應用程式視窗表徵圖。

void CMainFrame::OnTimer(UINT_PTR nIDEvent){    //TODO: 在此添加訊息處理常式代碼和/或調用預設值    static int index = 1;    SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[index]);    index = ++index % 4;    CFrameWnd::OnTimer(nIDEvent);    CFrameWnd::OnTimer(nIDEvent);}

因為程式每次發送定時器訊息都會調用OnTimer函數,所以把index定義為靜態(分配在棧中)。

7.4工具列編程7.4.1 在工具列添加按鈕

在資源的toolbar中在IDR_MAINFRAME的最右邊添加一個按鈕IDM_TEST。並在功能表列【協助】下添加一個同ID的按鈕,Caption設定為Test。添加一個命令響應函數OnTestShow。可以將T按鈕享有拖動一點,此時協助與T按鈕有一定空隙。想要刪除只需del。

void CMainFrame::OnTestShow(){    //TODO: 在此添加命令處理常式代碼    MessageBox("Teston toolbar");}

7.4.2建立工具列——4個步驟

Step1:建立工具列資源;

Step2:構造CToolBar對象;主架構添加私人變數

Step3:調用Create或CreateEx函數建立Window工具列(工具列也是視窗)

Step4:調用LoadToolBar函數載入工具列資源。

7.4.3 建立自訂工具列

在TOOLBAR添加新資源,在架構類加加一個CToolBar類型的成員變數,調用create函數建立工具列,與CToolBar相關聯,可以在架構類的OnCreate函數實現。添加一下代碼。

 <span style="white-space:pre"></span>if (!m_newToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP        | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||        !m_newToolBar.LoadToolBar(IDR_TOOLBAR1))    {        TRACE0("Failed to create toolbar\n");        return-1;      // fail to create    }    m_newToolBar.EnableDocking(CBRS_ALIGN_ANY);    DockControlBar(&m_newToolBar);

CreateEx函數建立工具列,並與工具列對象:m_newToolBar關聯,固定位置設定為CBRS_RIGHT。調用LoadToolBar載入資源。調用EnableDocking函數允許工具列停靠客戶區任意位置。最後調用DockControlBar函數,讓工具列停靠在主架構視窗上。

7.4.4 顯示和隱藏工具列

在【視圖】自此阿達您下載添加一個功能表項目。ID屬性為IDM_VIEW_NEWTOOLBAR,Caption為“新的工具列”。接著添加命令響應函數。在響應函數中,實現先前建立的工具列的顯示與隱藏。可以調用ShowWindow函數。之後需要調整他們的位置,調用RecalcLayout函數。限制或隱藏後再次調用架構類DockControlBar函數。讓工具列停靠在主架構視窗上,使用DockControlBar函數。

void CMainFrame::OnViewNewtoolbar(){    //TODO: 在此添加命令處理常式代碼    if (m_newToolBar.IsWindowVisible())        m_newToolBar.ShowWindow(SW_HIDE);    else        m_newToolBar.ShowWindow(SW_SHOW);    RecalcLayout();    DockControlBar(&m_newToolBar);}

如何讓建立的工具列舍在原先顯示位置顯示。需要調用ShowControlBar函數。

下面,添加複選編輯。為此為功能表項目添加一個UPDATE_COMMAND_UI函數。內部添加代碼。

void CMainFrame::OnUpdateViewNewtoolbar(CCmdUI *pCmdUI){    //TODO: 在此添加命令更新使用者介面處理常式代碼    // 添加複選框    pCmdUI->SetCheck(m_newToolBar.IsWindowVisible());}
7.5 狀態列編程7.5.1 狀態列的提示行與指標

狀態列分為兩部分:提示行與指標。左邊最長的部分為提示行,通常用於顯示功能表項目或工具按鈕的提示資訊。右邊由若干窗格組成的部分為狀態列指標,通常用來顯示大小寫鍵、數字鎖定鍵等資訊。

架構程式專門提供了一個indicators數組來管理提示行與指標。如果要修改狀態列的外觀,則只需在indicators數組中添加或減少相應的字串資源ID即可。

① 在資源編輯器中新增字串資源ID:

      ID_TIMER                          時鐘

② 將新的字串資源ID添加到indicators數組中

③ 擷取系統目前時間(加在CMainFrame的OnCreate函數的後部)

    CTime t = CTime::GetCurrentTime();    CString str = t.Format("%H:%M:%S");

④ 將字串顯示到狀態列的窗格上,調用CStatusBar類的成員函數SetPaneText。如果不知道窗格的索引,可以調用CStatusBar類的成員函數CommandToIndex獲得。m_wndStatusBar.CommandToIndex(ID_TIMER)

    m_wndStatusBar.SetPaneText(1, str);
⑤ 調整窗格大小

CStatusBar類的成員函數:SetPaneInfo,該函數可以為指定的窗格設定新的ID、樣式和寬度。

    CClientDC dc(this);    CSize sz = dc.GetTextExtent(str);    m_wndStatusBar.SetPaneInfo(1, ID_TIMER, SBPS_NORMAL,sz.cx);

⑥ 在OnTimer中添加相關代碼。

7.6 在狀態列中添加滑鼠座標顯示

方法一:調用SetWindowText函數設定狀態列提示行文本

需添加標頭檔並把m_wndStatusBar改為公有

    CString str;    str.Format("x=%d, y=%d", point.x, point.y);    ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str);

方法二:利用CFrameWnd類的成員函數SetMessageText實現,該函數的作用是在狀態列的提示行中設定文本。

    ((CMainFrame*)GetParent())->SetMessageText(str);

方法三:利用CFrameWnd類的成員函數GetMessageBar可以返回狀態列對象的指標,這樣也不用再訪問CMainFrame類的保護成員變數:m_wndStatusBar。

    ((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(str);

在提示行中顯位元影像(藉助位元影像按鈕的方法)

在架構類添加CBitmapButton m_bmp變數。

    CRect rc(100, 4, 120, 20);    if (!m_bmp.Create("", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, rc, &m_wndStatusBar, 0))        return FALSE;    if (!m_bmp.LoadBitmaps(IDB_BITMAP1, NULL, NULL, NULL))        return FALSE;

7.7添加啟動介面7.7.1 利用VC++組件庫中提供的類完成

單擊[Project \ Add to Project \Components and controls…],在彈出的組件和控制項陳列庫對話方塊中雙擊“Visual C++ Components”目錄,在該目錄下找到Splashscreen組件。

替換splsh.bmp位元影像檔案可替換啟動介面;

更改SetTimer(1, 2000, NULL)可設定啟動畫面的停留時間。

7.7.2 VS添加啟動畫面

1)建立一個ID_BITMAP3的位元影像資源。

2)現在項目下建立一個類CSplashWnd,基類為CWnd;

3)在該類下添加一個protected型的變數CBitmap m_bitmap

4)添加一個Create函數載入位元影像,建立視窗;

public:    BOOL Create(); BOOL CSplashWnd::Create(){    if (!m_bitmap.LoadBitmap(IDB_BITMAP3))        return false;    BITMAP bm;    m_bitmap.GetBitmap(&bm);    return CreateEx(0, AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW)),        NULL, WS_POPUP | WS_VISIBLE, 0,0, bm.bmWidth, bm.bmHeight, NULL, NULL);}

5)顯示視窗發送WM_PAINT訊息,映射此訊息;

void CSplashWnd::OnPaint(){CPaintDC dc(this); // device context for painting   // TODO: 在此處添加訊息處理常式代碼   // 不為繪圖訊息調用 CWnd::OnPaint()CDC dcimage;if (!dcimage.CreateCompatibleDC(&dc)) return;BITMAP bm;m_bitmap.GetBitmap(&bm);CBitmap* pOldBitmap = dcimage.SelectObject(&m_bitmap);dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcimage, 0, 0, SRCCOPY);dcimage.SelectObject(pOldBitmap);}

6)在App類中包含新類的標頭檔後,在InitInstance()函數中添加以下代碼:

    CSplashWnd *pSplashWindow = new CSplashWnd;//建立對象    pSplashWindow->Create();    pSplashWindow->CenterWindow();    pSplashWindow->ShowWindow(SW_SHOW);  //顯示視窗    pSplashWindow->UpdateWindow();    Sleep(2000); //表示啟動畫面期間    pSplashWindow->DestroyWindow(); //銷毀啟動畫面    delete pSplashWindow; //刪除

 

七. 介面編程--Windows編程課程學習筆記

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.