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;
}
運行效果對比: