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;
}
运行效果对比: