根据:http://msdn.microsoft.com/en-us/library/windows/desktop/bb762102(v=vs.85).aspx
SetWindowSubclass 原型是:
BOOL SetWindowSubclass(
__in HWND hWnd,
__in SUBCLASSPROC pfnSubclass,
__in UINT_PTR uIdSubclass,
__in DWORD_PTR dwRefData
);
好的,我明白了
hWnd
、pfnSubclass
和dwRefData
。
我找不到好的信息是,我将
uIdSubclass
设置为什么?
MSDN 说:
子类 ID。该 ID 与子类过程一起唯一标识 一个子类。要删除子类,请将子类过程和此值传递给 RemoveWindowSubclass 函数。该值被传递给子类过程 uId子类参数。
好的,明白了,但是,我从哪里得到这个 ID?它是我创造的还是我在某个地方得到的?如果它是我创造的东西,它应该是什么样子?
我在 C++ 和 Win32 API 中做这件事,没有别的。
谢谢。
Karl E. Peterson 在 Visual Studio Magazine 07/16/2009 中写到 uIdSubclass 参数的用途 Karl E. Peterson 文章中讨论的主题: 使用 uIdSubclass 存储一个 this 指针 [或 HWND]。
使用 dwRefData 传递可选数据,例如创建数据的指针。
关于我遇到的唯一未记录的警告是您必须确保在销毁窗口之前取消挂钩您的子类。如果您使用我的技术将处理程序嵌入在 Form_Unload 方法期间销毁的窗体或类中,这应该永远不会成为问题。如果你真的不想冒险,你可以在你的处理例程中插入一个简单的分支:
Select Case uiMsg
Case WM_THIS
'
Case WM_THAT
'
Case WM_NCDESTROY
Call Unhook ' !!!
End Select
Explorer Browser Search Sample也有一个使用 uIdSubclass 存储指向 this 的指针的示例。
void CExplorerBrowserSearchApp::_OnInitializeDialog()
{
...
// Register the searchbox icon to receive hover and mouseclick events
SetWindowSubclass(GetDlgItem(_hdlg, IDC_SEARCHIMG), s_SearchIconProc, (UINT_PTR)this, 0);
...
}
Raymond Chen 的博客“The Old New Thing”文章Safer subclassing
也提到了在 pfnSubclass 中处理 WM_NCDESTROY 以调用 RemoveWindowSubclass() 的重要性。引自Raymond Chen的文章文档中没有清楚解释的一个问题是,您必须在被子类化的窗口被销毁之前删除您的窗口子类。这通常是通过在您的临时需求过去后删除子类来完成的,或者如果您正在安装永久子类,则通过在子类过程本身中插入对 RemoveWindowSubclass 的调用来完成:
case WM_NCDESTROY:
RemoveWindowSubclass(hwnd, thisfunctionname, uIdSubclass);
return DefSubclassProc(...);
文档警告说 SetWindowSubclass() 仅限于每个线程。作为旁注,Microsoft
SetWindowSubclass
C++ 类,它对假设我们有
ListViewHelper
ListView
及其父类(对话框,以接收通知):
// constructor
ListViewHelper(HWND hwndListView)
{
SetWindowSubclass(hwndListView, listViewSubclassProc,
0, reinterpret_cast<DWORD_PTR>(this)));
SetWindowSubclass(GetParent(hwndListView), parentSubclassProc,
0, reinterpret_cast<DWORD_PTR>(this)));
}
在这种情况下,
uIdSubclass
不需要,可以是任何数字,通常是0。但是如果对话框包含两个ListView
控件怎么办?
ListViewHelper
的第二个实例将使用与第一个实例相同的参数调用 SetWindowSubclass()
,但
dwRefData
除外,因此
SetWindowSubclass()
不会子类化,而只会更改
dwRefData
。糟糕,
ListViewHelper
的第一个实例已停止工作。
在我们的例子中,我们需要提供一个不同的
uIdSubclass
,以使用相同的
pfnSubclass
子类化相同的窗口。您可以在 static unsigned int
类中定义
ListViewHelper
变量,并在每个
ListViewHelper
实例中递增它。但更简单、更合乎逻辑的方法是使用
hwndListView
:
SetWindowSubclass(GetParent(hwndListView), parentSubclassProc,
reinterpret_cast<UINT_PTR>(hwndListView), reinterpret_cast<DWORD_PTR>(this)));
我认为还有其他情况应该使用
uIdSubclass
。