分类: C/C++
2006-04-25 23:48:24
int PropertySheet(
LPCPROPSHEETHEADER lppsph );
此API创建属性表,如果lppsph指针指向的PROPSHEETHEADER结构的dwFlags包含PSH_CALLBACK风格,则会调用回调函数,在pfnCallback变量中定义.
在此函数中修改窗口风格即可.代码中此函数是PropSheetCallback.
偶现在发现,类并没有减少复杂性,而是封装了复杂性.一次复杂,以后用起来方便说起来还是值得的.
下面是对代码的分析:
CPropView类是封装的属性表操作.在主窗口的OnCreate函数中调用
CPropView::Create(HWND hParent);
在此方法中已经调用了PropertySheet()函数,上面所说的修改风格在Create返回后已经完成了.返回后一个完整的属性表已经创建完成.
当然一个属性表需要一个以上的属性页,必须先建立属性页.看下面.
CPropView类有相关的成员变量:
CPropPagem_page0;
看名字可看出是属性页类.简单说下.IDD_PAGE0是资源ID,类型是对话框.IDC_EDIT0是对话框上的控件ID,可以有多个,这里只一个.
这里显示出属性页的特点了:每个页其实是一个对话框窗口.要先添加新的页,先在资源编辑器里建立对话框.
其实属性表也是一对话框窗口,有按钮,图标什么的.不过是特制的.当添加新页时会给我们加上标签.
理解了这些.就可以填充相关结构,然后一个API就可以完成我们想要的操作.呵呵,看看结构的长度就知道多麻烦了.还是用WTL类吧.
为了紧凑,下面一段代码在这儿列出来而没在Create处写:
template
BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd)
{
ATLASSERT(m_hWnd == NULL);
ATLASSERT(::IsWindow(hWnd));
m_thunk.Init(GetWindowProc(), this); //这里也很关键,具体看thunk机制
WNDPROC pProc = (WNDPROC)&(m_thunk.thunk);
WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
if(pfnWndProc == NULL)
return FALSE;
m_pfnSuperWindowProc = pfnWndProc;
m_hWnd = hWnd; //这里保存窗口句柄给成员变量,偶找了半天.
return TRUE;
}
这是因为PropertySheet最终会调用回调函数:
WTL.CPropertySheetImpl.PropSheetCallback
而它又会调用:
pT->SubclassWindow(hWnd);
这个pT是模板类生成,所以是不确定类型的.但如果不重载,会调用:
CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd)
这也就是上面的代码.
偶是边用边写.发现模板技术在WTL里无处不在啊.模板感觉有些不按常理,但竟出现了STL这样的天才库.嘿嘿.高人无处不在.