http://blog.csdn.net/strategycn/article/details/6428851
在窗口创建之前完成之前改变窗口属性
MFC中通过重写PreCreateWindow() 虚函数改变AppWizard生成的窗口的默认属性
①通过改变PreCreateWindow()函数的CREATSTRUCT来改变。
typedef struct tagCREATESTRUCT { LPVOID lpCreateParams; HANDLE hInstance; //实例 HMENU hMenu; //窗口菜单 HWND hwndParent; //父窗口 int cy; //窗口宽度 int cx; //窗口高度 int y; //窗口左上角y坐标 int x; //窗口左上角x坐标 LONG style; //窗口类型(初始最大/小化、 有无最大/小化按钮、边框、重叠窗口等等) LPCSTR lpszName; //窗口标题名(受style影响,如果style有FWS_ADDTOTITLE这一属性就不能自己设置) LPCSTR lpszClass; //窗口类 WNDCLASS ,可以通过自定义窗口类来改变窗口光标、图标、背景颜色,但是对于SDI单文档程序来说,Frame类上覆盖一个View类,因此在Frame类的PreCreateWindow()函数中改变了窗口类中改变了光标和背景以后,看起来只改变了图标而没有改变光标和背景颜色,这是因为:View类在前,显示的是View类的光标和背景,根据实际需要改变View类的光标和背景颜色即可,由于该窗口类已创建,在View类的PreCreateWindow()函数中给CREATESTRUCT结构体的lpszClass赋值为已注册的新建窗口类即可。 DWORD dwExStyle; //扩展窗口类型 } CREATESTRUCT;
NOTE:通过改变CREATSTRUCT结构体中的 lpszName来改变窗口的标题,结果发现没有变,原因是缺省的窗口类型是WS_OVERLAPPEDWINDOW 和FWS_ADDTOTITLE联合。 而FWS_ADDTOTITLE是用来通知框架用文档的标题当作窗口的标题,如果要修改窗口标题我们就要去掉这个属性。
so:
cs.style = cs.style & ~FWS_ADDTOTITLE; 或者
cs.style &= ~FWS_ADDTOTITLE; 也可以直接对style赋值:
cs.style = WS_OVERLAPPEDWINDOW;
更多欢笑更多惊喜更多style可用的值(Available styles)见MSDN CWnd::PreCreateWindow
NOTE:窗口类只是窗口的一部分,完整的窗口修改就是修改CREATSTRUCT结构体,该结构体包括窗口对应的窗口类(通过指定类名来修改窗口对应的窗口类)。
②一个具体的例子(方法1:新建窗口类)
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; cs.cx = 800; //宽度 cs.cy = 600; //高度 cs.style = cs.style & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX & ~FWS_ADDTOTITLE; cs.lpszName = "我的程序"; // new WNDCLASS WNDCLASS wndcls; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); wndcls.hCursor = LoadCursor(NULL, IDC_CROSS); wndcls.hInstance = AfxGetInstanceHandle(); //取得当前应用 程序的句柄 TRACE("Application instance handle1 is 0x%0X/n", AfxGetInstanceHandle()); //调试输出 //wndcls.hInstance = (HINSTANCE) GetWindowLong(m_hWnd, GWL_HINSTANCE);//尝试这样得到应用程序句柄,结果发现虽然不报错,但是结合下面取得窗口过程出错我认为:此时窗口还没有创建完成,也就取不到该窗口对应的程序实例句柄。 TRACE("Application instance handle2 is 0x%0X/n", GetWindowLong(m_hWnd, GWL_HINSTANCE)); //调试发现和上面取得的应用程序句柄不一样。 //wndcls.lpfnWndProc = (WNDPROC)GetWindowLong(m_hWnd, GWL_WNDPROC); //尝试这样取得窗口过程,报错“空文档建立失败”, 所以认为:在PreCreateWindow()中窗口建成,所以只能用SetWindowLong()之类Set函数 wndcls.lpfnWndProc = ::DefWindowProc; //缺省窗口过程(见:设计窗口类时设计窗口过程函数的完成代码)。 wndcls.lpszClassName = "cuihaoWndClass"; wndcls.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME); wndcls.style = CS_HREDRAW | CS_VREDRAW; wndcls.hIcon = LoadIcon(NULL, IDI_WARNING); RegisterClass(&wndcls); cs.lpszClass = "cuihaoWndClass"; return TRUE; }
BOOL CMy44View::PreCreateWindow(CREATESTRUCT& cs) { cs.lpszClass = "cuihaoWndClass"; //这样即可,因为 cuihaoWndClass类已经注册 return CView::PreCreateWindow(cs); }
③一个具体例子(方法2 :快速创建窗口类)
AfxRegisterWndClass 该函数快速注册一个窗口类,参数仅有:类样式,光标,背景色,图标。返回一个窗口类的类名
LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor=0, HBRUSHhbr Background=0, HICON hIcon=0 );
eg.
CString strClass = ""; //用来保存类名,全局变量,以便在View类中为CREATESTRUCT结构体制定 // lpszClass = strClass; BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; cs.cx = 800; cs.cy = 600; cs.style = cs.style & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX & ~FWS_ADDTOTITLE; cs.lpszName = "我的程序"; strClass = cs.lpszClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, LoadCursor(NULL, IDC_CROSS), (HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(NULL, IDI_WINLOGO)); return TRUE; }
BOOL CMy44View::PreCreateWindow(CREATESTRUCT& cs) { extern CString strClass; //声明在其他源文件中定义的全局变量 cs.lpszClass = strClass; //指定类名 OK return CView::PreCreateWindow(cs); }
3 窗口生成以后再改变窗口属性
在窗口OnCreate()函数中coding
①LONG SetWindowLong
LONG SetWindowLong( HWND hWnd, //窗口句柄,所有从CWnd类继承来的类都有一个m_hWnd成员变量标识 int nIndex, //要设置的值的基于0 的偏移量或者下列值 LONG dwNewLong //根据nIndex的值而设定的新值 );
nIndex:
GWL_EXSTYLE | Sets a new extended window style. For more information, seeCreateWindowEx. |
GWL_STYLE | 窗口类型 见MSDN: window style. |
GWL_WNDPROC | 窗口过程函数 |
GWL_HINSTANCE | 应用程序实例句柄 |
GWL_ID | Sets a new identifier of the window. |
GWL_USERDATA | Sets the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero. |
如果hWnd是一个对话框的时候用下面的值
DWL_DLGPROC | Sets the new address of the dialog box procedure. |
DWL_MSGRESULT | Sets the return value of a message processed in the dialog box procedure. |
DWL_USER | Sets new extra information that is private to the application, such as handles or pointers. |
LONG GetWindowLong( HWND hWnd, // handle to window int nIndex // offset of value to retrieve );
NOTE:至少在窗口创建完成后才能调用这个函数
③SetClassLong
DWORD SetClassLong( HWND hWnd, // handle to window int nIndex, // index of value to change LONG dwNewLong // new value );
④GetClassLong
DWORD GetClassLong( HWND hWnd, // handle to window int nIndex // offset of value to retrieve );
4 总结:
在窗口创建之前在PreCreateWindow()函数中用AfxRegisterWndClass创建窗口类
在窗口创建完后在OnCreat()函数中用 SetWindowLong() SetClassLong()
SetWindowLong()设置窗口属性, SetClassLong()设置窗口类属性
GetWindowLong()取得窗口属性, GetClassLong()取得窗口类属性