詳解CREATESTRUCT結構體

CREATESTRUCT結構定義了傳遞給應用程序的窗口過程的初始化參數,它定義了窗口外觀相關特性,CREATESTRUCT結構具有如下形式:


typedef struct tagCREATESTRUCT
{
  LPVOID  lpCreateParams;  //指向將被用於創建窗口的數據的指針。  
  HANDLE  hInstance;       //標識了擁有新窗口的模塊的模塊實例的句柄。  
  HMENU   hMenu;           //標識了要被用於新窗口的菜單。如果是子窗口,則包含整數ID。  
  HWND    hwndParent;      //標識了擁有新窗口的窗口。如果新窗口是一個頂層窗口,這個參數可以爲NULL。  
  int     cy;              //指定了新窗口的高。  
  int     cx;              //指定了新窗口的寬。  
  int     y;               //指定了新窗口的左上角的y軸座標。  
  int     x;               //指定了新窗口的左上角的x軸座標。 
  LONG    style;           //指定了新窗口的風格。  
  LPCSTR  lpszName;        //指向一個以null結尾的字符串,指定了新窗口的名字。  
  LPCSTR  lpszClass;       //指向一個以null結尾的字符串,指定了新窗口的Windows類名
  DWORD   dwExStyle;       //指定了新窗口的擴展風格。  
} CREATESTRUCT;


在MFC中我們利用MFC嚮導就可以創建一個單文檔和多文檔APP,這裏主要用單文檔應用程序舉例。MFC封裝了Win32 API使得我們窗口的創建更加簡單,利用APP Wizard可以生成具有默認屬性的窗口程序。如果我們需要修改應用程序的默認屬性,可以調用PreCreateWindow函數和SetWindowLong函數就行自定義,下面分別介紹之。


PreCreateWindow函數


PreCreateWindow函數從字面上看,就知道它是創建窗口有關係,它是在窗口創建之前進行外觀修改,通過重載該函數,可以修改CREATESTRUCT結構,從而加入用戶自定義的屬性,其函數聲明如下:


virtual BOOL PreCreateWindow( CREATESTRUCT& cs );
在SDI程序CMainFrame類中,一般都會自帶該函數的實現,代碼如下:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    // TODO: 在此處通過修改
    //  CREATESTRUCT cs 來修改窗口類或樣式
 
    return TRUE;
}

由於該函數是虛函數,因此MFC底層代碼創創建窗口之前,先會調用該函數,從而實現默認屬性修改,這裏我們修改寬度和高度,增加水平和垂直的滾動條,以及刪除可調邊框屬性。
例子1 修改外觀


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    // TODO: 在此處通過修改
    //  CREATESTRUCT cs 來修改窗口類或樣式
    //改變大小
    cs.cx = 500; 
    cs.cy = 400;
    //增加水平和垂直滾動條
    cs.style |= WS_HSCROLL | WS_VSCROLL;
    //去除可調邊框屬性
    cs.style &= ~WS_THICKFRAME ;
 
    return TRUE;
}
運行效果對比:

例子2:修改窗口標題

     在默認的單文檔和多文檔應用程序中,框架窗口stytle風格都包含有FWS_ADDTOTITLE這個屬性,其含義是將文檔的標題做爲窗口的標題,如果需要自定義窗口標題,需要將這個屬性刪除,具體代碼如下:


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    //  CREATESTRUCT cs 來修改窗口類或樣式
    //改變大小
    cs.cx = 400; 
    cs.cy = 300;
    //增加水平和垂直滾動條
    cs.style |= WS_HSCROLL | WS_VSCROLL;
    //去除FWS_ADDTOTITLE屬性
    cs.style &= ~FWS_ADDTOTITLE ;
    //自定義標題
    cs.lpszName = "HelloWorld";
 
    return TRUE;
}
運行效果:

SetWindowLong函數

上面介紹的PreCreateWindow函數是在創建之前進行修改的,而SetWinowLong函數是在窗口創建之後進行修改的。

我們在發現框架類(CMainFrame)中有個OnCreate函數,該函數的功能是完成窗口的創建,其部分代碼如下:


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;
    ...
 
    // TODO: 如果不需要可停靠工具欄,則刪除這三行
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);
 
    return 0;
}


我們發現該函數調用了基類的OnCreate()函數,就是這個函數完成了窗口的創建,我們可以在該函數返回前調用SetWindowLong完成指定窗口的屬性修改,該函數聲明如下:

LONG SetWindowLong(HWND hWnd,int nlndex,LONG dwNewLong)
hWnd:窗口句柄及間接給出的窗口所屬的類。
nlndex:指定將設定的大於等於0的偏移值。要設置其他任何值,可以指定下面值之一:
    GWL_EXISTYLE:設定一個新的擴展風格。
    GWL_STYLE:設定一個新的窗口風格。
    GWL_WNDPROC:爲窗口過程設定一個新的地址。GWL_ID:設置一個新的窗口標識符。
     ....
dwNewLong:指定的替換值。

對應的,MFC提供了GetWindowLong函數來獲取指定窗口的信息,其函數聲明如下:


LONG GetWindowLong(HWND hWnd,int nlndex)
該函數的返回值就是窗口的信息,nIndex指定了要獲取的內容,這個爲GWL_STYLE,意爲獲得窗口風格,修改風格的具體代碼如下:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;
    ...
 
    // TODO: 如果不需要可停靠工具欄,則刪除這三行
    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);
    SetWindowLong(m_hWnd, 
                  GWL_STYLE, //獲取風格
                  GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);//修改風格 去除最大化屬性。
    return 0;
}
運行效果對比:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章