SetWindowLong的另一个用途是子类化一个窗口。本质上讲,窗口子类化是使应用程序从先前存在的窗口类派生出新窗口类的一个实例。子类化的典型应用是修改窗口控件的行为,例如一个Edit控件。
子类化的过程实际上是很简单的。先创建一个窗口过程来为被子类化的窗口提供新功能,再用基础窗口类创建一个窗口。然后为该窗口调用GetWindowLong来获得并保存一个指向其初始窗口过程的指针,之后调用SetWindowLong函数,将窗口实例的窗口过程设置成新的窗口过程。这样,新的窗口过程就开始接收发给该窗口的消息了。任何没有被新窗口过程响应的消息都通过调用CallWindowProc传递给到旧的窗口过程。下面的代码展示了窗口创建及被子类化的过程。子类化窗口过程截获了WM_LBUTTONDOWN消息,并且在窗口收到该消息时使扬声器发出声音。
-
- LRESULT CALLBACK SCWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
-
-
- WNDPROC lpfnOldProc = 0;
-
-
-
- BOOL SubClassThisWnd (HWND hwndSC) {
- if (lpfnOldProc == 0) {
-
- lpfnOldProc = (WNDPROC)GetWindowLong (hwndSC, GWL_WNDPROC);
-
- return SetWindowLong (hwndSC, GWL_WNDPROC, (DWORD)SCWndProc);
- }
- return FALSE;
- }
-
-
-
- LRESULT CALLBACK SCWndProc(HWND hWnd, UINT wMsg, WPARAM wParam,LPARAM lParam) {
- switch (wMsg) {
- case WM_LBUTTONDOWN:
- MessageBeep(0);
- break;
- }
- return CallWindowProc (lpfnOldProc, hWnd, wMsg, wParam, lParam);
- }
要去除窗口的子类化,只要调用SetWindowLong,把WndProc指针设置回最初的窗口过程即可。
(jacky) |